Skip to content

Commit

Permalink
Add function overload support for Register events
Browse files Browse the repository at this point in the history
  • Loading branch information
Foereaper committed Nov 29, 2024
1 parent 931bdda commit f79289f
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Download the latest generated definitions from the build workflow action, altern
## Installation
1. **Install LuaLS**: Follow the [LuaLS installation instructions](https://luals.github.io/#vscode-install).
2. **Configure Your Workspace**: Point your workspace/LSP configuration to the location of the generated definitions.
3. **Enable parameter inference**: In the LuaLS configuration, enable Lua.type.inferParamType, this is required for callback parameters to function properly.

## Usage
1. Install Python 3, Pip, and dependencies:
Expand Down
106 changes: 98 additions & 8 deletions parser.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import os
import sys
import re
from bs4 import BeautifulSoup

debug = False

def extract_method_info(soup):
method_section = soup.find('h1')
class_name_tag = method_section.find_next()
Expand Down Expand Up @@ -105,6 +108,62 @@ def extract_argument_name_opt(argument_name):
argument_optional_value = optional_part
return argument_name, argument_optional, argument_optional_value

def extract_table(soup):
# Extract the header row
header = soup.find('thead')
if header is None:
return []

header_row = header.find_all('th')
if not header_row:
return []

# Extract the column names (keys) from the header
headers = [header.get_text(strip=True) for header in header_row]

# Find all the table rows, skipping the header
rows = soup.find_all('tr')[1:]
if not rows:
return []

row_list = []

for row in rows:
cells = row.find_all('td')
if not cells:
return []

# Ensure the row has the same number of columns as the header
if len(cells) != len(headers):
continue # Skip rows that don't match the header

cell_data = {}
for idx, cell in enumerate(cells):
# Check if the cell contains any <span> elements
if cell.find_all('span'):
cell_data[headers[idx]] = extract_parameters(cell)
else:
cell_data[headers[idx]] = cell.get_text(strip=True)

row_list.append(cell_data)

return row_list

def extract_parameters(cell):
parameters = {}

# Find all <span> tags in the 'cell'
spans = cell.find_all('span')

# Extract the 'title' as the key and text as the value
for span in spans:
title = span.get('title')
text = span.get_text(strip=True)
if title:
parameters[text] = title

return parameters

def extract_return_values(soup):
returns_section = soup.find('h2', id='returns')
if returns_section is None:
Expand Down Expand Up @@ -143,9 +202,9 @@ def extract_return_values(soup):
return_values_list.append({'type': return_type, 'name': return_name, 'description': return_description})
return return_values_list

def write_lua_stub(class_name, method_string, arguments_list, return_values_list, output_directory):
def write_lua_stub(class_name, method_string, arguments_list, table_list, return_values_list, output_directory):
with open(os.path.join(output_directory, class_name + ".lua"), "a") as lua_file:
# Write the parameter and return values
# Write the parameter definitions
for argument in arguments_list:
lua_file.write("---@param " + argument['name'])
if argument['optional']:
Expand All @@ -157,6 +216,27 @@ def write_lua_stub(class_name, method_string, arguments_list, return_values_list
lua_file.write(" Default value: (" + argument['optional_val'] + ")")

lua_file.write(" " + argument['description'] + "\n")

# Hard code table parsing for register events for now (function overload definitions)
if(class_name == "Global") and re.match(r"^Register\w+Event$", method_string):
for row in table_list:
# Only create function overloads for properly formatted parameter data
if 'Parameters' in row and isinstance(row['Parameters'], dict):
lua_file.write("---@overload fun(event: " + row['ID'] + ", func: fun(")

# Loop through parameters and check for 'event', we want to define this as the event ID and not a type
params = []
for key, value in row['Parameters'].items():
if key == 'event':
params.append(f'{key}: {row["ID"]}')
else:
params.append(f'{key}: {value}')

# Join the parameters and write to the file
lua_file.write(', '.join(params))
lua_file.write("), shots?: number): function\n")

# Write the return value definitions
for return_value in return_values_list:
lua_file.write("---@return " + return_value['type'] + " " + return_value['name'] + " " + return_value['description'] + "\n")

Expand All @@ -173,7 +253,9 @@ def write_lua_stub(class_name, method_string, arguments_list, return_values_list

lua_file.write(") end\n\n")

print(f"'{method_string}' stubs appended to '{class_name}.lua'")
global debug
if debug:
print(f"'{method_string}' stubs appended to '{class_name}.lua'")

def write_lua_class(class_name, inherited_objects, output_directory):
with open(os.path.join(output_directory, class_name + ".lua"), "w") as lua_file:
Expand All @@ -184,8 +266,10 @@ def write_lua_class(class_name, inherited_objects, output_directory):
lua_file.write(f": {', '.join(inherited_objects)}")

lua_file.write(f"\n{class_name} = {{}}\n\n")

print(f"'{class_name}' class information appended to '{class_name}.lua'")

global debug
if debug:
print(f"'{class_name}' class information appended to '{class_name}.lua'")

def process_html_file(html_file, filename, output_directory):
with open(html_file, "r") as f:
Expand All @@ -202,19 +286,25 @@ def process_html_file(html_file, filename, output_directory):
# Otherwise process like normal
class_name, method_string = extract_method_info(soup)
arguments_list = extract_arguments(soup)
table_list = extract_table(soup)
return_values_list = extract_return_values(soup)

write_lua_stub(class_name, method_string, arguments_list, return_values_list, output_directory)
write_lua_stub(class_name, method_string, arguments_list, table_list, return_values_list, output_directory)

def main():
# Check if command-line arguments are provided
if len(sys.argv) != 3:
print("Usage: python parser.py <html_input_directory> <output_directory>")
if len(sys.argv) < 3:
print("Usage: python parser.py <html_input_directory> <output_directory> <debug=false>")
sys.exit(1)

directory = sys.argv[1]
output_directory = sys.argv[2]

# Debug (Optional) - Default to false if not provided
if(sys.argv[3]):
global debug
debug = True if sys.argv[3].lower() == 'true' else False

# Special case to process our class definitions
html_file = os.path.join(directory, "index.html")
process_html_file(html_file, "index.html", output_directory)
Expand Down
10 changes: 6 additions & 4 deletions runParser.ps1
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
# Define the paths to the parser script and the parent directory containing Eluna API HTML files
$parserScriptPath = "C:\Path\To\parser.py"
$htmlParentDirectory = "C:\Path\To\ElunaLuaEngine.github.io-master"
$parserScriptPath = "C:\Users\foereaper\Desktop\luaLS\LuaLS-Eluna-Parser\parser.py"
$htmlParentDirectory = "C:\Users\foereaper\Desktop\tc\elunatrinitywotlk\src\server\game\LuaEngine\docs\build"

# Define the output directory for the LuaLS workspace
$outputDirectory = "C:\Path\To\LuaLS\Workspace"
$outputDirectory = "C:\Users\foereaper\Desktop\luaLS\LuaLS-Eluna-Parser\build"

$debug = $false

# Define the list of subdirectories to process
$subdirectories = @("Aura", "BattleGround", "Corpse", "Creature", "ElunaQuery", "GameObject", "Group", "Guild", "Global", "Item", "Map", "Object", "Player", "Quest", "Spell", "Unit", "Vehicle", "WorldObject", "WorldPacket")

# Iterate over each subdirectory
foreach ($subdir in $subdirectories) {
$htmlDirectory = Join-Path -Path $htmlParentDirectory -ChildPath $subdir
python $parserScriptPath $htmlDirectory $outputDirectory
python $parserScriptPath $htmlDirectory $outputDirectory $debug
}

0 comments on commit f79289f

Please sign in to comment.