Skip to content

fix(gleam): extract parameters for external functions#1127

Open
carlos-alm wants to merge 5 commits into
mainfrom
fix/1110-gleam-external-function-params
Open

fix(gleam): extract parameters for external functions#1127
carlos-alm wants to merge 5 commits into
mainfrom
fix/1110-gleam-external-function-params

Conversation

@carlos-alm
Copy link
Copy Markdown
Contributor

Summary

  • Mirror regular function behavior in handle_external_function (Rust) and handleExternalFunction (JS) so external function definitions expose their parameter list as children in both engines.
  • Tree-sitter external_function exposes a parameters field (aliased from external_function_parameters to function_parameters) with the same shape as regular function, so extract_params/extractParams can be reused as-is. Type-only external params (no name field) are correctly omitted.

Test plan

  • Rust: cargo test --lib extractors::gleam — 12/12 pass (2 new tests cover named and nameless external params).
  • JS: npx vitest run tests/parsers/gleam.test.ts — 6/6 pass (2 new tests cover named and nameless external params).
  • JS: npx vitest run tests/parsers/ — 476/476 pass after npm run build.
  • Rust: cargo test --lib — 299/299 pass.
  • End-to-end smoke (--engine wasm): codegraph children parse lists input and base as parameter children.

Closes #1110

Mirror regular `function` behavior so `external_function` definitions
expose their parameter list as children in both native and WASM engines.
Previously external functions silently dropped parameter children even
though the grammar exposes them via the same `parameters` field.

Closes #1110
@claude
Copy link
Copy Markdown

claude Bot commented May 15, 2026

Claude finished @carlos-alm's task —— View job


Pull Request Review - COMPLETED ⭐⭐⭐⭐⭐

Conducting comprehensive review of PR #1127 - fix(gleam): extract parameters for external functions

Review Checklist

  • Phase 1: Root Cause Analysis - Understand the problem and verify the approach
  • Phase 2: Configuration Change Detection - Check for risky config modifications
  • Phase 3: Test Integrity - Verify tests are strengthened, not weakened
  • Phase 4: Code Quality - Review implementation details and potential issues
  • Phase 5: Backlog Compliance - Assess against project principles and priorities
  • Final Assessment - Provide rating and recommendation

Root Cause Analysis

Problem Being Solved: Gleam external function definitions were missing parameter extraction, creating engine parity gap and inconsistency with regular function behavior. External functions had hardcoded children: None (Rust) and omitted children entirely (JS), while regular functions properly extracted parameters as child nodes.

Why This Approach: Tree-sitter external_function nodes expose a parameters field aliased from external_function_parameters with the same structure as regular function_parameters. The existing extract_params/extractParams functions handle both cases correctly, including type-only parameters (which get filtered out when no name field exists).

Risk Assessment: ✅ MINIMAL RISK - Purely additive change that reuses battle-tested extraction logic. No modification of existing behavior.

Backlog Compliance

  • Zero-dep: ✅ - No new dependencies, reuses existing tree-sitter infrastructure
  • Foundation-aligned: ✅ - Fixes dual-engine parity (core principle), improves accuracy without violating any foundation rules
  • Problem-fit: 5/5 - Directly addresses AI agent accuracy by providing complete function signatures for better dependency understanding
  • Breaking: No - Purely additive, existing queries continue to work
  • Tier: 1 (zero-dep ✓ + foundation-aligned ✓)

Test Integrity Analysis ✅ EXCELLENT

  • New tests are MORE strict than before: Added comprehensive assertions for both named parameters and type-only parameter edge cases
  • Tests verify both positive and negative cases: Named params → children present, type-only params → children absent
  • Matching test coverage across engines: Rust (2 new tests) and JS (2 new tests) with identical behavior verification
  • NO weakened assertions: All existing tests preserved, new tests only added

Code Quality Assessment ✅ HIGH QUALITY

Implementation Details:

  • Rust: 2-line change - adds let params = extract_params(node, source); and changes children: None to children: opt_children(params)
  • JS: 3-line change - adds const params = extractParams(node); and changes missing children to children: params.length > 0 ? params : undefined
  • Perfect engine parity: Both use identical logic (opt_children returns None for empty Vec, JS uses undefined for empty array)
  • Reuses proven logic: extract_params/extractParams already handles the tree-sitter parameters field correctly
  • Handles edge cases: Type-only external params (no name field) correctly filtered out by existing parameter extraction logic

Potential Issues Checked:

  • No SQL injection risk: Uses existing safe tree-sitter node traversal
  • No performance regression: Reuses existing extraction functions
  • No memory leaks: Standard Vec/Array patterns used consistently
  • No thread safety issues: Stateless extraction functions

Best Practices:

  • Consistent with existing patterns: Mirrors exact logic from handle_function/handleFunction
  • Proper error handling: Graceful fallback to empty params if extraction fails
  • Clear test documentation: Test comments explain type-only vs named parameter scenarios

Critical Concerns

NONE IDENTIFIED - This is a clean, well-implemented fix that addresses a legitimate parity gap.

Final Recommendation

  • Rating: ⭐⭐⭐⭐⭐ (5/5)
  • Action: APPROVE
  • Reasoning: Exemplary fix that addresses real engine parity issue with minimal, safe changes. Perfect test coverage, follows all project conventions, and directly improves AI agent accuracy by providing complete function signatures. This is exactly the kind of incremental improvement that makes codegraph more reliable for dependency analysis.

Specific Strengths:

  1. Addresses core mission: Better function signatures → better AI agent dependency understanding
  2. Follows dual-engine principles: Both engines produce identical results (per CLAUDE.md requirement)
  3. Zero breaking changes: Purely additive functionality
  4. Comprehensive testing: Covers both success and edge cases
  5. Clean implementation: Minimal diff, reuses existing infrastructure

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 15, 2026

Greptile Summary

This PR extends parameter extraction to external Gleam functions in both the Rust and TypeScript engines by reusing the existing extract_params/extractParams helpers, mirroring the behavior already in place for regular function nodes.

  • Rust (gleam.rs): handle_external_function now calls extract_params(node, source) and stores the result via opt_children(params), replacing the hard-coded children: None.
  • TypeScript (gleam.ts): handleExternalFunction similarly calls extractParams(node) and assigns children: params.length > 0 ? params : undefined.
  • Tests: Two tests added in each engine — one asserting that named parameters (input, base) appear as parameter children, and one asserting that type-only parameters (no name field) produce no children.

Confidence Score: 5/5

Safe to merge — the change is additive, touches only the external-function handler in both engines, and reuses the already-tested extract_params/extractParams helper without modifying it.

Both engines receive a two-line addition that calls an existing, well-tested helper and wires its output into children. The new tests exercise the parser end-to-end against real tree-sitter output, covering both the named-parameter happy path and the type-only filtering edge case. No shared logic was changed and no existing tests were modified.

No files require special attention.

Important Files Changed

Filename Overview
crates/codegraph-core/src/extractors/gleam.rs Adds extract_params call to handle_external_function and two new tests; change is a minimal mirror of handle_function with no logic changes to the shared helper.
src/extractors/gleam.ts Adds extractParams call and children field to handleExternalFunction; directly mirrors handleFunction with no new logic paths.
tests/parsers/gleam.test.ts Two new integration tests for external function parameter extraction; both exercise the tree-sitter parser end-to-end and cover the named and type-only parameter cases correctly after the fix in 7dde2c3.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Tree-sitter parses Gleam source] --> B{Node kind?}
    B -- function --> C[handle_function / handleFunction]
    B -- external_function --> D[handle_external_function / handleExternalFunction]
    C --> E[extract_params / extractParams]
    D --> E
    E --> F{parameters field\nor function_parameters child?}
    F -- None --> G[return empty Vec / array]
    F -- found --> H[iterate parameter children]
    H --> I{param kind: function_parameter\nor parameter?}
    I -- yes --> J{has name field\nor identifier child?}
    J -- yes --> K[push child def: kind=parameter]
    J -- no --> L[skip — type-only param]
    I -- no, identifier --> K
    I -- other --> L
    G --> M[children: None / undefined]
    K --> N{params non-empty?}
    N -- yes --> O[children: Some / defined]
    N -- no --> M
Loading

Reviews (6): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

Comment on lines +63 to +68
it('omits children for external functions with type-only parameters', () => {
const symbols = parseGleam(`pub external fn random() -> Int = "rand" "uniform"`);
const randomFn = symbols.definitions.find((d) => d.name === 'random');
expect(randomFn).toBeDefined();
expect(randomFn?.children).toBeUndefined();
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Test description doesn't match the code under test

The test is named 'omits children for external functions with type-only parameters' and its Rust counterpart has the comment // External function with type-only parameters (no names), yet both use random() — a function with zero parameters, not one with anonymous type-only params (e.g. random(Int, String)). These are structurally different tree nodes: an empty parameter list has no children at all, whereas random(Int, String) produces parameter nodes that simply lack a name field. The PR description explicitly calls out "Type-only external params (no name field) are correctly omitted", but that code path is never exercised by either test suite.

Fix in Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 7dde2c3 — both the JS and Rust tests now use random(Int, String) (type-only parameters with no name field) instead of random() (zero parameters), so the assertion that children is undefined actually exercises the documented edge case: parameter nodes that exist in the tree but get filtered out by extractParams/extract_params because they lack a name field.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 15, 2026

Codegraph Impact Analysis

4 functions changed3 callers affected across 2 files

  • handle_external_function in crates/codegraph-core/src/extractors/gleam.rs:55 (1 transitive callers)
  • extracts_external_function_with_named_parameters in crates/codegraph-core/src/extractors/gleam.rs:450 (0 transitive callers)
  • external_function_without_param_names_has_no_children in crates/codegraph-core/src/extractors/gleam.rs:470 (0 transitive callers)
  • handleExternalFunction in src/extractors/gleam.ts:84 (2 transitive callers)

…1127)

Replace random() (zero parameters) with random(Int, String) (type-only
parameters) so the test actually covers the documented edge case:
parameter nodes that exist in the tree but lack a name field. The old
case asserted the same observable outcome (no children) but exercised
the empty-parameter-list path, not the type-only path.

Applies to both Rust and JS engines.
@carlos-alm
Copy link
Copy Markdown
Contributor Author

@greptileai

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.

follow-up: extract parameters for Gleam external_function in both engines

1 participant