Skip to content

Add Swift grammar support and skeleton coverage#71

Open
marvin-yorke wants to merge 1 commit intoRyandonofrio3:mainfrom
marvin-yorke:swift
Open

Add Swift grammar support and skeleton coverage#71
marvin-yorke wants to merge 1 commit intoRyandonofrio3:mainfrom
marvin-yorke:swift

Conversation

@marvin-yorke
Copy link

@marvin-yorke marvin-yorke commented Dec 12, 2025

The readme file mentions support for Swift, but there's no Tree-sitter grammar defined in the source code itself. This PR introduces https://github.com/alex-pinkus/tree-sitter-swift grammar for parsing Swift code files, as the official https://github.com/tree-sitter/tree-sitter-swift/ is abandoned

The additional code in skeletonizer.js solves the argument names being the part of the Swift function signature. In case we have something like

class Greeter {
  func greet(name: String) {} 
  func greet(person: Person) {}
}

func doThing() {
  // ... 
  greeter.greet(name: "Alice")
}

only outputting -> greet as callee is not enough, there are two separate functions, greet(name:) and greet(person:) which we need to distinguish

Implementation is aided by Codex

Summary by CodeRabbit

  • New Features
    • Added Swift language support, enabling code analysis and navigation for .swift files
    • Improved symbol extraction with language-aware processing for more accurate function and declaration identification
    • Enhanced support for Swift-specific constructs including classes, protocols, and initializers

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

@coderabbitai
Copy link

coderabbitai bot commented Dec 12, 2025

Walkthrough

The changes add comprehensive Swift language support to the codebase by introducing a Swift language definition with AST node mappings, extending skeleton field configurations for Swift containers, and refactoring symbol extraction logic to be language-aware with Swift-specific formatting for function calls.

Changes

Cohort / File(s) Summary
Language Definition
src/lib/core/languages.ts
Added new Swift language definition with id "swift", file extension ".swift", tree-sitter grammar URL, and nine declaration types (function_declaration, class_declaration, protocol_declaration, property_declaration, typealias_declaration, init_declaration, deinit_declaration, macro_declaration, subscript_declaration).
Skeleton Configuration
src/lib/skeleton/body-fields.ts
Extended BODY_FIELDS with Swift language mappings for function/init/deinit bodies, and added Swift container types (class_declaration, class_body, enum_class_body, protocol_declaration, protocol_body) to CONTAINER_TYPES for recursive skeleton analysis.
Symbol Extraction
src/lib/skeleton/skeletonizer.ts
Refactored extractReferencedSymbols() to accept langId parameter and introduced language-aware helper functions (getNavigationIdentifier, getCallFunctionNode, extractFunctionName, extractSwiftArgumentLabels, formatSwiftFunction, pushRef) to robustly handle symbol extraction across languages with Swift-specific argument label and formatting logic.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • src/lib/skeleton/skeletonizer.ts requires the most attention: multiple new helper functions, language-aware branching logic, updated method signature, and Swift-specific formatting heuristics (argument label extraction, truncation, ellipsis handling) need careful verification against expected Swift AST shapes
  • Verify that all call sites of extractReferencedSymbols() have been updated to pass langId
  • Cross-check the nine declaration types in languages.ts against actual tree-sitter Swift grammar to ensure completeness
  • Validate the pushRef() helper constraints (length < 30, deduplication) align with downstream expectations

Poem

🐰 A rabbit hops through syntax trees,
Swift as the wind, with graceful ease,
New nodes and fields now intertwine,
Symbols extracted, clean and fine!
The skeleton dances, language-aware,
Swift support blooms—everywhere!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main changes: adding Swift grammar support and expanding skeleton coverage to handle Swift-specific patterns.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 51906e2 and ef70441.

📒 Files selected for processing (3)
  • src/lib/core/languages.ts (1 hunks)
  • src/lib/skeleton/body-fields.ts (2 hunks)
  • src/lib/skeleton/skeletonizer.ts (4 hunks)
🔇 Additional comments (1)
src/lib/skeleton/skeletonizer.ts (1)

293-320: Good: referenced symbol extraction is now language-aware.
Passing langId into extractReferencedSymbols is the right hook for Swift-specific call formatting without impacting other languages.

Comment on lines +178 to +196
{
id: "swift",
extensions: [".swift"],
grammar: {
name: "swift",
url: "https://github.com/alex-pinkus/tree-sitter-swift/releases/download/0.7.1/tree-sitter-swift.wasm",
},
definitionTypes: [
"function_declaration",
"class_declaration",
"protocol_declaration",
"property_declaration",
"typealias_declaration",
"init_declaration",
"deinit_declaration",
"macro_declaration",
"subscript_declaration",
],
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find the grammar loader implementation
rg -t ts -t js "Language\.load\|grammar.*url" --max-count 20

Repository: Ryandonofrio3/osgrep

Length of output: 184


🏁 Script executed:

# Check if there are existing tests for language definitions
fd -e test -e spec | head -20

Repository: Ryandonofrio3/osgrep

Length of output: 46


🏁 Script executed:

# Look for Swift-specific tests or references
rg -i "swift" --max-count 20

Repository: Ryandonofrio3/osgrep

Length of output: 1348


🏁 Script executed:

# Check the web-tree-sitter version and dependencies
cat package.json | grep -A 5 -B 5 "web-tree-sitter"

Repository: Ryandonofrio3/osgrep

Length of output: 354


🏁 Script executed:

# View the body-fields.ts Swift mappings in detail
cat -n src/lib/skeleton/body-fields.ts | grep -A 10 -B 2 "swift:"

Repository: Ryandonofrio3/osgrep

Length of output: 959


🏁 Script executed:

# Check for any existing Swift tests
find . -name "*.test.*" -o -name "*.spec.*" | xargs grep -l "swift" 2>/dev/null || echo "No Swift tests found"

Repository: Ryandonofrio3/osgrep

Length of output: 84


🏁 Script executed:

# Look for integration or fixture files related to languages
find . -type f -name "*language*" -o -name "*grammar*" | grep -v node_modules | head -20

Repository: Ryandonofrio3/osgrep

Length of output: 125


🌐 Web query:

tree-sitter-swift 0.7.1 release github alex-pinkus wasm

💡 Result:

Yes — alex-pinkus's tree-sitter-swift has a 0.7.1 release (published June 23, 2025) and the repo includes instructions for building/using a WebAssembly (wasm) bundle with web-tree-sitter. Sources: GitHub repo (README with wasm instructions) and crate release listing. [1][2]

Sources

  • alex-pinkus/tree-sitter-swift (README, wasm usage). [1]
  • crate/release listing showing 0.7.1 — Jun 23, 2025. [2]

🏁 Script executed:

# Check grammar-loader.ts to understand how Language.load() works
cat -n src/lib/index/grammar-loader.ts

Repository: Ryandonofrio3/osgrep

Length of output: 2413


🏁 Script executed:

# Search for property_declaration, typealias_declaration, macro_declaration, subscript_declaration usage
rg "property_declaration|typealias_declaration|macro_declaration|subscript_declaration" --max-count 30

Repository: Ryandonofrio3/osgrep

Length of output: 286


🏁 Script executed:

# Check if there are any comments or docs about supported node types for Swift
rg -i "node.*type|definition.*type" src/lib/core/languages.ts -A 3 -B 3

Repository: Ryandonofrio3/osgrep

Length of output: 3601


🌐 Web query:

tree-sitter-swift property_declaration macro_declaration subscript_declaration node structure

💡 Result:

I can’t reliably list exact fields without reading the grammar’s generated node-types.json, but you can inspect the precise node structure (fields, children and supertypes) for property_declaration, macro_declaration and subscript_declaration in the tree-sitter‑swift grammar’s node‑types.json. Useful links:

  • tree-sitter docs on node-types.json (explains format and how to read fields/children). [1]
  • tree-sitter‑swift repository (contains src/node-types.json to inspect exact node shapes). [2]
  • Rust crate / package pages for tree-sitter‑swift (versions/releases). [3][4]

If you want, I can fetch and paste the exact node-types.json entries for: property_declaration, macro_declaration, and subscript_declaration — tell me which repository/version (e.g., alex-pinkus/tree-sitter-swift main or the tree-sitter-swift v0.7.1 release) and I’ll extract and show the exact JSON for those node types.

Sources:
[1] https://tree-sitter.github.io/tree-sitter/using-parsers/6-static-node-types
[2] https://github.com/alex-pinkus/tree-sitter-swift
[3] https://crates.io/crates/tree-sitter-swift
[4] https://pypi.org/project/tree-sitter-swift/


🏁 Script executed:

# Check if there's any documentation or comments about why certain types are excluded
rg -B 5 -A 5 "body-fields|definitionTypes" src/lib/core/languages.ts

Repository: Ryandonofrio3/osgrep

Length of output: 4791


🏁 Script executed:

# Look for any usage of property_declaration, macro_declaration, subscript_declaration in the codebase
rg -r "property_declaration|macro_declaration|subscript_declaration" src/ --type-list

Repository: Ryandonofrio3/osgrep

Length of output: 453


🏁 Script executed:

# Try to download and inspect tree-sitter-swift node-types.json from the repository
curl -s "https://raw.githubusercontent.com/alex-pinkus/tree-sitter-swift/0.7.1/src/node-types.json" 2>/dev/null | python3 << 'EOF'
import sys
import json

try:
    data = json.load(sys.stdin)
    # Look for property_declaration, macro_declaration, subscript_declaration, typealias_declaration
    target_types = ["property_declaration", "macro_declaration", "subscript_declaration", "typealias_declaration"]
    
    for item in data:
        if isinstance(item, dict) and item.get("type") in target_types:
            print(f"\n{item['type']}:")
            print(json.dumps(item, indent=2))
except Exception as e:
    print(f"Error: {e}", file=sys.stderr)
EOF

Repository: Ryandonofrio3/osgrep

Length of output: 150


🏁 Script executed:

# Also check if there's a skeletonizer pattern that processes definitionTypes
rg -A 20 "definitionTypes" src/lib/skeleton/skeletonizer.ts

Repository: Ryandonofrio3/osgrep

Length of output: 46


🏁 Script executed:

# Check how definitionTypes are actually used - search for usage patterns
rg "definitionTypes" src/ -B 2 -A 2 | head -40

Repository: Ryandonofrio3/osgrep

Length of output: 2207


🏁 Script executed:

# Look for the extraction logic that uses definitionTypes
rg -t ts "function.*extract|walk.*node|traverse" src/lib/skeleton/ | head -20

Repository: Ryandonofrio3/osgrep

Length of output: 157


Add body-field mappings for property_declaration, typealias_declaration, macro_declaration, and subscript_declaration in src/lib/skeleton/body-fields.ts.

The Swift grammar (0.7.1 WASM URL is valid and loads correctly), but src/lib/core/languages.ts declares 9 definitionTypes while src/lib/skeleton/body-fields.ts only maps 5. When chunker.ts classifies nodes by definitionTypes, the four unmapped types (property_declaration, typealias_declaration, macro_declaration, subscript_declaration) will be identified as definitions but their bodies will fail to extract, breaking semantic chunking. Determine whether these types should have body mappings (e.g., property_declaration → "value" field) or be removed from definitionTypes if they don't contain extractable bodies.

🤖 Prompt for AI Agents
In src/lib/core/languages.ts around lines 178-196, the Swift entry lists
definitionTypes that are not mapped in src/lib/skeleton/body-fields.ts, causing
body extraction to fail; update src/lib/skeleton/body-fields.ts to add
body-field mappings for the missing Swift node types (property_declaration →
"value", typealias_declaration → "type", macro_declaration → "body" (or
"declaration" if that matches the grammar), subscript_declaration → "accessors"
or "body" depending on tree-sitter fields), or alternatively remove those four
types from the Swift definitionTypes in src/lib/core/languages.ts if they truly
have no extractable body; ensure chosen field names match the tree-sitter-swift
grammar fields and run the chunker unit tests to confirm correct extraction.

Comment on lines +113 to +120
swift: {
function_declaration: "body",
init_declaration: "body",
deinit_declaration: "body",
class_declaration: null, // Container (covers class/struct/enum/actor)
protocol_declaration: null, // Container
enum_class_body: null, // Container for nested declarations
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's locate the body-fields.ts file and see its context
find . -name "body-fields.ts" -type f 2>/dev/null | head -5

Repository: Ryandonofrio3/osgrep

Length of output: 97


🏁 Script executed:

# Search for tree-sitter-swift references in the codebase
rg "tree-sitter-swift" --type json --type ts --type js -i | head -20

Repository: Ryandonofrio3/osgrep

Length of output: 199


🏁 Script executed:

# Look for package.json to check dependencies and versions
find . -name "package.json" -type f -exec grep -l "tree-sitter" {} \; 2>/dev/null | head -5

Repository: Ryandonofrio3/osgrep

Length of output: 78


🏁 Script executed:

# Read the body-fields.ts file to see the full context
cat -n ./src/lib/skeleton/body-fields.ts | head -130

Repository: Ryandonofrio3/osgrep

Length of output: 4775


🏁 Script executed:

# Look for grammar or schema definitions in the codebase
find . -type f \( -name "*.json" -o -name "*.ts" -o -name "*.js" \) -path "*/grammar*" 2>/dev/null | head -10

Repository: Ryandonofrio3/osgrep

Length of output: 97


🏁 Script executed:

# Search for Swift-related grammar or schema definitions
rg "class_declaration|init_declaration|deinit_declaration" --type ts --type json -B2 -A2 | head -40

Repository: Ryandonofrio3/osgrep

Length of output: 2406


🏁 Script executed:

# Check if there's documentation about tree-sitter node types
find . -name "*swift*" -type f 2>/dev/null | grep -E "\.(md|txt|json)$" | head -10

Repository: Ryandonofrio3/osgrep

Length of output: 46


🏁 Script executed:

# Check the grammar-loader.ts file
cat -n ./src/lib/index/grammar-loader.ts | head -100

Repository: Ryandonofrio3/osgrep

Length of output: 2413


🏁 Script executed:

# Look for tests or validation that use Swift node types
find . -name "*.test.*" -o -name "*.spec.*" | xargs grep -l "swift" 2>/dev/null | head -5

Repository: Ryandonofrio3/osgrep

Length of output: 46


🏁 Script executed:

# Search for any test files that might validate body-fields
rg "init_declaration|deinit_declaration|function_declaration" --type ts -B2 -A2 | head -50

Repository: Ryandonofrio3/osgrep

Length of output: 2792


🏁 Script executed:

# Check if there's a CONTAINER_TYPES entry for Swift
cat -n ./src/lib/skeleton/body-fields.ts | grep -A 20 "swift:" | tail -20

Repository: Ryandonofrio3/osgrep

Length of output: 741


🏁 Script executed:

# Get full CONTAINER_TYPES section to see if Swift is included
sed -n '127,150p' ./src/lib/skeleton/body-fields.ts

Repository: Ryandonofrio3/osgrep

Length of output: 933


🏁 Script executed:

# Search for any schema files that might define node types
find . -name "*schema*" -o -name "*grammar*" | grep -v node_modules | head -10

Repository: Ryandonofrio3/osgrep

Length of output: 97


🏁 Script executed:

# Check if there's documentation about supported node types
find . -name "README*" -o -name "*.md" | xargs grep -l "swift\|node.type" 2>/dev/null | head -5

Repository: Ryandonofrio3/osgrep

Length of output: 46


🌐 Web query:

tree-sitter-swift 0.7.1 grammar node types class_declaration struct_declaration enum_declaration

💡 Result:

In tree-sitter-swift v0.7.1 the grammar's generated node-types file includes the node types named:

  • class_declaration
  • struct_declaration
  • enum_declaration

You can view the grammar / package (v0.7.1) on the project repo and package metadata. [1][2]

Sources:
[1] alex-pinkus/tree-sitter-swift (GitHub, v0.7.1). [2] tree-sitter-swift package metadata (tree-sitter.json / v0.7.1).


🌐 Web query:

tree-sitter-swift 0.7.1 init_declaration deinit_declaration body field

💡 Result:

Yes — in tree-sitter-swift v0.7.1 the grammar exposes init_declaration and deinit_declaration nodes and places them inside class/protocol bodies (they're used by the package TAGS query). The repository and crate docs show init_declaration and deinit_declaration are matched inside class_body / protocol_body (used as method-like definitions). See the TAGS_QUERY and project repo for v0.7.1. [1][2]

Sources:

  • TAGS_QUERY (shows init_declaration / deinit_declaration inside class_body / protocol_body). [1]
  • tree-sitter-swift v0.7.1 repository (grammar package info, release 0.7.1). [2]

🌐 Web query:

site:github.com tree-sitter-swift v0.7.1 grammar.js node-types.json

💡 Result:

Here are locations for tree-sitter-swift v0.7.1 on GitHub / npm (includes node-types.json and the grammar source):

References
[1] https://github.com/alex-pinkus/tree-sitter-swift.
[2] https://app.unpkg.com/tree-sitter-swift@0.7.1/files/tree-sitter.json.
[3] https://www.jsdelivr.com/package/npm/tree-sitter-swift (package v0.7.1).
[4] https://lib.rs/crates/tree-sitter-swift (shows 0.7.1 release).

Want me to fetch and paste the contents of src/node-types.json or src/grammar.ts/grammar.js for v0.7.1?


🌐 Web query:

tree-sitter-swift 0.7.1 function_declaration struct_declaration enum_declaration body field

💡 Result:

Do you want (A) the exact grammar node shapes for tree-sitter-swift v0.7.1 (so I should fetch and quote the grammar source/grammar.json), (B) examples of how those nodes appear in parse trees, or (C) help matching/extracting those nodes with queries?


🏁 Script executed:

# Check languages.ts to see how Swift is defined and what node types are used
cat -n ./src/lib/core/languages.ts | grep -A 20 "swift"

Repository: Ryandonofrio3/osgrep

Length of output: 930


🏁 Script executed:

# Fetch node-types.json for tree-sitter-swift 0.7.1
curl -s "https://unpkg.com/tree-sitter-swift@0.7.1/src/node-types.json" | head -200

Repository: Ryandonofrio3/osgrep

Length of output: 4166


🏁 Script executed:

# Also try to get grammar.js or grammar structure
curl -s "https://unpkg.com/tree-sitter-swift@0.7.1/package.json" | grep -A 5 -B 5 "version"

Repository: Ryandonofrio3/osgrep

Length of output: 308


🏁 Script executed:

# Extract just the declaration types and their fields from the node-types.json
curl -s "https://unpkg.com/tree-sitter-swift@0.7.1/src/node-types.json" | python3 << 'EOF'
import json
import sys

data = json.load(sys.stdin)

# Filter for declaration types
declarations = [
    "function_declaration", "init_declaration", "deinit_declaration",
    "class_declaration", "struct_declaration", "enum_declaration",
    "protocol_declaration", "property_declaration", "macro_declaration",
    "subscript_declaration"
]

for node in data:
    if node.get("type") in declarations:
        print(f"\n{node['type']}:")
        print(f"  fields: {list(node.get('fields', {}).keys())}")
        if "body" in node.get("fields", {}):
            print(f"    body: {node['fields']['body']}")
EOF

Repository: Ryandonofrio3/osgrep

Length of output: 150


Add missing Swift node type mappings for struct_declaration and enum_declaration.

In tree-sitter-swift 0.7.1, class_declaration, struct_declaration, and enum_declaration are separate node types, not covered by a single type. The mappings at lines 113–120 are incomplete and the comment on line 117 is misleading. Add explicit entries for struct_declaration and enum_declaration to prevent silent failures when eliding struct and enum bodies in Swift code.

🤖 Prompt for AI Agents
In src/lib/skeleton/body-fields.ts around lines 113 to 120, the Swift mapping
only lists class_declaration while tree-sitter-swift 0.7.1 uses separate node
types for class_declaration, struct_declaration, and enum_declaration; update
the mapping to add explicit entries for struct_declaration and enum_declaration
(matching the same value used for class_declaration), and update or remove the
misleading comment about Container so the code will correctly elide struct and
enum bodies instead of silently failing.

c: [],
ruby: ["class", "module"],
php: ["class_declaration", "trait_declaration"],
swift: ["class_declaration", "class_body", "enum_class_body", "protocol_declaration", "protocol_body"],
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cd src/lib/skeleton && find . -name "*body-fields*" -o -name "*CONTAINER*" | head -20

Repository: Ryandonofrio3/osgrep

Length of output: 80


🏁 Script executed:

rg "CONTAINER_TYPES" --type ts -A 5 -B 5 | head -100

Repository: Ryandonofrio3/osgrep

Length of output: 1472


🏁 Script executed:

rg "swift.*class_declaration" --type ts -A 2 -B 2 | head -50

Repository: Ryandonofrio3/osgrep

Length of output: 413


🏁 Script executed:

rg "enum_class_body|struct_declaration|enum_declaration|actor_declaration" --type ts | head -20

Repository: Ryandonofrio3/osgrep

Length of output: 997


🏁 Script executed:

rg "swift" --type ts -i | grep -i "grammar\|node\|tree" | head -30

Repository: Ryandonofrio3/osgrep

Length of output: 291


🏁 Script executed:

find . -name "*.swift" -o -name "*swift*" -o -name "*tree-sitter*" | grep -E "\.(json|md|txt)$" | head -20

Repository: Ryandonofrio3/osgrep

Length of output: 46


🏁 Script executed:

rg "tree-sitter" . --type json --type md | head -30

Repository: Ryandonofrio3/osgrep

Length of output: 265


🏁 Script executed:

rg "BODY_FIELDS" --type ts -A 100 | grep -A 100 "swift:" | head -80

Repository: Ryandonofrio3/osgrep

Length of output: 2010


🏁 Script executed:

rg "struct_declaration|enum_declaration|actor_declaration" --type ts -B 3 -A 1 | grep -E "swift|struct|enum|actor" | head -40

Repository: Ryandonofrio3/osgrep

Length of output: 981


🏁 Script executed:

cat -n src/lib/skeleton/body-fields.ts | head -200

Repository: Ryandonofrio3/osgrep

Length of output: 6656


🏁 Script executed:

find . -name "*.test.*" -o -name "*.spec.*" -o -name "__tests__" -o -name "test*" | head -20

Repository: Ryandonofrio3/osgrep

Length of output: 331


🏁 Script executed:

rg "swift" --type ts | grep -i "test\|example\|grammar\|node" | head -40

Repository: Ryandonofrio3/osgrep

Length of output: 46


🏁 Script executed:

rg "class_declaration|enum_class_body" --type ts -B 5 -A 5 | head -80

Repository: Ryandonofrio3/osgrep

Length of output: 4681


🏁 Script executed:

cat test_skeleton.py | head -150

Repository: Ryandonofrio3/osgrep

Length of output: 95


🏁 Script executed:

rg "swift" . -i -A 3 -B 3 | grep -E "swift|struct|enum|actor|class" | head -60

Repository: Ryandonofrio3/osgrep

Length of output: 793


🏁 Script executed:

find . -path "./node_modules" -prune -o -type f -name "*.swift" -print

Repository: Ryandonofrio3/osgrep

Length of output: 46


🌐 Web query:

tree-sitter-swift 0.7.1 grammar node types struct_declaration enum_declaration actor_declaration

💡 Result:

Yes — tree-sitter-swift v0.7.1 exposes node types for struct_declaration, enum_declaration and actor_declaration (see the crate/github packaging for v0.7.1 which includes the generated node-types.json). [1][2]

Sources:

  • crate docs (node-types included in the v0.7.1 package). [1]
  • repository / package metadata for tree-sitter-swift v0.7.1. [2]

🌐 Web query:

tree-sitter-swift struct_body enum_body actor_body node types

💡 Result:

Yes — the Swift tree-sitter grammar exposes node types for struct/enum/actor bodies via its generated node-types.json. To inspect them:

  • The tree-sitter docs explain the generated node-types.json format (fields, children, named/unamed). [1]
  • The tree-sitter-swift grammar (npm/rust package) is available (package metadata / repo). You can fetch its generated node-types.json from the package or by building the grammar; it contains node types such as struct_body, enum_body and actor_body. See the tree-sitter-swift repository / package pages. [2][3]

How to get the exact node entries:

  • Install or download the tree-sitter-swift package (npm or repo) and open src/node-types.json (or run tree-sitter to generate node-types.json after building). The file lists each node like:
    • "struct_body"
    • "enum_body"
    • "actor_body"
      and shows their fields/children. [1][2][3]

References

  1. Tree-sitter — Static node types / node-types.json docs. [1]
  2. tree-sitter-swift (alex-pinkus) repository / package info. [2]
  3. tree-sitter-swift npm/package metadata (tree-sitter.json listing). [3]

If you want, I can fetch and paste the exact node-types.json entries for struct_body / enum_body / actor_body from the latest tree-sitter-swift release — tell me which release (or “latest”) and I’ll fetch it.


🏁 Script executed:

rg "enum_class_body" --type ts -B 10 -A 10

Repository: Ryandonofrio3/osgrep

Length of output: 2807


🌐 Web query:

tree-sitter-swift "enum_class_body" node type

💡 Result:

Do you want the node's definition/fields from the tree-sitter-swift node-types.json, examples of how it appears in parsed Swift code, or how to query it with a Tree-sitter query?


Add missing Swift container types to CONTAINER_TYPES.swift.

Tree-sitter-swift 0.7.1 exposes separate node types for struct_declaration, enum_declaration, and actor_declaration (each with corresponding _body variants). These should be added to the Swift entry in CONTAINER_TYPES so that methods and nested declarations within structs, enums, and actors are properly recursed into during skeletonization. Currently only class_declaration, class_body, enum_class_body, protocol_declaration, and protocol_body are included, which misses structs and actors entirely and may not correctly handle enums. Also update the code comment on line 117 which incorrectly states that class_declaration "covers class/struct/enum/actor"—these are separate node types in the grammar.

🤖 Prompt for AI Agents
In src/lib/skeleton/body-fields.ts around line 140, the Swift entry in
CONTAINER_TYPES only lists class/protocol nodes and is missing
struct_declaration, struct_body, enum_declaration, enum_body, actor_declaration,
and actor_body; update the array to include these node types so skeletonization
recurses into structs, enums, and actors. Also update the comment at line 117 to
remove the incorrect claim that class_declaration "covers
class/struct/enum/actor" and state that class, struct, enum, and actor are
separate node types in tree-sitter-swift 0.7.1.

Comment on lines +448 to +567
private extractReferencedSymbols(
node: TreeSitterNode,
langId: string,
): string[] {
const refs: string[] = [];
const seen = new Set<string>();

const extract = (n: TreeSitterNode) => {
if (n.type === "call_expression" || n.type === "call") {
const func = n.childForFieldName?.("function");
if (func) {
let funcName = func.text;

// Handle member access (obj.method) - extract just method
if (func.type === "member_expression") {
const prop = func.childForFieldName?.("property");
if (prop) funcName = prop.text;
} else if (func.type === "attribute") {
const attr = func.childForFieldName?.("attribute");
if (attr) funcName = attr.text;
}
const getNavigationIdentifier = (node: TreeSitterNode): string | null => {
if (node.type !== "navigation_expression") return null;
const suffixes = (node.namedChildren || []).filter(
(child) => child.type === "navigation_suffix",
);
const lastSuffix = suffixes[suffixes.length - 1];
if (lastSuffix) {
const simple = (lastSuffix.namedChildren || []).find(
(child) => child.type === "simple_identifier",
);
if (simple?.text) return simple.text;
}
// Fallback: look at nested navigation expressions or identifiers
const fallbacks = [...(node.namedChildren || [])].reverse();
for (const child of fallbacks) {
if (child.type === "simple_identifier" && child.text) {
return child.text;
}
if (child.type === "navigation_expression") {
const nested = getNavigationIdentifier(child);
if (nested) return nested;
}
}
return null;
};

const getCallFunctionNode = (
node: TreeSitterNode,
): TreeSitterNode | null => {
const direct =
node.childForFieldName?.("function") ||
node.childForFieldName?.("name") ||
null;
if (direct) return direct;
return node.namedChildren && node.namedChildren.length > 0
? node.namedChildren[0]
: null;
};

const extractFunctionName = (
func: TreeSitterNode | null,
): string | null => {
if (!func) return null;
if (func.type === "member_expression") {
const prop = func.childForFieldName?.("property");
if (prop?.text) return prop.text;
} else if (func.type === "attribute") {
const attr = func.childForFieldName?.("attribute");
if (attr?.text) return attr.text;
} else if (func.type === "navigation_expression") {
const navName = getNavigationIdentifier(func);
if (navName) return navName;
}

// Dedupe and filter noise
if (funcName && !seen.has(funcName) && funcName.length < 30) {
seen.add(funcName);
refs.push(funcName);
// Fallback: use direct text (strip qualifiers like Module.)
const raw = func.text || "";
if (raw.includes(".")) {
const lastSegment = raw.split(".").pop();
if (lastSegment) return lastSegment;
}
return raw || null;
};

const extractSwiftArgumentLabels = (
callNode: TreeSitterNode,
): string[] => {
const suffix =
callNode.childForFieldName?.("call_suffix") ||
(callNode.namedChildren || []).find(
(child) => child.type === "call_suffix",
);
if (!suffix) return [];

const labels: string[] = [];
const collect = (current: TreeSitterNode) => {
if (current.type === "value_argument") {
const labelNode =
current.childForFieldName?.("label") ||
(current.namedChildren || []).find(
(child) => child.type === "value_argument_label",
);

if (labelNode) {
const simple = (labelNode.namedChildren || []).find(
(child) => child.type === "simple_identifier",
);
labels.push(simple?.text || labelNode.text.replace(/[:\s]/g, ""));
} else {
labels.push("_");
}
} else {
for (const child of current.namedChildren || []) {
collect(child);
}
}
};

collect(suffix);
return labels;
};

const formatSwiftFunction = (
baseName: string,
callNode: TreeSitterNode,
): string => {
const labels = extractSwiftArgumentLabels(callNode);
const meaningful = labels.filter((label) => label && label !== "_");
if (labels.length === 0 || meaningful.length === 0) return baseName;

const truncated = labels.slice(0, 3).map((label) => `${label || "_"}:`);
if (labels.length > 3) truncated.push("…");
return `${baseName}(${truncated.join("")})`;
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Verify tree-sitter-swift AST node and field names against version 0.7.1 grammar.

The code assumes specific AST shapes (navigation_expression, call_suffix, value_argument, value_argument_label, field names function, property, attribute, label) that must match tree-sitter-swift's grammar. If any differ, Swift call summaries will regress to empty or misformatted symbols. Add a fixture test asserting formatting like greet(name:) to lock down this contract.

🤖 Prompt for AI Agents
In src/lib/skeleton/skeletonizer.ts around lines 448 to 567 the Swift
symbol-extraction helpers assume specific tree-sitter-swift node types and field
names (navigation_expression, call_suffix, value_argument, value_argument_label
and fields function/property/attribute/label) which may differ from v0.7.1
grammar; add a fixture unit test that parses a Swift call like `greet(name:)`
and asserts the formatter returns `greet(name:)`, and update the extraction
logic to defensively handle alternate node type/field names used by
tree-sitter-swift v0.7.1 (e.g., accept both
navigation_expression/member_expression variants, search for call argument lists
if call_suffix absent, accept value_argument/value_label variations, and
fallback to scanning namedChildren for identifiers/labels), then run/update
tests and pin or document the required tree-sitter-swift grammar version to
prevent regressions.

Comment on lines +569 to 586
const pushRef = (name: string | null) => {
if (!name) return;
const trimmed = name.trim();
if (!trimmed || trimmed.length >= 30) return;
if (seen.has(trimmed)) return;
seen.add(trimmed);
refs.push(trimmed);
};

const extract = (n: TreeSitterNode) => {
if (n.type === "call_expression" || n.type === "call") {
const funcNode = getCallFunctionNode(n);
let funcName = extractFunctionName(funcNode);
if (funcName && langId === "swift") {
funcName = formatSwiftFunction(funcName, n);
}
pushRef(funcName);
} else if (
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid dropping Swift call symbols just because the formatted signature crosses the 30-char cap.
Right now pushRef() will discard long baseName(label1:label2:…) names, and you don’t fall back to the unformatted base name—so you can lose the call entirely in summaries.

Suggested minimal tweak (fallback to baseName when formatted is too long):

-        if (funcName && langId === "swift") {
-          funcName = formatSwiftFunction(funcName, n);
-        }
-        pushRef(funcName);
+        if (funcName && langId === "swift") {
+          const formatted = formatSwiftFunction(funcName, n);
+          // If the formatted signature is too long, keep at least the base name.
+          pushRef(formatted);
+          if (!seen.has(formatted.trim()) && formatted.trim().length >= 30) {
+            pushRef(funcName);
+          }
+        } else {
+          pushRef(funcName);
+        }
🤖 Prompt for AI Agents
In src/lib/skeleton/skeletonizer.ts around lines 569 to 586, Swift call symbols
are being dropped when the formatted signature exceeds the 30-char limit because
pushRef is only given the formatted name; compute the raw base name (unformatted
function name) before formatting, then for Swift: first try
formatSwiftFunction(funcName, n) and if that result is null/empty or length >=
30, fall back to the unformatted base name (trimmed) before calling pushRef;
keep the existing trimming, seen set checks and pushRef behavior otherwise.

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.

1 participant