Skip to content

Comments

feat(ast): implement Issue #41 P0 parser adaptations#48

Merged
phodal merged 1 commit intomasterfrom
feat/issue-41-parser-p0-adaptation
Jan 20, 2026
Merged

feat(ast): implement Issue #41 P0 parser adaptations#48
phodal merged 1 commit intomasterfrom
feat/issue-41-parser-p0-adaptation

Conversation

@phodal
Copy link
Owner

@phodal phodal commented Jan 20, 2026

Summary

Implements P0 parser adaptations for Issue #41 (chapi-domain core model improvements):

  • TypeScript Parser: Populate TopLevel structure alongside legacy default node for backward compatibility; add structured call chain parsing with ReceiverExpr, Chain, ChainArguments, IsOptional fields
  • Go Parser: Populate TopLevel structure for package-level functions; add ReceiverExpr to CodeCall
  • Rust Parser: Populate TopLevel structure for free functions; add ReceiverExpr to CodeCall
  • Tests: Add regression tests covering new structured fields

Related Issue

Closes #41 (partial - P0 parser adaptations)

Changes

File Description
TypeScriptFullIdentListener.kt Add TopLevel population, structured chain call parsing with ChainCallInfo
GoFullIdentListener.kt Add TopLevel population, ReceiverExpr field
RustAstBaseListener.kt Add TopLevel population
RustFullIdentListener.kt Add ReceiverExpr field
TypeScriptCallTest.kt Add tests for TopLevel, Import/Export, Container metadata
GoAnalyserTest.kt Update test to include new ReceiverExpr field

Test Plan

  • All existing TypeScript parser tests pass
  • All existing Go parser tests pass
  • All existing Rust parser tests pass
  • New regression tests for structured fields pass
  • Full test suite passes (./gradlew test)

Summary by CodeRabbit

  • New Features

    • Added receiver expression tracking for function calls across Go, Rust, and TypeScript analyzers
    • Introduced top-level scope support to capture module-level functions and fields
    • Enhanced structured representation for chained method calls and import/export handling in TypeScript
  • Tests

    • Added comprehensive test coverage for top-level structure population, import/export fields, and container metadata

✏️ Tip: You can customize this high-level summary in your review settings.

- TypeScript: populate TopLevel structure alongside legacy default node
- TypeScript: add structured call chain parsing (ReceiverExpr, Chain, ChainArguments, IsOptional)
- Go: populate TopLevel structure and add ReceiverExpr to CodeCall
- Rust: populate TopLevel structure and add ReceiverExpr to CodeCall
- Add regression tests for new structured fields
Copilot AI review requested due to automatic review settings January 20, 2026 00:32
@coderabbitai
Copy link

coderabbitai bot commented Jan 20, 2026

📝 Walkthrough

Walkthrough

This PR implements multi-language parser improvements from Issue #41, introducing structured representations for top-level declarations and method call receivers across Go, Rust, and TypeScript. Key additions include TopLevelScope for file-level functions and fields, a new ReceiverExpr field in CodeCall to capture receiver context, and enhanced TypeScript chain call handling with structured metadata.

Changes

Cohort / File(s) Summary
Go Parser Updates
chapi-ast-go/src/main/kotlin/chapi/ast/goast/GoFullIdentListener.kt, chapi-ast-go/src/test/kotlin/chapi/ast/goast/GoAnalyserTest.kt
Resolves receiver context during function call construction; introduces ReceiverExpr field to CodeCall and TopLevelScope for top-level Functions/Fields; populates TopLevelScope when declarations exist; test updated to include ReceiverExpr="fmt"
Rust Parser Updates
chapi-ast-rust/src/main/kotlin/chapi/ast/rustast/RustAstBaseListener.kt, chapi-ast-rust/src/main/kotlin/chapi/ast/rustast/RustFullIdentListener.kt
Initializes TopLevel structure in getNodeInfo when individual functions/fields exist; adds ReceiverExpr field to three CodeCall construction sites, populating with nodeName or instanceVar as fallback
TypeScript Parser Updates
chapi-ast-typescript/src/main/kotlin/chapi/ast/typescriptast/TypeScriptFullIdentListener.kt
Introduces ChainCallInfo and Quadruple data classes for structured chain representation; new buildStructuredCallChain function extracts receiver, chain methods, per-call arguments, and optional chaining flags; refactored top-level export handling to populate TopLevelScope; updates CodeCall with ReceiverExpr, Chain, ChainArguments, and IsOptional fields
TypeScript Test Suite
chapi-ast-typescript/src/test/kotlin/chapi/ast/typescriptast/TypeScriptCallTest.kt
Adds three new test methods: shouldPopulateTopLevelStructure (validates Functions/Fields presence), shouldPopulateStructuredImportFields (validates import/export specs), shouldPopulateContainerMetadata (validates Language/Kind metadata)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 Structured calls now bloom with grace,
Receivers parsed in their rightful place,
Top-level functions skip the hack,
Chains unwind without the slack,
Multi-language harmony at last!

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly references Issue #41 and accurately describes the main change: P0 parser adaptations across TypeScript, Go, and Rust.
Linked Issues check ✅ Passed PR implements key P0 objectives from Issue #41: TopLevel structure for package-level functions, ReceiverExpr field in CodeCall, and regression tests covering the new structured fields.
Out of Scope Changes check ✅ Passed All changes are directly aligned with Issue #41 P0 scope: TypeScript, Go, and Rust parser adaptations with TopLevel and ReceiverExpr fields.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@phodal phodal merged commit 0624b00 into master Jan 20, 2026
7 of 8 checks passed
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements P0 parser adaptations for Issue #41, adding structured call chain parsing and TopLevel scope population across TypeScript, Go, and Rust parsers.

Changes:

  • Added TopLevel structure population for package/module-level functions and fields in TypeScript, Go, and Rust
  • Implemented structured call chain parsing in TypeScript with ReceiverExpr, Chain, ChainArguments, and IsOptional fields
  • Added ReceiverExpr field to CodeCall in Go and Rust parsers
  • Added regression tests for TopLevel structure and import/export metadata

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
TypeScriptFullIdentListener.kt Adds TopLevel population and structured call chain parsing with ChainCallInfo; maintains backward compatibility with legacy "default" node
TypeScriptCallTest.kt Adds tests for TopLevel structure, Import/Export fields, and Container metadata
GoFullIdentListener.kt Adds TopLevel population for package-level functions and ReceiverExpr field to CodeCall
GoAnalyserTest.kt Updates test to include ReceiverExpr field in expected CodeCall
RustAstBaseListener.kt Adds TopLevel population for free functions and fields
RustFullIdentListener.kt Adds ReceiverExpr field to CodeCall for call and method call expressions
Comments suppressed due to low confidence (1)

chapi-ast-go/src/test/kotlin/chapi/ast/goast/GoAnalyserTest.kt:42

  • The test verifies ReceiverExpr for the function call within main(), but doesn't verify that the package-level function main() is correctly populated in codeContainer.TopLevel. Add assertions to verify that TopLevel is populated and contains the main function, similar to the TypeScript tests for TopLevel structure.
    @Test
    fun analysis() {
        val helloworld = """
package main

import "fmt"

func main() {
    fmt.Println("hello world")
}
"""
        val codeContainer = GoAnalyser().analysis(helloworld, "")
        val value = codeContainer.DataStructures[0]
        val expect = CodeDataStruct(
            Functions = listOf(
                CodeFunction(
                    Name = "main", Package = "main",
                    FunctionCalls = listOf(
                        CodeCall(
                            NodeName = "fmt",
                            FunctionName = "Println",
                            Parameters = listOf(CodeProperty(TypeValue = "hello world", TypeType = "string")),
                            // New structured field (Issue #41)
                            ReceiverExpr = "fmt"
                        )
                    ),
                )
            ),
        )
        assertEquals(Json.encodeToString(value), Json.encodeToString(expect))
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 1229 to 1252
is TypeScriptParser.ArgumentsExpressionContext -> {
val nodeName = wrapTargetType(singleExprCtx)
val funcName = buildFunctionName(singleExprCtx)

// Check if this is a chained call (contains ->)
val callee = singleExprCtx.singleExpression()
val (receiverExpr, chain, chainArgs, isOptional) = if (callee is TypeScriptParser.MemberDotExpressionContext) {
val info = buildStructuredCallChain(callee)
Quadruple(info.receiverExpr, info.chain, info.chainArguments, info.isOptional)
} else {
Quadruple(nodeName, listOf<String>(), listOf<List<CodeProperty>>(), false)
}

currentFunc.FunctionCalls += CodeCall(
Parameters = processArgumentList(singleExprCtx.arguments()?.argumentList()),
FunctionName = buildFunctionName(singleExprCtx),
NodeName = wrapTargetType(singleExprCtx),
Position = buildPosition(ctx)
FunctionName = funcName,
NodeName = nodeName,
Position = buildPosition(ctx),
// New structured fields (Issue #41)
ReceiverExpr = receiverExpr,
Chain = chain,
ChainArguments = chainArgs,
IsOptional = isOptional
)
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the bug in argumentsExpressionToCall, the structured call chain fields are incorrectly populated here. For chained calls, the Parameters should come from the innermost method's arguments (from chainInfo), not from the outermost call's arguments. For non-chained calls, ReceiverExpr should be empty for standalone function calls (where there's no receiver object), not set to nodeName which could be the function name itself. Additionally, ChainArguments has the same issue as in argumentsExpressionToCall where it doesn't include the outermost call's arguments.

Copilot uses AI. Check for mistakes.
Comment on lines +30 to 104
/**
* Issue #41 - Test TopLevel structure is populated for TypeScript
*/
@Test
fun shouldPopulateTopLevelStructure() {
val code = """
const API_URL = "https://api.example.com";

export function fetchData() {
return fetch(API_URL);
}

export const handler = async () => {
return "result";
};
"""
val codeFile = TypeScriptAnalyser().analysis(code, "test.ts")

// New: TopLevel should be populated
assertNotNull(codeFile.TopLevel, "TopLevel should be populated")
assertTrue(codeFile.TopLevel!!.Functions.isNotEmpty(), "TopLevel should have functions")
assertTrue(codeFile.TopLevel!!.Fields.isNotEmpty(), "TopLevel should have fields")

// Should have fetchData and handler functions
val functionNames = codeFile.TopLevel!!.Functions.map { it.Name }
assertTrue(functionNames.contains("fetchData"), "TopLevel should contain fetchData function")
assertTrue(functionNames.contains("handler"), "TopLevel should contain handler function")

// Should have API_URL field
val fieldNames = codeFile.TopLevel!!.Fields.map { it.TypeKey }
assertTrue(fieldNames.contains("API_URL"), "TopLevel should contain API_URL field")
}

/**
* Issue #41 - Test structured import/export with new fields
*/
@Test
fun shouldPopulateStructuredImportFields() {
val code = """
import { foo, bar as baz } from "module";
import * as utils from "./utils";
import React from "react";
"""
val codeFile = TypeScriptAnalyser().analysis(code, "test.ts")

val namedImport = codeFile.Imports.find { it.Source == "module" }
assertNotNull(namedImport)
assertEquals(chapi.domain.core.ImportKind.NAMED, namedImport.Kind)
assertTrue(namedImport.Specifiers.isNotEmpty(), "Named import should have specifiers")

val namespaceImport = codeFile.Imports.find { it.Source.contains("utils") }
assertNotNull(namespaceImport)
assertEquals(chapi.domain.core.ImportKind.NAMESPACE, namespaceImport.Kind)
assertEquals("utils", namespaceImport.NamespaceName)

val defaultImport = codeFile.Imports.find { it.Source == "react" }
assertNotNull(defaultImport)
assertEquals(chapi.domain.core.ImportKind.DEFAULT, defaultImport.Kind)
assertEquals("React", defaultImport.DefaultName)
}

/**
* Issue #41 - Test CodeContainer new fields (Language, Kind)
*/
@Test
fun shouldPopulateContainerMetadata() {
val code = """
export const x = 1;
"""
val codeFile = TypeScriptAnalyser().analysis(code, "test.ts")

assertEquals("typescript", codeFile.Language)
assertEquals(chapi.domain.core.ContainerKind.MODULE, codeFile.Kind)
}
}
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new tests don't verify the core new fields that were added (ReceiverExpr, Chain, ChainArguments, IsOptional). The tests only check TopLevel, Import/Export fields, and Container metadata, but don't validate that the structured call chain parsing is working correctly. Add assertions to verify ReceiverExpr, Chain, ChainArguments, and IsOptional fields for various call patterns like "axios.get(url).then(handler)".

Copilot uses AI. Check for mistakes.
Comment on lines +1276 to +1277
/** Simple quadruple data class for destructuring. */
private data class Quadruple<A, B, C, D>(val first: A, val second: B, val third: C, val fourth: D)
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Quadruple data class is a generic utility but is only used for destructuring in one place. Consider using Kotlin's built-in destructuring with data classes or inline this to avoid introducing a reusable generic class that isn't actually reused. Alternatively, create a specific data class with meaningful field names like ChainDestructured with receiverExpr, chain, chainArguments, and isOptional fields for better code clarity.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chapi-domain 核心模型:面向多语言 parser 的结构化改进(namespace/module、import/export、type、call、top-level)

1 participant