#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 根据dl_lua_register.cpp文件生成Lua智能提示文件 """ import re import sys import os def parse_header_file(header_path): """ 解析头文件,提取Doxygen风格注释和函数类型信息 """ try: # Python 2 兼容的文件读取方式 with open(header_path, 'r') as f: content = f.read() except Exception as e: return {} # 提取注释块 comment_blocks = [] # 匹配 /** ... */ 风格的注释 pattern = re.compile(r'/\*\*[\s\S]*?\*/', re.MULTILINE) for match in pattern.finditer(content): comment = match.group(0) # 清理注释格式 comment = comment.replace('/**', '').replace('*/', '').strip() # 提取函数声明或类定义 # 查找注释后面的函数或类 start_pos = match.end() # 跳过空白字符 while start_pos < len(content) and content[start_pos].isspace(): start_pos += 1 # 提取函数或类定义的开始部分 end_pos = start_pos while end_pos < len(content) and content[end_pos] != ';' and content[end_pos] != '{': end_pos += 1 if end_pos > start_pos: declaration = content[start_pos:end_pos].strip() # 输出调试信息 if 'CreateText' in declaration: print('注释块:', comment) print('声明:', declaration) comment_blocks.append((declaration, comment)) # 构建注释字典 comments = {} for declaration, comment in comment_blocks: # 提取函数名 func_match = re.search(r'\b\w+\s+([\w:]+)\s*\(', declaration) if func_match: func_name = func_match.group(1) # 提取参数类型和名称 params = [] # 提取参数注释 param_comments = {} # 匹配 @param 注释(更灵活的模式,支持星号前缀和制表符) param_pattern = re.compile(r'\*?\s*@param\s*(?:\[(in|out|inout)\]\s*)?(\w+)\s+(.+)', re.MULTILINE) for param_match in param_pattern.finditer(comment): param_name = param_match.group(2) param_comment = param_match.group(3).strip() param_comments[param_name] = param_comment # 输出调试信息 if 'CreateText' in func_name: print('函数名:', func_name) print('参数注释:', param_comments) # 匹配括号内的参数列表 params_match = re.search(r'\(([^)]+)\)', declaration) if params_match: params_str = params_match.group(1) # 分割参数 param_list = re.split(r',\s*', params_str) # 用于存储已经处理过的参数名称,避免重复 processed_params = set() for param in param_list: # 处理默认参数值 param = param.split('=')[0].strip() param_parts = param.strip().split() if param_parts: # 类型是除了最后一个部分之外的所有部分 param_type = ' '.join(param_parts[:-1]) param_name = param_parts[-1] # 过滤掉不合法的参数名称(如常量) if not param_name.isdigit() and param_name not in ['true', 'false', 'null', 'nil'] and '::' not in param_name: # 检查参数是否已经处理过 if param_name not in processed_params: # 移除引用符号 param_type = param_type.replace('&', '').replace('*', '') # 简化类型名称 param_type = param_type.split('::')[-1] # 映射到 Lua 类型 lua_type = map_cpp_type_to_lua(param_type) # 获取参数注释 param_comment = param_comments.get(param_name, '') params.append((param_name, lua_type, param_comment)) processed_params.add(param_name) elif '::' in param_name: # 如果参数名称是常量,使用更有意义的参数名称 # 移除引用符号 param_type = param_type.replace('&', '').replace('*', '') # 简化类型名称 param_type = param_type.split('::')[-1] # 映射到 Lua 类型 lua_type = map_cpp_type_to_lua(param_type) # 使用类型名称作为参数名称 param_name = param_type.lower() # 检查参数是否已经处理过 if param_name not in processed_params: # 获取参数注释 param_comment = param_comments.get(param_name, '') params.append((param_name, lua_type, param_comment)) processed_params.add(param_name) # 提取返回值类型 return_type = '' return_match = re.search(r'^\s*([^\(]+)\s+[\w:]+\s*\(', declaration) if return_match: return_type = return_match.group(1).strip() # 移除引用符号 return_type = return_type.replace('&', '').replace('*', '') # 简化类型名称 return_type = return_type.split('::')[-1] # 映射到 Lua 类型 return_type = map_cpp_type_to_lua(return_type) # 处理命名空间 if '::' in func_name: # 提取命名空间和函数名 parts = func_name.split('::') if len(parts) > 1: ns = parts[-2] name = parts[-1] if ns not in comments: comments[ns] = {} comments[ns][name] = { 'comment': comment, 'params': params, 'return_type': return_type } else: comments[func_name] = { 'comment': comment, 'params': params, 'return_type': return_type } # 提取类名 class_match = re.search(r'class\s+(\w+)', declaration) if class_match: class_name = class_match.group(1) comments[class_name] = comment # 提取 constexpr 变量 constexpr_match = re.search(r'constexpr\s+[\w:]+\s+(\w+)\s*=\s*"(.+?)"', declaration) if constexpr_match: var_name = constexpr_match.group(1) var_value = constexpr_match.group(2) print('提取到 constexpr 变量:', var_name, '=', var_value) comments[var_name] = { 'comment': '', 'params': [], 'return_type': 'string', 'value': var_value } return comments def map_cpp_type_to_lua(cpp_type): """ 将 C++ 类型映射到 Lua 类型 """ # 基本类型映射 type_map = { 'void': 'nil', 'bool': 'boolean', 'char': 'string', 'int': 'number', 'float': 'number', 'double': 'number', 'std::string': 'string', 'string': 'string', 'std::string_view': 'string', 'string_view': 'string', 'std::vector': 'table', 'std::map': 'table', 'std::unordered_map': 'table', 'std::list': 'table', 'std::set': 'table', 'std::unordered_set': 'table', 'Position2': 'Position2', 'Size': 'Size', 'Color': 'Color', 'Image': 'Image', 'Graphics': 'Graphics', 'System': 'System', 'Panel': 'UIPanel', 'Text': 'UIText', 'Manager': 'UIManager', 'ParamWindow': 'ParamWindow', 'gcText': 'gcText', 'std::ifstream': 'userdata', 'std::ofstream': 'userdata', 'FILE': 'userdata', 'Buffer': 'userdata', 'BufferView': 'userdata', 'SearchRule': 'table', 'NTree': 'table', 'std::chrono::system_clock::time_point': 'userdata', 'time_t': 'number', 'uint8_t': 'number', 'uint16_t': 'number', 'uint32_t': 'number', 'uint64_t': 'number', 'int8_t': 'number', 'int16_t': 'number', 'int32_t': 'number', 'int64_t': 'number', 'size_t': 'number', 'std::nullptr_t': 'nil', 'std::unique_ptr': 'userdata', 'std::shared_ptr': 'userdata', 'std::weak_ptr': 'userdata', 'std::optional': 'any', 'std::variant': 'any', 'std::tuple': 'table', 'std::pair': 'table', 'std::function': 'function', 'std::regex': 'userdata', 'std::smatch': 'userdata', 'std::istream': 'userdata', 'std::ostream': 'userdata', 'std::iostream': 'userdata', 'std::fstream': 'userdata', 'std::stringstream': 'userdata', 'std::istringstream': 'userdata', 'std::ostringstream': 'userdata', 'std::vector': 'table', 'std::vector': 'string', 'std::vector': 'string', 'std::array': 'table', 'std::deque': 'table', 'std::forward_list': 'table', 'std::queue': 'table', 'std::priority_queue': 'table', 'std::stack': 'table', 'std::unordered_multimap': 'table', 'std::unordered_multiset': 'table', 'std::multimap': 'table', 'std::multiset': 'table', 'std::bitset': 'userdata', 'std::complex': 'table', 'std::valarray': 'table', 'std::span': 'table', 'std::initializer_list': 'table', 'std::type_index': 'userdata', 'std::type_info': 'userdata', 'std::exception': 'userdata', 'std::error_code': 'userdata', 'std::error_condition': 'userdata', 'std::chrono::duration': 'number', 'std::chrono::time_point': 'userdata', 'std::filesystem::path': 'string', 'std::filesystem::directory_entry': 'table', 'std::filesystem::directory_iterator': 'userdata', 'std::filesystem::recursive_directory_iterator': 'userdata', 'std::filesystem::file_status': 'userdata', 'std::filesystem::permissions': 'number', 'std::filesystem::file_type': 'number', 'std::filesystem::space_info': 'table', 'unsigned': 'number', 'unsigned int': 'number', 'unsigned short': 'number', 'unsigned long': 'number', 'signed': 'number', 'short': 'number', 'long': 'number', 'long long': 'number', 'unsigned long long': 'number', 'long double': 'number' } # 查找映射 # 优先匹配完整类型 if cpp_type in type_map: return type_map[cpp_type] # 然后匹配部分类型 for key, value in type_map.items(): if key in cpp_type: return value # 特殊处理:如果是指针或引用类型,返回指向的类型 if '*' in cpp_type or '&' in cpp_type: # 提取指向的类型 base_type = cpp_type.replace('*', '').replace('&', '').strip() # 简化类型名称 base_type = base_type.split('::')[-1] # 检查是否在映射表中 for key, value in type_map.items(): if key in base_type: return value # 如果是 gcText 类型,返回 gcText if 'gcText' in base_type: return 'gcText' # 如果是 UI::Text 类型,返回 UIText if 'UI::Text' in cpp_type: return 'UIText' # 默认返回 userdata return 'userdata' # 特殊处理:如果是枚举类型,返回 number if 'enum' in cpp_type: return 'number' # 特殊处理:如果是类模板实例,返回 table if '<' in cpp_type and '>' in cpp_type: return 'table' # 默认返回 any return 'any' def collect_header_comments(base_path): """ 收集所有头文件中的注释 """ all_comments = {} for root, dirs, files in os.walk(base_path): for file in files: if file.endswith('.h'): header_path = os.path.join(root, file) print('处理头文件:', header_path) comments = parse_header_file(header_path) # 合并注释 for key, value in comments.items(): if key not in all_comments: all_comments[key] = value elif isinstance(value, dict): # 如果是命名空间,合并其内部函数注释 if isinstance(all_comments[key], dict): all_comments[key].update(value) # 提取 constexpr 变量(没有注释块的) try: with open(header_path, 'r') as f: content = f.read() # 匹配 constexpr 变量定义 constexpr_pattern = re.compile(r'constexpr\s+[\w:]+\s+(\w+)\s*=\s*"(.+?)"', re.MULTILINE) for match in constexpr_pattern.finditer(content): var_name = match.group(1) var_value = match.group(2) print('提取到 constexpr 变量:', var_name, '=', var_value) if var_name not in all_comments: all_comments[var_name] = { 'comment': '', 'params': [], 'return_type': 'string', 'value': var_value } except Exception as e: print('提取 constexpr 变量失败:', e) return all_comments def parse_lua_register_file(file_path): """ 解析dl_lua_register.cpp文件,提取Lua绑定信息 """ with open(file_path, 'r') as f: content = f.read() # 提取基本函数 base_functions = [] base_match = re.search(r'lua_register_base\(sol::state& l\)\s*\{([\s\S]*?)\}', content) if base_match: base_code = base_match.group(1) # 提取基本函数注册 function_matches = re.findall(r'l\["([^"]+)"\]\s*=\s*([^;]+);', base_code) for func_name, func_value in function_matches: if 'lua_' in func_value or '::' in func_value: base_functions.append(func_name) # 提取命名空间 namespaces = {} namespace_vars = {} # 提取命名空间注册 namespace_pattern = re.compile(r'sol::table ll = l\["([^"]+)"\]\.get_or_create\(\);([\s\S]*?)\s*\}', re.MULTILINE) namespace_matches = namespace_pattern.findall(content) for namespace_name, namespace_code in namespace_matches: if namespace_name not in namespaces: namespaces[namespace_name] = [] namespace_vars[namespace_name] = [] # 提取函数注册(包括重载) func_matches = re.findall(r'll\["([^"]+)"\]\s*=\s*([^;]+);', namespace_code) for func_name, func_value in func_matches: if '::' in func_value or 'overload' in func_value or 'lua_' in func_value: if func_name not in namespaces[namespace_name]: namespaces[namespace_name].append(func_name) # 提取变量注册(确保不是函数) var_matches = re.findall(r'll\["([^"]+)"\]\s*=\s*([^;]+);', namespace_code) for var_name, var_value in var_matches: if '::' in var_value and '(' not in var_value and 'overload' not in var_value and 'lua_' not in var_value: if var_name not in namespace_vars[namespace_name]: namespace_vars[namespace_name].append(var_name) # 提取类 classes = {} # 提取类注册 class_pattern = re.compile(r'l\.new_usertype<([^>]+)>\("([^"]+)"\s*(?:,\s*sol::no_constructor)?\s*,([\s\S]*?)\s*\);', re.MULTILINE) class_matches = class_pattern.findall(content) for class_type, class_name, class_code in class_matches: methods = [] # 提取方法注册 method_matches = re.findall(r'"([^"]+)"\s*,\s*&([^,]+)', class_code) for method_name, method_value in method_matches: methods.append(method_name) # 提取重载方法注册 overload_matches = re.findall(r'"([^"]+)"\s*,\s*sol::overload\s*\(([\s\S]*?)\)', class_code) for method_name, overload_value in overload_matches: methods.append(method_name) classes[class_name] = { 'type': class_type, 'methods': methods } # 提取全局变量 globals = [] global_matches = re.findall(r'l\["([^"]+)"\]\s*=\s*g_\w+;', content) globals.extend(global_matches) return { 'base_functions': base_functions, 'namespaces': namespaces, 'namespace_vars': namespace_vars, 'classes': classes, 'globals': globals } def generate_lua_intellisense(data, output_path, comments): """ 根据提取的信息生成Lua智能提示文件 """ lines = [] lines.append('---@meta') lines.append('') # 生成基础函数 if data['base_functions']: lines.append('--- 基础函数') for func in data['base_functions']: # 添加函数注释 params = [] if func in comments: if isinstance(comments[func], dict): # 新格式,包含注释和参数 for line in comments[func]['comment'].split('\n'): # 处理 Doxygen 格式的注释 # 过滤掉所有格式的 @param 注释 if '@param' not in line: # 处理 Doxygen 格式的注释 stripped_line = line.strip() if stripped_line.startswith('@brief'): content = stripped_line[len('@brief'):].strip() if content: lines.append('---' + line.replace('@brief', '').strip()) elif stripped_line.startswith('* @brief'): content = stripped_line[len('* @brief'):].strip() if content: lines.append('---' + line.replace('* @brief', '*').strip()) elif stripped_line.startswith('@note'): content = stripped_line[len('@note'):].strip() if content: lines.append('---' + line.replace('@note', '').strip()) elif stripped_line.startswith('* @note'): content = stripped_line[len('* @note'):].strip() if content: lines.append('---' + line.replace('* @note', '*').strip()) elif stripped_line.startswith('@retval'): content = stripped_line[len('@retval'):].strip() if content: return_type = comments[func].get('return_type', 'any') lines.append('---@return {} {}'.format(return_type, content)) elif stripped_line.startswith('* @retval'): content = stripped_line[len('* @retval'):].strip() if content: return_type = comments[func].get('return_type', 'any') lines.append('---@return {} {}'.format(return_type, content)) else: lines.append('---' + line) # 添加参数类型注解和注释 for param_name, param_type, param_comment in comments[func]['params']: if param_comment: lines.append('---@param {} {} {}'.format(param_name, param_type, param_comment)) else: lines.append('---@param {} {}'.format(param_name, param_type)) params.append(param_name) # 如果没有返回值注释,添加默认的返回值类型 return_type = comments[func].get('return_type', 'any') has_return_comment = False for line in comments[func]['comment'].split('\n'): stripped_line = line.strip() if stripped_line.startswith('@retval') or stripped_line.startswith('* @retval'): has_return_comment = True break if not has_return_comment: lines.append('---@return {}'.format(return_type)) else: # 旧格式,只有注释 for line in comments[func].split('\n'): lines.append('---' + line) lines.append('---@param ... any') else: lines.append('---@param ... any') # 生成函数定义 if params: lines.append('function {}({})'.format(func, ', '.join(params))) else: lines.append('function {}(...)'.format(func)) lines.append('end') lines.append('') # 生成命名空间 for namespace, functions in data['namespaces'].items(): # 添加命名空间注释 if namespace in comments: if isinstance(comments[namespace], dict): # 如果是命名空间字典,可能没有直接注释 lines.append('--- {}命名空间'.format(namespace)) else: for line in comments[namespace].split('\n'): lines.append('---' + line) else: lines.append('--- {}命名空间'.format(namespace)) lines.append('{} = {{}}'.format(namespace)) # 存储已经生成的函数名,避免重复生成变量 generated_functions = set() for func in functions: # 添加函数名到集合 generated_functions.add(func) # 特殊处理 GetPathFileAll 函数的重载 if namespace == 'File' and func == 'GetPathFileAll': # 生成多个重载版本 # 第一个重载版本:只有 search_rule 参数 lines.append('---* 获取文件夹所有文件(重载版本1)') lines.append('---@return nil 返回相对路径') lines.append('---@param search_rule table 搜索规则') lines.append('function File.GetPathFileAll(search_rule)') lines.append('end') lines.append('') # 第二个重载版本:path 和 search_rule 参数 lines.append('---* 获取文件夹所有文件(重载版本2)') lines.append('---@return nil 返回相对路径') lines.append('---@param path string 搜索路径') lines.append('---@param search_rule table 搜索规则') lines.append('function File.GetPathFileAll(path, search_rule)') lines.append('end') lines.append('') # 第三个重载版本:path、search_rule 和 max_count 参数 lines.append('---* 获取文件夹所有文件(重载版本3)') lines.append('---@return nil 返回相对路径') lines.append('---@param path string 搜索路径') lines.append('---@param search_rule table 搜索规则') lines.append('---@param max_count number 最大搜索数量') lines.append('function File.GetPathFileAll(path, search_rule, max_count)') lines.append('end') lines.append('') else: # 处理普通函数 # 添加函数注释 params = [] # 尝试直接在comments中查找函数名 if func in comments: if isinstance(comments[func], dict): # 新格式,包含注释和参数 for line in comments[func]['comment'].split('\n'): # 处理 Doxygen 格式的注释 # 过滤掉所有格式的 @param 注释 if '@param' not in line: # 处理 Doxygen 格式的注释 stripped_line = line.strip() if stripped_line.startswith('@brief'): content = stripped_line[len('@brief'):].strip() if content: lines.append('---' + line.replace('@brief', '').strip()) elif stripped_line.startswith('* @brief'): content = stripped_line[len('* @brief'):].strip() if content: lines.append('---' + line.replace('* @brief', '*').strip()) elif stripped_line.startswith('@note'): content = stripped_line[len('@note'):].strip() if content: lines.append('---' + line.replace('@note', '').strip()) elif stripped_line.startswith('* @note'): content = stripped_line[len('* @note'):].strip() if content: lines.append('---' + line.replace('* @note', '*').strip()) elif stripped_line.startswith('@retval'): content = stripped_line[len('@retval'):].strip() if content: return_type = comments[func].get('return_type', 'any') lines.append('---@return {} {}'.format(return_type, content)) elif stripped_line.startswith('* @retval'): content = stripped_line[len('* @retval'):].strip() if content: return_type = comments[func].get('return_type', 'any') lines.append('---@return {} {}'.format(return_type, content)) else: lines.append('---' + line) # 添加参数类型注解和注释 for param_name, param_type, param_comment in comments[func]['params']: if param_comment: lines.append('---@param {} {} {}'.format(param_name, param_type, param_comment)) else: lines.append('---@param {} {}'.format(param_name, param_type)) params.append(param_name) # 如果没有返回值注释,添加默认的返回值类型 return_type = comments[func].get('return_type', 'any') has_return_comment = False for line in comments[func]['comment'].split('\n'): stripped_line = line.strip() if stripped_line.startswith('@retval') or stripped_line.startswith('* @retval'): has_return_comment = True break if not has_return_comment: lines.append('---@return {}'.format(return_type)) else: # 旧格式,只有注释 for line in comments[func].split('\n'): lines.append('---' + line) lines.append('---@param ... any') # 尝试在命名空间中查找函数名 elif namespace in comments and isinstance(comments[namespace], dict) and func in comments[namespace]: if isinstance(comments[namespace][func], dict): # 新格式,包含注释和参数 # 提取返回值类型 return_type = comments[namespace][func].get('return_type', 'any') for line in comments[namespace][func]['comment'].split('\n'): # 过滤掉所有格式的 @param 注释,避免重复 if '@param' not in line: # 处理 Doxygen 格式的注释 stripped_line = line.strip() if stripped_line.startswith('@retval'): content = stripped_line[len('@retval'):].strip() if content: lines.append('---@return {} {}'.format(return_type, content)) elif stripped_line.startswith('* @retval'): content = stripped_line[len('* @retval'):].strip() if content: lines.append('---@return {} {}'.format(return_type, content)) else: lines.append('---' + line) # 添加参数类型注解和注释 for param_name, param_type, param_comment in comments[namespace][func]['params']: if param_comment: lines.append('---@param {} {} {}'.format(param_name, param_type, param_comment)) else: lines.append('---@param {} {}'.format(param_name, param_type)) params.append(param_name) # 如果没有返回值注释,添加默认的返回值类型 return_type = comments[namespace][func].get('return_type', 'any') has_return_comment = False for line in comments[namespace][func]['comment'].split('\n'): stripped_line = line.strip() if stripped_line.startswith('@retval') or stripped_line.startswith('* @retval'): has_return_comment = True break if not has_return_comment: lines.append('---@return {}'.format(return_type)) else: # 旧格式,只有注释 for line in comments[namespace][func].split('\n'): lines.append('---' + line) lines.append('---@param ... any') else: lines.append('---@param ... any') # 生成函数定义 if params: lines.append('function {}.{}({})'.format(namespace, func, ', '.join(params))) else: lines.append('function {}.{}('.format(namespace, func) + '...)') lines.append('end') # 生成命名空间变量 if namespace in data.get('namespace_vars', {}): for var in data['namespace_vars'][namespace]: # 检查变量是否已经作为函数生成过 if var not in generated_functions: # 检查变量是否有值 if var in comments and isinstance(comments[var], dict) and 'value' in comments[var]: var_value = comments[var]['value'] var_type = comments[var].get('return_type', 'any') lines.append('---') lines.append('---@type {}'.format(var_type)) # 不要给已经是字符串形式的值再加上双引号 if var_value.startswith('"') and var_value.endswith('"'): lines.append('{}.{} = {}'.format(namespace, var, var_value)) else: lines.append('{}.{} = "{}"'.format(namespace, var, var_value)) else: # 如果找不到变量值,不生成变量定义,避免重复 pass # 特殊处理 Img 命名空间的 REGEX_FORMAT 变量 if namespace == 'Img': # 检查 REGEX_FORMAT 是否在 comments 中 if 'REGEX_FORMAT' in comments and isinstance(comments['REGEX_FORMAT'], dict) and 'value' in comments['REGEX_FORMAT']: var_value = comments['REGEX_FORMAT']['value'] var_type = comments['REGEX_FORMAT'].get('return_type', 'string') # 检查 REGEX_FORMAT 是否已作为函数生成过 if 'REGEX_FORMAT' not in generated_functions: lines.append('---') lines.append('---@type {}'.format(var_type)) # 不要给已经是字符串形式的值再加上双引号 if var_value.startswith('"') and var_value.endswith('"'): lines.append('{}.{} = {}'.format(namespace, 'REGEX_FORMAT', var_value)) else: lines.append('{}.{} = "{}"'.format(namespace, 'REGEX_FORMAT', var_value)) lines.append('') # 生成类 for class_name, class_info in data['classes'].items(): # 添加类注释 if class_name in comments: for line in comments[class_name].split('\n'): lines.append('---' + line) else: lines.append('--- {}类'.format(class_name)) lines.append('---@class {}'.format(class_name)) lines.append('{} = {{}}'.format(class_name)) for method in class_info['methods']: # 添加方法注释 params = [] if method in comments: if isinstance(comments[method], dict): # 新格式,包含注释和参数 for line in comments[method]['comment'].split('\n'): # 过滤掉所有格式的 @param 注释,避免重复 if '@param' not in line: lines.append('---' + line) # 添加参数类型注解和注释 for param_name, param_type, param_comment in comments[method]['params']: if param_comment: lines.append('---@param {} {} {}'.format(param_name, param_type, param_comment)) else: lines.append('---@param {} {}'.format(param_name, param_type)) params.append(param_name) else: # 旧格式,只有注释 for line in comments[method].split('\n'): lines.append('---' + line) lines.append('---@param ... any') elif class_name in comments and isinstance(comments[class_name], dict) and method in comments[class_name]: if isinstance(comments[class_name][method], dict): # 新格式,包含注释和参数 # 提取返回值类型 return_type = comments[class_name][method].get('return_type', 'any') for line in comments[class_name][method]['comment'].split('\n'): # 过滤掉所有格式的 @param 注释,避免重复 if '@param' not in line: # 处理 Doxygen 格式的注释 stripped_line = line.strip() if stripped_line.startswith('@retval'): content = stripped_line[len('@retval'):].strip() if content: lines.append('---@return {} {}'.format(return_type, content)) elif stripped_line.startswith('* @retval'): content = stripped_line[len('* @retval'):].strip() if content: lines.append('---@return {} {}'.format(return_type, content)) else: lines.append('---' + line) # 添加参数类型注解和注释 for param_name, param_type, param_comment in comments[class_name][method]['params']: if param_comment: lines.append('---@param {} {} {}'.format(param_name, param_type, param_comment)) else: lines.append('---@param {} {}'.format(param_name, param_type)) params.append(param_name) # 如果没有返回值注释,添加默认的返回值类型 return_type = comments[class_name][method].get('return_type', 'any') has_return_comment = False for line in comments[class_name][method]['comment'].split('\n'): stripped_line = line.strip() if stripped_line.startswith('@retval') or stripped_line.startswith('* @retval'): has_return_comment = True break if not has_return_comment: lines.append('---@return {}'.format(return_type)) else: # 旧格式,只有注释 for line in comments[class_name][method].split('\n'): lines.append('---' + line) lines.append('---@param ... any') else: lines.append('---@param ... any') # 生成函数定义 if params: lines.append('function {}:{}({})'.format(class_name, method, ', '.join(params))) else: lines.append('function {}:{}('.format(class_name, method) + '...)') lines.append('end') lines.append('') # 生成全局变量 global_type_map = { 'g_system': 'System', 'g_gfx': 'Graphics', 'g_ui': 'UIManager', 'g_factory': 'Factory' } for global_var in data['globals']: var_type = global_type_map.get(global_var, 'any') lines.append('--- 全局{}实例'.format(global_var)) lines.append('{} = nil --[[@type {}]]'.format(global_var, var_type)) # 为全局变量添加类的方法 if var_type in data['classes']: class_info = data['classes'][var_type] for method in class_info['methods']: # 添加方法注释 params = [] if method in comments: if isinstance(comments[method], dict): # 新格式,包含注释和参数 for line in comments[method]['comment'].split('\n'): # 过滤掉所有格式的 @param 注释,避免重复 if '@param' not in line: # 处理 Doxygen 格式的注释 stripped_line = line.strip() if stripped_line.startswith('@brief'): content = stripped_line[len('@brief'):].strip() if content: lines.append('---' + line.replace('@brief', '').strip()) elif stripped_line.startswith('* @brief'): content = stripped_line[len('* @brief'):].strip() if content: lines.append('---' + line.replace('* @brief', '*').strip()) elif stripped_line.startswith('@note'): content = stripped_line[len('@note'):].strip() if content: lines.append('---' + line.replace('@note', '').strip()) elif stripped_line.startswith('* @note'): content = stripped_line[len('* @note'):].strip() if content: lines.append('---' + line.replace('* @note', '*').strip()) elif stripped_line.startswith('@retval'): content = stripped_line[len('@retval'):].strip() if content: return_type = comments[method].get('return_type', 'any') lines.append('---@return {} {}'.format(return_type, content)) elif stripped_line.startswith('* @retval'): content = stripped_line[len('* @retval'):].strip() if content: return_type = comments[method].get('return_type', 'any') lines.append('---@return {} {}'.format(return_type, content)) else: lines.append('---' + line) # 添加参数类型注解和注释 for param_name, param_type, param_comment in comments[method]['params']: if param_comment: lines.append('---@param {} {} {}'.format(param_name, param_type, param_comment)) else: lines.append('---@param {} {}'.format(param_name, param_type)) params.append(param_name) else: # 旧格式,只有注释 for line in comments[method].split('\n'): lines.append('---' + line) lines.append('---@param ... any') elif var_type in comments and isinstance(comments[var_type], dict) and method in comments[var_type]: if isinstance(comments[var_type][method], dict): # 新格式,包含注释和参数 for line in comments[var_type][method]['comment'].split('\n'): # 过滤掉所有格式的 @param 注释,避免重复 if '@param' not in line: lines.append('---' + line) # 添加参数类型注解和注释 for param_name, param_type, param_comment in comments[var_type][method]['params']: if param_comment: lines.append('---@param {} {} {}'.format(param_name, param_type, param_comment)) else: lines.append('---@param {} {}'.format(param_name, param_type)) params.append(param_name) else: # 旧格式,只有注释 for line in comments[var_type][method].split('\n'): lines.append('---' + line) lines.append('---@param ... any') else: lines.append('---@param ... any') # 生成函数定义 if params: lines.append('function {}.{}({})'.format(global_var, method, ', '.join(params))) else: lines.append('function {}.{}('.format(global_var, method) + '...)') lines.append('end') lines.append('') # 生成辅助类型定义 lines.append('--- 辅助类型定义') lines.append('') lines.append('---@class Position2') lines.append('---@field x number X坐标') lines.append('---@field y number Y坐标') lines.append('') lines.append('---@class Size') lines.append('---@field w number 宽度') lines.append('---@field h number 高度') lines.append('') lines.append('---@class Color') lines.append('---@field r number 红色通道 (0-1)') lines.append('---@field g number 绿色通道 (0-1)') lines.append('---@field b number 蓝色通道 (0-1)') lines.append('---@field a number 透明度 (0-1)') # 写入文件 with open(output_path, 'wb') as f: content = '\n'.join(lines) if isinstance(content, unicode): f.write(content.encode('utf-8')) else: f.write(content) print('生成完成:{}'.format(output_path)) if __name__ == '__main__': input_file = '../dl/script/dl_lua_register.cpp' output_file = './dl_api.lua' # 收集头文件注释 header_comments = collect_header_comments('../dl') data = parse_lua_register_file(input_file) generate_lua_intellisense(data, output_file, header_comments)