abcoder

repository·main·Indexed 18 days ago

https://github.com/cloudwego/abcoder

A TypeScript AST parser and toolset designed to extract method calls, variable references, and dependencies, optimized for monorepo environments. It utilizes UniAST and LSP to perform hallucination-free code analysis and provides an MCP server for deep local code analysis. The system supports multiple languages including Go, TypeScript, Rust, Python, C, and Java, and includes a specialized configuration for AST-driven development in Claude Code.

Tokens
29.2K
Snippets
62
Records
98
Agent score
62%

What's inside abcoder

  1. Known Issues and Fixes in C++ Collector

    main

    This document tracks historical issues encountered during the parsing of C++ code (specifically within freq_service v7) using the ABCoder C++ Collector. It details phenomena, root causes, and the status of fixes for issues related to template functions, NVI (Non-Virtual Interface) patterns, inheritance, and forward declarations.

    Key Areas of Improvement

    • Template Function Calls: Fixed issues where template function calls (e.g., main<...>(...)) were not being correctly identified as reference tokens, leading to failed dependency collection.
    • Inheritance and Templates: Resolved bugs where Implements fields were empty for classes inheriting from template base classes (e.g., SimpleProvider<X,Y>). The collector now uses BaseClassRefs to parse base names directly from declarationText when standard definition lookups fail.
    • NVI and Method Ownership: Fixed issues where methods using the NVI pattern or inline-in-class definitions had missing dependencies or incorrect NodeID assignments. The collector now correctly distinguishes between inline methods (where the receiver class body contains the method body) and out-of-line methods to avoid skipping dependency tokens.
    • Forward Declarations: Fixed a bug where forward declarations (e.g., class X;) were incorrectly emitted as full Type nodes. The collector now filters these out by checking if the content contains a { brace.
    • Alias Resolution: Improved support for using NS::Name; declarations to prevent incorrect NodeID construction (e.g., preventing app::Provider::Provider errors) by implementing resolveAlias and better alias detection in spec.go.
  2. What is the Universal Abstract-Syntax-Tree (UAST)?

    main

    The Universal Abstract-Syntax-Tree (UAST) is a language-agnostic code context data structure designed to be LLM-friendly. It represents a unified abstract syntax tree for a repository's code.

    It collects the definitions of language entities—such as functions, types, and constants/variables—along with their mutual dependency relationships. This structure is intended to facilitate AI understanding and coding-workflow development.

  3. Understand UniAST terminology mapping

    main

    The parser maps TypeScript/JavaScript concepts to the UniAST specification. Note that the terminology is inverted compared to standard npm conventions:

    • TypeScript/JavaScript Package (an npm package with package.json) $\rightarrow$ UniAST Module
    • TypeScript/JavaScript Module (individual .ts/.js files) $\rightarrow$ UniAST Package

    Be aware of this mapping when consuming the generated JSON output.

  4. Understand the Universal Abstract-Syntax-Tree (UniAST) concept

    main
    Universal Abstract-Syntax-Tree (UniAST) is a language-agnostic code context data structure designed to be LLM-friendly. It represents a unified AST of a repository, collecting definitions of language entities (such as functions, types, and constants/variables) and their interdependencies. This structure is intended to facilitate AI understanding and the development of coding workflows.
  5. Understand the Universal Abstract-Syntax-Tree (UniAST) Specification

    main

    The UniAST specification (v0.1.5) defines a structured way to represent codebases as a collection of Modules, Packages, and a dependency Graph. This allows for recursive context retrieval and deep understanding of code relationships across a repository.

    Core Hierarchy

    1. Repository: The top-level container composed of Modules and a Graph.
    2. Module: An independent compilation unit (e.g., a Go module). It contains multiple Packages and manages its own Dependencies.
    3. Package: A code namespace within a module containing Files, Functions, Types, and Vars.
    4. Graph: A topological map of AST nodes, enabling navigation of dependencies and references across the entire repository.
  6. Tree-sitter AST traversal and preliminary symbolization

    main

    When processing Java, the ScannerByTreeSitter method performs the following steps:

    1. Project Scanning: Parses pom.xml to find Maven module paths and traverses .java files.
    2. File Parsing: Reads file content and calls javaparser.Parse(ctx, content) to generate a sitter.Tree.
    3. LSP Notification: Calls c.cli.DidOpen(ctx, uri) to inform the LSP server the file is open.
    4. AST Walking: Performs a depth-first traversal of the tree using c.walk(tree.RootNode(), ...). It identifies nodes by type (e.g., class_declaration, method_declaration) and creates preliminary DocumentSymbol objects containing syntax-based information (name, kind, and local range).
    // Simplified version of the walk method in collect.go
    func (c *Collector) walk(node *sitter.Node, ...) {
        switch node.Type() {
        case "class_declaration":
            // 1. Extract class name from the node
            nameNode := javaparser.FindChildIdentifier(node)
            name := nameNode.Content(content)
    
            // 2. Create a preliminary DocumentSymbol based on syntax info
            sym := &DocumentSymbol{
                Name: name,
                Kind: SKClass,
                Location: Location{URI: uri, Range: ...}, // Location within the current file
                Node: node, // Store the tree-sitter node
                Role: DEFINITION,
            }
            c.syms[sym.Location] = sym
    
            // 3. Recursively walk into the class body
            bodyNode := node.ChildByFieldName("body")
            if bodyNode != nil {
                for i := 0; i < int(bodyNode.ChildCount()); i++ {
                    c.walk(bodyNode.Child(i), ...)
                }
            }
            return
    
        case "method_declaration":
            // ... similar logic for methods ...
        }
    }
  7. Understand the UAST (Universal Abstract Syntax Tree) Core Concepts

    main

    UAST is a unified intermediate representation used to represent multi-language code as a graph structure. It abstracts different programming languages into a common set of entities and relationships, enabling cross-language analysis.

    Top-Level Hierarchy

    • Repository: The highest level, containing one or more Modules.
    • Module: An independent code unit (e.g., a Go Module, Java Maven project, or Python package).
    • Package: A language-specific namespace (e.g., Go package or Java package).
    • File: A physical source code file.

    Core Entities: Node

    Every Node represents a named entity in the code. Nodes are categorized by NodeType:

    • FUNC: Functions or methods.
    • TYPE: Classes, structs, interfaces, enums, etc.
    • VAR: Global variables or constants.

    Identity

    Each node is uniquely identified by an Identity string in the format: ModPath?PkgPath#Name

    • ModPath: Module path (e.g., github.com/your/project@v1.2.0)
    • PkgPath: Package path (e.g., github.com/your/project/internal/utils)
    • Name: Entity name (e.g., MyFunction, MyStruct.MyMethod)
  8. Understand the Module vs Package mapping in UNIAST

    main

    In the UNIAST v0.1.3 mapping strategy used by the TypeScript parser, the concepts of 'Module' and 'Package' differ from standard npm terminology. Understanding this distinction is critical for interpreting the structure of the parsed AST:

    Module (Represents an npm package)

    • Definition: A directory containing a package.json.
    • Name/Version: Derived from the package.json fields.
    • Dir: The relative path from the repository root.
    • Dependencies: Extracted from dependencies and devDependencies in package.json.
    • Language: Always an empty string ('') for TypeScript modules.

    Package (Represents an individual file)

    • Definition: Every individual TypeScript or JavaScript file is treated as a separate Package.
    • PkgPath: The file path relative to the module root (e.g., src/utils.ts).
    • IsMain: A boolean indicating if the file is a main entry point (e.g., index.ts, main.ts).
    • IsTest: A boolean indicating if the file is a test file (e.g., *.test.ts, *.spec.ts, or located in test/ or __tests__/ directories).
  9. How Package paths are resolved

    main

    The parser resolves package paths based on whether the file is internal to the module or an external dependency:

    • Internal Packages: The PkgPath is the file path relative to the module root using forward slashes (e.g., src/utils.ts, lib/helpers.ts).
    • External Packages: These are resolved from node_modules using the module name (e.g., lodash, react, @types/node).

    Note on TypeScript Path Mapping: While tsconfig.json paths (aliases) affect module resolution during parsing, the PkgPath always refers to the actual physical file path relative to the module root. Path aliases are used for symbol resolution, not for defining the PkgPath.

  10. Understand the Universal Abstract-Syntax-Tree (UniAST) Specification

    main

    Universal Abstract-Syntax-Tree (UniAST) is a language-agnostic code context data structure designed to be LLM-friendly. It represents a unified AST of a repository by collecting definitions of language entities (functions, types, constants, variables) and their interdependencies. This structure is used to facilitate AI understanding and coding-workflow development.

    Each AST node contains an Identity composed of three fields: ModPath, PkgPath, and Name.

  11. Understand the AST-Driven Coding core principles

    main

    AST-Driven Coding uses UniAST + LSP to perform hallucination-free code analysis. The workflow follows these four principles:

    • Never Assume: If code details are uncertain, you MUST verify them using mcp__abcoder__get_ast_node.
    • Analysis Priority: Use mcp__abcoder tools over standard Read or Search operations.
    • Direct Use Principle: Provide complete context via pre-analysis so that SubAgents can execute tasks directly without re-analyzing.
    • Phased Development: Follow the progression of MVP $\rightarrow$ Refinement $\rightarrow$ Optimization.
  12. Understand UAST Relations and Entity Details

    main

    UAST uses Relation objects to define edges in the code graph, connecting different Nodes.

    Relation Types (RelationKind)

    • DEPENDENCY: Indicates a node depends on another (e.g., a function call or type usage).
    • IMPLEMENT: Indicates a type node implements an interface node.
    • INHERIT: Indicates a type node inherits from another type node.
    • GROUP: Indicates multiple variables/constants are defined in the same declaration block.

    Entity Details

    Each Node is associated with a detailed structure based on its type:

    • Function: Stores signature, parameters, return values, receiver (for methods), and a list of called functions/methods.
    • Type: Stores kind (struct, interface, etc.), fields, embedded/inherited types, and implemented methods/interfaces.
    • Var: Stores type information and whether it is a constant or pointer.