Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 8 additions & 24 deletions crates/codegraph-core/src/extractors/fsharp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,31 +355,15 @@ fn extract_value_name(decl_left: &Node, source: &[u8]) -> Option<String> {
}

fn has_function_type(node: &Node) -> bool {
// The two grammar versions use different node shapes for type signatures:
//
// • WASM (tree-sitter-fsharp npm 0.1.0): `function_type` is the explicit
// function-type kind, only present for `a -> b` types.
// • Native (tree-sitter-fsharp 0.3.0): every type signature is wrapped
// in `curried_spec`. For a function it contains `arguments_spec`
// children; for a plain value (e.g. `val pi : float`) it wraps a
// single `simple_type`.
//
// Treat both engines consistently by classifying as a function whenever
// a function_type node appears OR a curried_spec contains `arguments_spec`.
for i in 0..node.child_count() {
let Some(child) = node.child(i) else { continue };
match child.kind() {
"function_type" => return true,
"curried_spec" => {
for j in 0..child.child_count() {
if let Some(g) = child.child(j) {
if g.kind() == "arguments_spec" {
return true;
}
}
}
// The grammar wraps every type signature in `curried_spec`. A function type
// (e.g. `val add : int -> int -> int`) contains one or more `arguments_spec`
// children; a plain value (e.g. `val pi : float`) wraps a single `simple_type`.
let Some(curried) = find_child(node, "curried_spec") else { return false };
for i in 0..curried.child_count() {
if let Some(child) = curried.child(i) {
if child.kind() == "arguments_spec" {
return true;
}
_ => {}
}
}
false
Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@
"tree-sitter-dart": "^1.0.0",

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 GitHub tarball pin has no semver upgrade path

Because the npm registry has no 0.3.0 release, the tarball URL is the right choice here. Worth noting: unlike ^0.x.y semver ranges, npm update will never touch this entry — upgrading to a future release (e.g. 0.4.0) requires a manual URL edit in both package.json and package-lock.json. A short comment in package.json would help future maintainers know why the tarball form was chosen instead of a registry reference.

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 — added a docblock to src/extractors/fsharp.ts explaining (a) why the tarball form is used (no v0.3.0 on npm), (b) that the cargo crate uses the same version, and (c) that upgrading requires a manual URL edit in both package.json and package-lock.json because npm update won't touch this entry. Put it in the extractor docblock rather than package.json since pure JSON doesn't support comments and a _comment field would be non-standard for this repo.

"tree-sitter-elixir": "^0.3.5",
"tree-sitter-erlang": "github:WhatsApp/tree-sitter-erlang#semver:*",
"tree-sitter-fsharp": "^0.1.0",
"tree-sitter-fsharp": "https://github.com/ionide/tree-sitter-fsharp/archive/refs/tags/0.3.0.tar.gz",
"tree-sitter-gleam": "github:gleam-lang/tree-sitter-gleam",
"tree-sitter-go": "^0.25.0",
"tree-sitter-groovy": "^0.1.2",
Expand Down
39 changes: 16 additions & 23 deletions src/extractors/fsharp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ import { findChild, nodeEndLine } from './helpers.js';
/**
* Extract symbols from F# files.
*
* Grammar source: `tree-sitter-fsharp` v0.3.0 installed via a pinned GitHub
* tarball in `package.json` because the ionide/tree-sitter-fsharp project has
* no v0.3.0 release published to the npm registry. The cargo crate the native
* engine uses is also v0.3.0; both engines must stay aligned. Upgrading
* requires a manual edit of the tarball URL in `package.json` and
* `package-lock.json` — `npm update` will not bump this entry.
*
* tree-sitter-fsharp grammar notes:
* - named_module: top-level module declaration
* - function_declaration_left: LHS of `let name params = ...`
Expand Down Expand Up @@ -280,31 +287,17 @@ function handleValueDefinition(
findChild(pattern, 'identifier');
if (!ident) return;

// The two grammar versions use different shapes for type signatures:
// • WASM (npm tree-sitter-fsharp 0.1.0): `function_type` is the explicit
// function-type kind, only present for `a -> b` types.
// • Native (cargo tree-sitter-fsharp 0.3.0): every type signature is
// wrapped in `curried_spec`. For a function it contains `arguments_spec`
// children; for a plain value (e.g. `val pi : float`) it wraps a single
// `simple_type`.
// Treat both engines consistently by classifying as a function whenever
// function_type appears OR a curried_spec contains an arguments_spec child.
// The grammar wraps every type signature in `curried_spec`. A function type
// (e.g. `val add : int -> int -> int`) contains one or more `arguments_spec`
// children; a plain value (e.g. `val pi : float`) wraps a single `simple_type`.
const curriedSpec = findChild(node, 'curried_spec');
let hasFunctionType = false;
for (let i = 0; i < node.childCount; i++) {
const c = node.child(i);
if (!c) continue;
if (c.type === 'function_type') {
hasFunctionType = true;
break;
}
if (c.type === 'curried_spec') {
for (let j = 0; j < c.childCount; j++) {
if (c.child(j)?.type === 'arguments_spec') {
hasFunctionType = true;
break;
}
if (curriedSpec) {
for (let i = 0; i < curriedSpec.childCount; i++) {
if (curriedSpec.child(i)?.type === 'arguments_spec') {
hasFunctionType = true;
break;
}
if (hasFunctionType) break;
}
}

Expand Down
Loading