Tree-sitterPatterns treesitter-patterns

这是一个通用的tree-sitter代码解析技能,涵盖AST解析、查询模式、访问者和语言插件开发,适用于所有tree-sitter项目。

架构设计 0 次安装 0 次浏览 更新于 3/3/2026

Tree-sitter Patterns 技能

通用的 tree-sitter 代码解析模式。涵盖 AST 访问者、查询模式和语言插件开发。框架无关。

设计原则

这项技能是 框架通用 的。它提供了通用的 tree-sitter 模式:

  • 不针对 Code-Index-MCP、treesitter-chunker 或任何特定项目
  • 涵盖所有 tree-sitter 项目通用的模式
  • 项目特定的查询放在项目特定的技能中

变量

变量 默认 描述
TREE_SITTER_DIR tree_sitter 语言解析器目录
QUERY_DIR queries .scm 查询文件目录
LANGUAGES auto 自动检测或语言列表

指令

MANDATORY - 按顺序遵循以下工作流程。

  1. 确定要解析的语言
  2. 安装适当的语言解析器
  3. 编写查询以提取需求
  4. 处理边缘情况和错误

红旗 - 停止并重新考虑

如果你即将:

  • 没有错误处理地解析(语法错误很常见)
  • 假设所有文件都成功解析
  • 不在样本代码上测试就编写查询
  • 忽略大文件的性能

停止 -> 添加错误处理 -> 在边缘情况上测试 -> 然后继续

食谱书

语言插件开发

  • 如果:创建新的语言解析器
  • 那么:阅读并执行 ./食谱书/语言插件.md

AST 访问者模式

  • 如果:遍历 AST 以提取信息
  • 那么:阅读并执行 ./食谱书/ast-访问者.md

查询模式

  • 如果:编写 tree-sitter 查询
  • 那么:阅读并执行 ./食谱书/查询模式.md

快速参考

Python 设置

import tree_sitter_python as tspython
from tree_sitter import Language, Parser

# 创建解析器
parser = Parser(Language(tspython.language()))

# 解析代码
source = b"def hello(): pass"
tree = parser.parse(source)

# 访问根节点
root = tree.root_node
print(root.sexp())

节点导航

# 获取子节点
for child in node.children:
    print(child.type, child.text)

# 仅命名子节点(跳过标点符号)
for child in node.named_children:
    print(child.type)

# 按类型查找
def find_all(node, type_name):
    results = []
    if node.type == type_name:
        results.append(node)
    for child in node.children:
        results.extend(find_all(child, type_name))
    return results

functions = find_all(root, "function_definition")

查询语言

; 匹配函数定义
(function_definition
  name: (identifier) @function.name
  parameters: (parameters) @function.params
  body: (block) @function.body)

; 匹配类定义
(class_definition
  name: (identifier) @class.name
  body: (block) @class.body)

; 匹配导入
(import_statement
  (dotted_name) @import.module)

; 匹配装饰函数
(decorated_definition
  (decorator) @decorator
  definition: (function_definition
    name: (identifier) @function.name))

运行查询

from tree_sitter import Query

query = Query(Language(tspython.language()), """
(function_definition
  name: (identifier) @name
  body: (block) @body)
""")

captures = query.captures(root)
for node, name in captures:
    print(f"{name}: {node.text.decode()}")

常见节点类型

语言 函数 导入
Python function_definition class_definition import_statement
JavaScript function_declaration class_declaration import_statement
TypeScript function_declaration class_declaration import_statement
Go function_declaration type_declaration import_declaration
Rust function_item impl_item use_declaration

错误处理

def safe_parse(source: bytes) -> tuple[Tree | None, list[str]]:
    """带错误收集的解析。"""
    tree = parser.parse(source)
    errors = []

    def collect_errors(node):
        if node.type == "ERROR" or node.is_missing:
            errors.append(f"Error at {node.start_point}: {node.text[:50]}")
        for child in node.children:
            collect_errors(child)

    collect_errors(tree.root_node)
    return tree, errors

tree, errors = safe_parse(source)
if errors:
    print(f"Parse errors: {errors}")

访问者模式

from abc import ABC, abstractmethod

class ASTVisitor(ABC):
    """tree-sitter AST的基础访问者。"""

    def visit(self, node):
        method_name = f"visit_{node.type}"
        visitor = getattr(self, method_name, self.generic_visit)
        return visitor(node)

    def generic_visit(self, node):
        for child in node.named_children:
            self.visit(child)

    @abstractmethod
    def visit_function_definition(self, node):
        pass

class FunctionExtractor(ASTVisitor):
    def __init__(self):
        self.functions = []

    def visit_function_definition(self, node):
        name_node = node.child_by_field_name("name")
        if name_node:
            self.functions.append(name_node.text.decode())
        self.generic_visit(node)

extractor = FunctionExtractor()
extractor.visit(tree.root_node)
print(extractor.functions)

性能提示

  1. 增量解析:对于编辑,使用 parser.parse(new_source, old_tree)
  2. 延迟评估:如果只需要特定节点,不要遍历整个树
  3. 查询优化:使用更具体的查询以减少匹配
  4. 内存管理:大文件可以使用大量内存
  5. 批量处理:并行处理多个文件

集成

与代码分析集成

def analyze_file(path: Path) -> CodeAnalysis:
    source = path.read_bytes()
    tree = parser.parse(source)

    return CodeAnalysis(
        functions=extract_functions(tree),
        classes=extract_classes(tree),
        imports=extract_imports(tree),
        complexity=calculate_complexity(tree)
    )

与 BAML 集成

class CodeStructure {
  functions FunctionInfo[]
  classes ClassInfo[]
  imports string[]
}

class FunctionInfo {
  name string
  parameters string[]
  return_type string?
  line_start int
  line_end int
}

最佳实践

  1. 错误容忍:始终优雅地处理解析错误
  2. 使用查询:优先使用查询而不是手动遍历
  3. 在真实代码上测试:用实际代码库测试,不仅仅是样本
  4. 记录节点类型:参考语言语法以获取节点类型
  5. 版本解析器:固定 tree-sitter 语言版本