Skip to main content
Glama
const_checker.py12.8 kB
"""C++ const 正确性检查工具""" import re from typing import List, Dict, Tuple class ConstCorrectnessChecker: """const 正确性检查器""" def check_const_correctness(self, code: str) -> Tuple[List[Dict], str]: """ 检查代码中的 const 正确性 Args: code: 要检查的 C++ 代码 Returns: (问题列表, 格式化的检查报告) """ issues = [] # 检查各种 const 使用问题 issues.extend(self._check_member_functions(code)) issues.extend(self._check_parameters(code)) issues.extend(self._check_return_values(code)) issues.extend(self._check_variables(code)) issues.extend(self._check_pointers_refs(code)) # 生成报告 report = self._generate_report(issues) return issues, report def _check_member_functions(self, code: str) -> List[Dict]: """检查成员函数的 const 正确性""" issues = [] # 检查 getter 函数是否是 const getter_pattern = re.compile(r'(\w+)\s+(get\w+|is\w+|has\w+)\s*\(\s*\)\s*\{') for match in getter_pattern.finditer(code): func_name = match.group(2) # 检查是否有 const 关键字 full_line = code[max(0, match.start() - 50):match.end()] if 'const' not in full_line: issues.append({ "type": "missing_const_member", "severity": "warning", "message": f"getter 函数 {func_name}() 应该是 const", "suggestion": f"在函数声明后添加 const: {func_name}() const", "location": match.group(0), "line": code[:match.start()].count('\n') + 1 }) # 检查不修改成员的函数 method_pattern = re.compile(r'(\w+)\s+(\w+)\s*\([^)]*\)\s*\{([^}]*)\}', re.DOTALL) for match in method_pattern.finditer(code): return_type = match.group(1) func_name = match.group(2) func_body = match.group(3) # 跳过构造函数、析构函数、运算符重载 if func_name in ['if', 'for', 'while'] or func_name.startswith('operator'): continue # 检查函数体是否修改成员 if not re.search(r'\w+\s*=', func_body) and 'const' not in code[match.start():match.end()]: # 可能应该是 const issues.append({ "type": "potentially_const_member", "severity": "info", "message": f"函数 {func_name}() 可能应该是 const", "suggestion": "检查是否修改成员变量,如果不修改则添加 const", "location": f"{return_type} {func_name}()", "line": code[:match.start()].count('\n') + 1 }) return issues def _check_parameters(self, code: str) -> List[Dict]: """检查函数参数的 const 正确性""" issues = [] # 检查大对象参数是否使用 const 引用 param_pattern = re.compile(r'(\w+(?:<[^>]+>)?)\s+(\w+)\s*[,)]') for match in param_pattern.finditer(code): param_type = match.group(1) param_name = match.group(2) # 检查是否是大对象类型 large_types = ['string', 'vector', 'map', 'set', 'list', 'deque', 'unordered_map', 'unordered_set'] is_large = any(t in param_type.lower() for t in large_types) if is_large and '&' not in code[match.start():match.end() + 20]: issues.append({ "type": "missing_const_ref_param", "severity": "warning", "message": f"参数 {param_name} 应该使用 const 引用传递", "suggestion": f"const {param_type}& {param_name}", "location": match.group(0), "line": code[:match.start()].count('\n') + 1 }) # 检查引用参数是否缺少 const ref_param_pattern = re.compile(r'(\w+)\s*&\s*(\w+)\s*[,)]') for match in ref_param_pattern.finditer(code): # 检查前面是否有 const prefix = code[max(0, match.start() - 10):match.start()] if 'const' not in prefix: param_type = match.group(1) param_name = match.group(2) issues.append({ "type": "non_const_ref_param", "severity": "info", "message": f"引用参数 {param_name} 可能应该是 const", "suggestion": f"如果不修改参数,使用 const {param_type}& {param_name}", "location": match.group(0), "line": code[:match.start()].count('\n') + 1 }) return issues def _check_return_values(self, code: str) -> List[Dict]: """检查返回值的 const 正确性""" issues = [] # 检查返回指针是否应该是 const return_ptr_pattern = re.compile(r'return\s+(\w+)\s*;') for match in return_ptr_pattern.finditer(code): var_name = match.group(1) # 查找函数签名 func_start = code.rfind('(', 0, match.start()) if func_start > 0: func_sig = code[max(0, func_start - 100):func_start] if '*' in func_sig and 'const' not in func_sig: issues.append({ "type": "non_const_return_ptr", "severity": "info", "message": "返回指针可能应该是 const", "suggestion": "如果不应修改返回的对象,返回 const T*", "location": match.group(0), "line": code[:match.start()].count('\n') + 1 }) # 检查返回引用 return_ref_pattern = re.compile(r'(\w+)\s*&\s+(\w+)\s*\([^)]*\)') for match in return_ref_pattern.finditer(code): return_type = match.group(1) func_name = match.group(2) # 检查是否有 const if 'const' not in code[max(0, match.start() - 10):match.start()]: issues.append({ "type": "non_const_return_ref", "severity": "info", "message": f"函数 {func_name} 返回引用可能应该是 const", "suggestion": f"const {return_type}& {func_name}()", "location": match.group(0), "line": code[:match.start()].count('\n') + 1 }) return issues def _check_variables(self, code: str) -> List[Dict]: """检查变量的 const 正确性""" issues = [] # 检查未修改的局部变量 var_pattern = re.compile(r'(\w+)\s+(\w+)\s*=\s*([^;]+);') for match in var_pattern.finditer(code): var_type = match.group(1) var_name = match.group(2) # 跳过已经是 const 的 if var_type == 'const' or 'const' in code[max(0, match.start() - 10):match.start()]: continue # 检查后续是否修改了这个变量 rest_code = code[match.end():match.end() + 500] assignment_pattern = rf'\b{var_name}\s*=' if not re.search(assignment_pattern, rest_code): issues.append({ "type": "missing_const_variable", "severity": "info", "message": f"变量 {var_name} 可能应该是 const", "suggestion": f"const {var_type} {var_name} = ...", "location": match.group(0), "line": code[:match.start()].count('\n') + 1 }) return issues def _check_pointers_refs(self, code: str) -> List[Dict]: """检查指针和引用的 const 正确性""" issues = [] # 检查指针的 const 位置 ptr_pattern = re.compile(r'(\w+)\s*\*\s*(const)?\s*(\w+)') for match in ptr_pattern.finditer(code): type_name = match.group(1) const_after = match.group(2) var_name = match.group(3) # 检查是否有 const before * prefix = code[max(0, match.start() - 10):match.start()] const_before = 'const' in prefix if not const_before and not const_after: issues.append({ "type": "non_const_pointer", "severity": "info", "message": f"指针 {var_name} 缺少 const 限定", "suggestion": "使用 const T* (指向const) 或 T* const (const指针) 或 const T* const (都是const)", "location": match.group(0), "line": code[:match.start()].count('\n') + 1 }) return issues def _generate_report(self, issues: List[Dict]) -> str: """生成格式化的检查报告""" if not issues: return """ # ✅ const 正确性检查报告 **结果**: 代码的 const 使用看起来很好! **const 最佳实践提醒**: 1. 不修改的成员函数应该声明为 const 2. 大对象参数使用 const 引用传递 3. 不修改的局部变量声明为 const 4. 正确使用 const T* (指向const) 和 T* const (const指针) 5. 返回内部数据时使用 const 引用或指针 """ # 按严重程度分类 errors = [i for i in issues if i['severity'] == 'error'] warnings = [i for i in issues if i['severity'] == 'warning'] infos = [i for i in issues if i['severity'] == 'info'] report = "# 🔍 const 正确性检查报告\n\n" report += f"**检查结果**: 发现 {len(issues)} 个潜在问题\n" report += f"- 🔴 错误: {len(errors)}\n" report += f"- 🟡 警告: {len(warnings)}\n" report += f"- 🔵 建议: {len(infos)}\n\n" report += "---\n\n" # 报告问题 if warnings: report += "## 🟡 应该改进的地方\n\n" for i, issue in enumerate(warnings, 1): report += self._format_issue(i, issue) if infos: report += "## 🔵 可以改进的地方\n\n" for i, issue in enumerate(infos, 1): report += self._format_issue(i, issue) # const 使用指南 report += "\n## 📚 const 使用指南\n\n" report += "### 成员函数\n" report += "```cpp\n" report += "class Widget {\n" report += " int getValue() const; // 不修改成员\n" report += " void setValue(int v); // 修改成员\n" report += " bool isEmpty() const; // getter 应该是 const\n" report += "};\n" report += "```\n\n" report += "### 函数参数\n" report += "```cpp\n" report += "// 大对象使用 const 引用\n" report += "void process(const std::string& str);\n" report += "void process(const std::vector<int>& vec);\n\n" report += "// 小对象可以传值\n" report += "void process(int value);\n" report += "void process(std::string_view sv); // C++17\n" report += "```\n\n" report += "### 指针的 const\n" report += "```cpp\n" report += "const int* p1; // 指向 const int (不能通过 p1 修改)\n" report += "int* const p2; // const 指针 (不能改变指向)\n" report += "const int* const p3; // 都是 const\n" report += "```\n\n" report += "### 返回值\n" report += "```cpp\n" report += "class Container {\n" report += " const T& get(int i) const; // 返回 const 引用\n" report += " T& get(int i); // 返回可修改引用\n" report += "};\n" report += "```\n" return report def _format_issue(self, index: int, issue: Dict) -> str: """格式化单个问题""" output = f"### {index}. {issue['message']}\n\n" if issue.get('line', 0) > 0: output += f"**位置**: 第 {issue['line']} 行\n" if issue.get('location'): output += f"**代码**: `{issue['location']}`\n" output += f"**建议**: {issue['suggestion']}\n\n" return output # 全局实例 _checker = None def get_checker() -> ConstCorrectnessChecker: """获取全局 const 正确性检查器实例""" global _checker if _checker is None: _checker = ConstCorrectnessChecker() return _checker

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/SongJiangzhou/cpp_guidelines'

If you have feedback or need assistance with the MCP directory API, please join our Discord server