From fe7542b6f6a4939b89964affeea74f78a1c78b96 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 05:51:51 +0000 Subject: [PATCH 01/23] fix(vbnet): index names that begin with a keyword (SharedCache, Dimension, Sub NewItem) (#2365) The vendored grammar lexed the member modifiers as one prec-10 token and `Sub New` as one prec-100 token. Neither went through keyword extraction, and both outranked the prec(-1) identifier, so the lexer stopped at the end of a modifier spelled at the start of a name: `Public SharedCache` indexed a field `Cache`, `Public Dimension` a field `ension`, `Public Shared Shared1` was lost to a parse error, and `Sub NewItem()` became a constructor. `Dim` and `Const` were part of that token, which also kept the local-declaration `Dim`/`Const` out of keyword extraction, so `ConstVBV.Value = False` and `ConstructPath()` inside a method parsed as `Const` declarations. The modifiers and `Sub New` are now plain keywords. The old tokens also folded a newline into the keyword after it, which two parses relied on by accident: `Option` lines under a comment banner may now follow newlines, and upstream's top-level `file_attribute_section` is gone, so attribute lines above a top-level declaration belong to it. `Protected Friend` and `Private Protected` are two modifiers now; the extractor reads them as protected and private. Rebuilt with tree-sitter-cli 0.25.10 and emscripten 4.0.4. On SCrawler and staxrip, 3 fields get their whole names, staxrip recovers one method, and every other graph difference is an `imports` edge or a node start now on its own line instead of the comment line above. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + .../vbnet-keyword-prefixed-names.test.ts | 242 ++++++++++++++++++ docs/grammars/tree-sitter-vbnet.md | 43 ++++ docs/grammars/tree-sitter-vbnet.patch | 200 +++++++++++---- src/extraction/languages/vbnet.ts | 5 +- src/extraction/wasm/tree-sitter-vbnet.wasm | Bin 6477499 -> 6614160 bytes 6 files changed, 442 insertions(+), 49 deletions(-) create mode 100644 __tests__/vbnet-keyword-prefixed-names.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c5351db2d..1e066c8f62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Axum routes now link to their handler when rustfmt wraps the `.route(` call so the handler sits on a later line, and when the handler's name also appears elsewhere on the line, as in `delete(handlers::user::delete)` or `.route("/login", post(handlers::user::login))`; Actix's `web::resource(…)` and `.route(…)` registrations get the same fix. A call inside a closure handler is no longer mistaken for a route, and an Actix resource no longer takes the next route's handler as its own. Thanks @mg-mg-mg for the report and @danusha2345. (#2326) - In JavaScript and TypeScript, the functions written inside a named object literal are now symbols of their own even when the object isn't exported: a plain `const api = { load() {…} }`, an object declared inside an IIFE or a function, and a namespace hung on the page or on another object, like `window.App = { init() {…} }`, `App.utils = {…}` or `dw_page = {…}`. Calls such as `api.load()`, `window.App.init()`, `App.utils.pad()`, a sibling's `this.render()`, and `App.init()` from another script on the page now reach them, the calls made inside a member belong to that member instead of the object, and a bare `init()` is no longer taken for `App.init`, so script-tag apps no longer lose most of their code from `callers` and impact. A member's qualified name now carries its object, exported or not (`api::load`, `window.App::init`), so asking for `App.init` finds it. Re-index JavaScript and TypeScript projects after upgrading. Thanks @tkhoaaa for the report and @danusha2345. (#2300) - In JavaScript and TypeScript files with Windows (CRLF) line endings, as a Windows checkout usually has them, a store exported on a later line, like `const useStore = create(…)` followed by `export default useStore;`, now has its actions indexed, as it already did with Unix line endings. Before, those actions were missing from the graph on Windows, so their callers and impact came back empty. Re-index JavaScript and TypeScript projects after upgrading. +- In VB.NET, a name that begins with a keyword, like `SharedCache`, `Dimension`, `PublicKey` or `FriendlyName`, is now indexed whole, and a method like `Sub NewItem()` is no longer taken for a constructor. Before, the keyword was cut off (`Cache`, `ension`, `Key`) or the declaration was lost, and a line in a method that starts with such a name, like `Constants.Reload()` or `ConstVBV.Value = False`, was misread as a declaration, so reads of and calls to these names didn't link. A `Private Protected` member now counts as private instead of public. Re-index VB.NET projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/vbnet-keyword-prefixed-names.test.ts b/__tests__/vbnet-keyword-prefixed-names.test.ts new file mode 100644 index 0000000000..271e1dd642 --- /dev/null +++ b/__tests__/vbnet-keyword-prefixed-names.test.ts @@ -0,0 +1,242 @@ +/** + * VB.NET names that begin with a keyword. + * + * The vendored grammar lexed the member modifiers (`Public`, `Shared`, `Dim`, + * `Const`, …) as one token that outranked identifiers, so the lexer stopped at + * the end of a modifier spelled at the start of a name: `Public SharedCache As + * Integer` indexed a field `Cache`, `Public Dimension` a field `ension`, + * `Private FriendlyNameValue` (staxrip) a field `lyNameValue`, and `Public + * Shared Shared1` lost the field to a parse error. Inside a method `Dim` and + * `Const` did the same: `ConstVBV.Value = False` (staxrip) parsed as a + * declaration `Const VBV`, and `ConstructPath()` as `Const ructPath()`. And + * `Sub NewItem()` lexed as the constructor `Sub New` followed by `Item`. + * + * Two things the old lexing got right only by accident are pinned too: the + * attribute lines above a top-level declaration belong to it, and `Option` + * lines may follow a comment banner. + */ +import { describe, it, expect, afterAll, beforeAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; +import { extractFromSource } from '../src/extraction'; +import { getParser, initGrammars, loadGrammarsForLanguages } from '../src/extraction/grammars'; + +// The issue's class, verbatim. +const HOLDER = `Public Class Holder + Public Shared Shared1 As Integer + Public Shared SharedCache As Integer + Public Dimension As Integer + Public Endpoint As String + Public PublicKey As String + Private Property1 As Integer + Public Shared Function SharedHelper() As Integer + Return 1 + End Function + Public Sub EndSession() + End Sub + Public Normal As Integer +End Class +`; + +const MODIFIERS = [ + 'Public', 'Private', 'Protected', 'Friend', 'ReadOnly', 'WriteOnly', 'Shared', 'Shadows', 'MustInherit', + 'NotInheritable', 'Overrides', 'NotOverridable', 'Overridable', 'Overloads', 'WithEvents', 'Widening', + 'Narrowing', 'Partial', 'Async', 'Iterator', 'Dim', 'Const', 'Static', 'MustOverride', +]; + +function namesOf(source: string, kind: string): string[] { + return extractFromSource('Probe.vb', source).nodes.filter((n) => n.kind === kind).map((n) => n.name); +} + +beforeAll(async () => { + await initGrammars(); + await loadGrammarsForLanguages(['vbnet']); +}); + +describe('VB.NET names that begin with a keyword', () => { + it('index the fields of the issue under their whole names', () => { + expect(namesOf(HOLDER, 'field')) + .toEqual(['Shared1', 'SharedCache', 'Dimension', 'Endpoint', 'PublicKey', 'Property1', 'Normal']); + expect(namesOf(HOLDER, 'method')).toEqual(['SharedHelper', 'EndSession']); + }); + + it('keep every member modifier out of a name it begins, in any case', () => { + const source = [ + 'Public Class Fields', + ...MODIFIERS.flatMap((m) => [ + ` Private ${m}Field As Integer`, + ` PUBLIC SHARED ${m.toUpperCase()}UPPER As Integer`, + ` friend ${m.toLowerCase()}lower As Integer`, + ]), + 'End Class', + '', + ].join('\n'); + expect(namesOf(source, 'field')).toEqual( + MODIFIERS.flatMap((m) => [`${m}Field`, `${m.toUpperCase()}UPPER`, `${m.toLowerCase()}lower`]), + ); + }); + + it('still read the modifiers themselves', () => { + const source = `Public Class Settings + Public Shared ReadOnly Limit As Integer = 1 + Public Shared SharedCache As Integer + Protected Friend Inherited As Integer + Private Protected Derived As Integer + Friend FriendlyName As String + Private Const ConstantRate As Integer = 2 +End Class +`; + const fields = new Map(extractFromSource('Probe.vb', source).nodes + .filter((n) => n.kind === 'field' || n.kind === 'constant') + .map((n) => [n.name, n])); + expect([...fields.keys()]).toEqual(['Limit', 'SharedCache', 'Inherited', 'Derived', 'FriendlyName', 'ConstantRate']); + expect(fields.get('SharedCache')?.isStatic).toBe(true); + expect(fields.get('Inherited')?.visibility).toBe('protected'); + // `Private Protected` was one token that matched no visibility, so it read as public. + expect(fields.get('Derived')?.visibility).toBe('private'); + expect(fields.get('FriendlyName')?.visibility).toBe('internal'); + }); + + it('tell Sub New from a method whose name begins with New', () => { + const source = `Public Class Menu + Public Sub New() + End Sub + Shared Sub New() + End Sub + Private Sub NewFromDefaultsToolStripMenuItem_Click() Handles NewFromDefaultsToolStripMenuItem.Click + End Sub + Public Sub NewItem() + End Sub +End Class +`; + expect(namesOf(source, 'method')).toEqual(['New', 'New', 'NewFromDefaultsToolStripMenuItem_Click', 'NewItem']); + }); + + it('keep a statement that begins with Dim or Const a statement', () => { + const source = `Public Class Encoder + Private ConstVBV As New BoolParam() + Sub Apply() + ConstVBV.Value = False + ConstVBV.Reset() + ConstructPath() + DimSomething() + Constants.Reload() + Dim constructor As Object = Nothing + constructor = Nothing + End Sub +End Class +`; + const result = extractFromSource('Probe.vb', source); + expect(result.nodes.filter((n) => n.kind === 'field').map((n) => n.name)).toEqual(['ConstVBV']); + const refs = result.unresolvedReferences + .filter((r) => r.referenceKind === 'calls' || r.referenceKind === 'references') + .map((r) => `${r.referenceKind} ${r.referenceName}`); + expect(refs).toEqual([ + 'references ConstVBV.Value', + 'calls ConstVBV.Reset', + 'calls ConstructPath', + 'calls DimSomething', + 'calls Constants.Reload', + ]); + }); +}); + +describe('VB.NET top-level lines', () => { + it('give a declaration every attribute line above it', () => { + const source = `Imports System + + + +Public Class Settings +End Class + + +Class Plain +End Class +`; + const classes = extractFromSource('Probe.vb', source).nodes.filter((n) => n.kind === 'class'); + expect(classes.map((n) => [n.name, n.startLine])).toEqual([['Settings', 3], ['Plain', 8]]); + }); + + it('parse Option lines after a comment banner', () => { + const source = `'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + +Namespace My.Resources + Friend Module Resources + End Module +End Namespace +`; + const tree = getParser('vbnet')!.parse(source)!; + try { + expect(tree.rootNode.hasError).toBe(false); + expect(tree.rootNode.descendantsOfType('option_statement')).toHaveLength(2); + } finally { + tree.delete(); + } + }); +}); + +describe('VB.NET references to keyword-prefixed names', () => { + let root = ''; + let cg: CodeGraph; + const files: Record = { + 'Holder.vb': HOLDER.replace(' Public Normal As Integer\n', ` Public Normal As Integer + Public Sub NewItem() + End Sub +`), + 'Constants.vb': `Public Module Constants + Public Sub Reload() + End Sub +End Module +`, + 'User.vb': `Public Class User + Public Sub Run(x As Holder) + Dim a As Integer = Holder.Dimension + Holder.SharedCache = 2 + Dim c As Integer = Holder.Shared1 + Holder.SharedHelper() + Dim h As New Holder() + h.NewItem() + Constants.Reload() + End Sub +End Class +`, + }; + + beforeAll(async () => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-vb-keyword-names-')); + for (const [rel, content] of Object.entries(files)) fs.writeFileSync(path.join(root, rel), content); + cg = await CodeGraph.init(root, { index: true }); + }); + + afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + }); + + function linkedFrom(qualifiedName: string, kind: 'references' | 'calls'): string[] { + const found = cg.getNodesInFiles(Object.keys(files)).filter((n) => n.qualifiedName === qualifiedName); + expect(found.map((n) => n.qualifiedName)).toEqual([qualifiedName]); + return cg.getIncomingEdgesTo([found[0]!.id], [kind]).map((e) => cg.getNode(e.source)!.qualifiedName); + } + + it('link reads and writes through the class to the field', () => { + expect(linkedFrom('Holder::Dimension', 'references')).toEqual(['User::Run']); + expect(linkedFrom('Holder::SharedCache', 'references')).toEqual(['User::Run']); + expect(linkedFrom('Holder::Shared1', 'references')).toEqual(['User::Run']); + }); + + it('link calls to methods whose names begin with a keyword', () => { + expect(linkedFrom('Holder::SharedHelper', 'calls')).toEqual(['User::Run']); + expect(linkedFrom('Holder::NewItem', 'calls')).toEqual(['User::Run']); + expect(linkedFrom('Constants::Reload', 'calls')).toEqual(['User::Run']); + }); +}); diff --git a/docs/grammars/tree-sitter-vbnet.md b/docs/grammars/tree-sitter-vbnet.md index 3de667d35f..4aa84e257d 100644 --- a/docs/grammars/tree-sitter-vbnet.md +++ b/docs/grammars/tree-sitter-vbnet.md @@ -82,6 +82,31 @@ on those repos plus SCrawler and PCL: 12. **LINQ queries** — query expressions no longer require a trailing `Select`/`Group` clause, `Aggregate`-led queries, and `Distinct`/`Skip`/`Take` clauses. +13. **Names that begin with a keyword** — upstream lexed every member + modifier as one `token(prec(10, choice(…)))` and `Sub New` as one + `token(prec(100, …))`. A token that outranks the `prec(-1)` identifier + ends where its text ends, so `Public SharedCache` lexed as `Shared` + + `Cache`, `Public Dimension` as `Dim` + `ension`, and `Sub NewItem()` as a + constructor followed by `Item`. `Dim` and `Const` also appeared inside + that token, which kept the local-declaration `Dim`/`Const` out of keyword + extraction too, so `Constants.X = 1` in a method lexed as `Const ants.X`. + The modifiers and `Sub New` are now plain keywords, which the `word` + lexer matches only after it has read the whole identifier. `Protected + Friend` and `Private Protected` parse as two modifiers, and `prec(1)` on + `member_modifier` keeps a line that could start either a member or a + local declaration read as a member, as before. + The high-precedence tokens had also let the lexer fold a newline into the + keyword after it. Two parses depended on that by accident, so they are + now part of the grammar. `option_statements` may begin with newlines (an + `Option` line under a comment banner, as in every `My Project` + designer file). Upstream's top-level `file_attribute_section` is gone, so + every attribute line above a top-level declaration belongs to that + declaration, as one inside a class or namespace already did. + Measured on all five corpora below: clean parses rose on staxrip (138 → + 141 of 145) and fell nowhere. Apart from the fixed names and the + positions of the newlines no longer folded into a keyword, the trees + changed only where `Protected Friend` became two modifiers and where an + attribute line now attaches to its declaration. ### External scanner (`src/scanner.c`, new) @@ -130,6 +155,16 @@ Known remaining gap (localized ERROR regions, deliberately unpatched): `word:` stays and column-0 labels keep a localized error; indented labels parse fine. Worth an upstream tree-sitter investigation eventually. +Before changing a keyword rule, run `tree-sitter generate --log` and read the +`Keywords - exclude …` lines. A keyword-shaped token that is left out of +keyword extraction is lexed with its own precedence, and if that precedence is +above the identifier's it splits every identifier that starts with it. Those +lines name the tokens left out and the reason: a token that matches the same +string as another one, or that conflicts with a token, such as `"\n"`. Four +remain: `Inherits`, plain `Implements` and both spellings of `IsNot`. Valid VB +never starts a name where one of them can appear, so they split nothing in +valid code. + ## Rebuild ```bash @@ -156,6 +191,14 @@ npx tree-sitter generate # src/scanner.c from the patch is picked u npx tree-sitter build --wasm -o tree-sitter-vbnet.wasm # needs emscripten or Docker ``` +The CLI's Docker fallback uses emscripten 4.0.4. A local emsdk at the same +version works too, including on Windows (`emsdk install 4.0.4`, +`emsdk activate 4.0.4`, then `emsdk_env`). Built that way from this patch, +the vendored wasm's sha256 is +`5a8aa2911e28e43e22b077ae56c8143ccfe52485bb6719152b60e2e66a1a9e53`. The +wasm this one replaced did not rebuild byte for byte with that toolchain, but +the rebuild parsed every file in SCrawler and staxrip to the same tree. + Upstream's checked-in `test/corpus` expectations predate its own grammar.js (every corpus test fails at the pinned commit, before any patching), so the five-repo parse-health sweep above — plus 16 construct repros and the diff --git a/docs/grammars/tree-sitter-vbnet.patch b/docs/grammars/tree-sitter-vbnet.patch index 8caba699fb..37918d81ed 100644 --- a/docs/grammars/tree-sitter-vbnet.patch +++ b/docs/grammars/tree-sitter-vbnet.patch @@ -1,5 +1,5 @@ diff --git a/grammar.js b/grammar.js -index 21c8523..00bf2b1 100644 +index 21c8523..c9c1d85 100644 --- a/grammar.js +++ b/grammar.js @@ -21,10 +21,14 @@ const PRECEDENCE = { @@ -53,14 +53,46 @@ index 21c8523..00bf2b1 100644 [ $.class_declaration, $.structure_declaration, -@@ -89,7 +88,6 @@ module.exports = grammar({ +@@ -89,30 +88,29 @@ module.exports = grammar({ ], ], - word: ($) => $._identifier_token, rules: { ++ // An attribute list on the line above a top-level declaration belongs to ++ // it: VB continues the line after the closing `>`. With no standalone ++ // attribute-line rule, the newline after the list is an extra here, as it ++ // already is inside a class or namespace. source_file: ($) => + seq( + optional($.option_statements), + repeat(choice( + prec(10, $.imports_statement), + prec(10, $.global_attribute_section), +- prec(10, $.file_attribute_section), + $._declaration, + $._statement, + $._block_terminator + )) + ), + +- file_attribute_section: ($) => +- seq( +- $.attribute_list, +- $._terminator +- ), +- +- +- option_statements: ($) => repeat1($.option_statement), ++ // Files often open with a comment banner, so newlines may come before the ++ // first `Option` line. Only this path can be followed by `Option`, so it ++ // needs no precedence against a top-level empty line. ++ option_statements: ($) => ++ seq(optional($._block_terminator), repeat1($.option_statement)), + + option_statement: ($) => + seq( @@ -157,13 +155,14 @@ module.exports = grammar({ ), @@ -79,15 +111,87 @@ index 21c8523..00bf2b1 100644 identifier: ($) => choice( -@@ -194,7 +193,6 @@ module.exports = grammar({ - ci("MustInherit"), - ci("NotInheritable"), - ci("Overrides"), +@@ -174,41 +173,45 @@ module.exports = grammar({ + _implements_keyword: ($) => token(prec(10, ci("Implements"))), + _inherits_keyword: ($) => token(prec(10, ci("Inherits"))), + +- _sub_new: ($) => token(prec(100, seq(ci("Sub"), /\s+/, ci("New")))), +- ++ // `Sub New` as two keywords rather than one token(prec(100, ...)). The ++ // single token ended at `New`, so `Sub NewItem()` lexed as a constructor ++ // followed by a stray `Item`. The keyword lexer reads `NewItem` whole. ++ _sub_new: ($) => seq(ci("Sub"), ci("New")), ++ ++ // Each modifier is its own keyword, not one token(prec(10, choice(...))). ++ // That token outranked the prec(-1) identifier, so the lexer stopped at the ++ // end of a modifier spelled at the start of a name: `Public SharedCache` ++ // lexed as Shared + Cache, `Public Dimension` as Dim + ension. Keywords go ++ // through the `word` lexer, which reads the whole identifier first. ++ // `Protected Friend` and `Private Protected` are two modifiers. `Dim` and ++ // `Const` are now the same tokens as local_declaration_modifier's, so ++ // `Constants.X = 1` no longer lexes as `Const ants.X = 1`; prec(1) keeps ++ // the old reading (a member modifier) where a line could start either. + member_modifier: ($) => +- token( +- prec( +- 10, +- choice( +- ci("Public"), +- ci("Private"), +- ci("Protected"), +- ci("Friend"), +- ci("Protected Friend"), +- ci("Private Protected"), +- ci("ReadOnly"), +- ci("WriteOnly"), +- ci("Shared"), +- ci("Shadows"), +- ci("MustInherit"), +- ci("NotInheritable"), +- ci("Overrides"), - ci("MustOverride"), - ci("NotOverridable"), - ci("Overridable"), - ci("Overloads"), -@@ -225,43 +223,6 @@ module.exports = grammar({ +- ci("NotOverridable"), +- ci("Overridable"), +- ci("Overloads"), +- ci("WithEvents"), +- ci("Widening"), +- ci("Narrowing"), +- ci("Partial"), +- ci("Async"), +- ci("Iterator"), +- ci("Dim"), +- ci("Const") +- ) +- ) +- ), ++ prec(1, choice( ++ ci("Public"), ++ ci("Private"), ++ ci("Protected"), ++ ci("Friend"), ++ ci("ReadOnly"), ++ ci("WriteOnly"), ++ ci("Shared"), ++ ci("Shadows"), ++ ci("MustInherit"), ++ ci("NotInheritable"), ++ ci("Overrides"), ++ ci("NotOverridable"), ++ ci("Overridable"), ++ ci("Overloads"), ++ ci("WithEvents"), ++ ci("Widening"), ++ ci("Narrowing"), ++ ci("Partial"), ++ ci("Async"), ++ ci("Iterator"), ++ ci("Dim"), ++ ci("Const") ++ )), + + _method_body_statement: ($) => + choice( +@@ -225,43 +228,6 @@ module.exports = grammar({ $._statement // Fallback to regular statements ), @@ -131,7 +235,7 @@ index 21c8523..00bf2b1 100644 local_declaration_modifier: ($) => choice(ci("Dim"), ci("Const"), ci("Static")), -@@ -300,6 +261,8 @@ module.exports = grammar({ +@@ -300,6 +266,8 @@ module.exports = grammar({ _primary_expression: ($) => choice( $._literal, @@ -140,7 +244,7 @@ index 21c8523..00bf2b1 100644 $.identifier, $.parenthesized_expression, $.generic_invocation_expression, // Add this before regular invocation -@@ -320,17 +283,26 @@ module.exports = grammar({ +@@ -320,17 +288,26 @@ module.exports = grammar({ ), generic_invocation_expression: ($) => @@ -170,7 +274,7 @@ index 21c8523..00bf2b1 100644 member_access_expression: ($) => prec.left( PRECEDENCE.MEMBER_ACCESS, -@@ -350,20 +322,23 @@ module.exports = grammar({ +@@ -350,20 +327,23 @@ module.exports = grammar({ ) ), @@ -199,7 +303,7 @@ index 21c8523..00bf2b1 100644 ")" ) ), -@@ -471,16 +446,53 @@ module.exports = grammar({ +@@ -471,16 +451,53 @@ module.exports = grammar({ ), lambda_expression: ($) => @@ -258,7 +362,7 @@ index 21c8523..00bf2b1 100644 typeof_is_expression: ($) => prec.left( -@@ -488,7 +500,7 @@ module.exports = grammar({ +@@ -488,7 +505,7 @@ module.exports = grammar({ seq( ci("TypeOf"), field("expression", $._expression), @@ -267,7 +371,7 @@ index 21c8523..00bf2b1 100644 field("type", $._type) ) ), -@@ -504,29 +516,12 @@ module.exports = grammar({ +@@ -504,29 +521,12 @@ module.exports = grammar({ "initializer", choice( $.object_initializer, @@ -298,7 +402,7 @@ index 21c8523..00bf2b1 100644 object_initializer: ($) => -@@ -551,6 +546,8 @@ module.exports = grammar({ +@@ -551,6 +551,8 @@ module.exports = grammar({ collection_initializer: ($) => seq(ci("From"), "{", commaSep($._expression), "}"), @@ -307,7 +411,7 @@ index 21c8523..00bf2b1 100644 array_creation_expression: ($) => seq( -@@ -646,6 +643,9 @@ module.exports = grammar({ +@@ -646,6 +648,9 @@ module.exports = grammar({ seq(field("object", $._expression), "!", field("member", $.identifier)), _literal: ($) => choice( @@ -317,7 +421,7 @@ index 21c8523..00bf2b1 100644 $.string_literal, $.character_literal, $.integer_literal, -@@ -654,16 +654,49 @@ module.exports = grammar({ +@@ -654,16 +659,49 @@ module.exports = grammar({ $.nothing_literal, $.date_literal ), @@ -371,7 +475,7 @@ index 21c8523..00bf2b1 100644 ) ), boolean_literal: ($) => choice(ci("True"), ci("False")), -@@ -672,7 +705,7 @@ module.exports = grammar({ +@@ -672,7 +710,7 @@ module.exports = grammar({ // Names and types _name_reference: ($) => @@ -380,7 +484,7 @@ index 21c8523..00bf2b1 100644 simple_name: ($) => $.identifier, -@@ -682,7 +715,7 @@ module.exports = grammar({ +@@ -682,7 +720,7 @@ module.exports = grammar({ seq( field("qualifier", $._name_reference), ".", @@ -389,7 +493,7 @@ index 21c8523..00bf2b1 100644 ) ), global_qualified_name: ($) => -@@ -694,6 +727,7 @@ module.exports = grammar({ +@@ -694,6 +732,7 @@ module.exports = grammar({ $.simple_name, $.qualified_name, $.generic_name, @@ -397,7 +501,7 @@ index 21c8523..00bf2b1 100644 $.predefined_type, $.array_type, $.tuple_type -@@ -720,7 +754,8 @@ module.exports = grammar({ +@@ -720,7 +759,8 @@ module.exports = grammar({ ), generic_name: ($) => seq(field("name", $.identifier), $.type_argument_list), @@ -407,7 +511,7 @@ index 21c8523..00bf2b1 100644 array_type: ($) => seq(field("element_type", $._type), $.array_rank_specifier), array_rank_specifier: ($) => seq("(", repeat(","), ")"), -@@ -742,10 +777,14 @@ module.exports = grammar({ +@@ -742,10 +782,14 @@ module.exports = grammar({ field("type", $._type) ), @@ -426,7 +530,7 @@ index 21c8523..00bf2b1 100644 implements_member_clause: ($) => seq(ci("Implements"), commaSep1($._name_reference)), -@@ -856,7 +895,7 @@ module.exports = grammar({ +@@ -856,7 +900,7 @@ module.exports = grammar({ enum_member_declaration: ($) => seq( @@ -435,7 +539,7 @@ index 21c8523..00bf2b1 100644 field("name", $.identifier), optional(seq("=", field("value", $._expression))), $._terminator -@@ -882,6 +921,10 @@ module.exports = grammar({ +@@ -882,6 +926,10 @@ module.exports = grammar({ prec(10, $.inherits_statement), prec(10, $.implements_statement), prec(100, $.constructor_declaration), @@ -446,7 +550,7 @@ index 21c8523..00bf2b1 100644 // Explicitly add statements that can appear at class level prec(200, $.try_statement), // Very high precedence prec(200, $.select_statement), // Very high precedence -@@ -936,33 +979,21 @@ module.exports = grammar({ +@@ -936,33 +984,21 @@ module.exports = grammar({ variable_declarator: ($) => seq( field("name", $.identifier), @@ -483,7 +587,7 @@ index 21c8523..00bf2b1 100644 optional(field("modifiers", repeat1($.member_modifier))), commaSep1($.variable_declarator), $._terminator -@@ -970,7 +1001,8 @@ module.exports = grammar({ +@@ -970,7 +1006,8 @@ module.exports = grammar({ field_variable_declarator: ($) => seq( @@ -493,7 +597,7 @@ index 21c8523..00bf2b1 100644 optional($.array_rank_specifier), optional($.as_clause), optional(seq("=", field("initializer", $._expression))) -@@ -978,12 +1010,13 @@ module.exports = grammar({ +@@ -978,12 +1015,13 @@ module.exports = grammar({ property_declaration: ($) => seq( @@ -509,7 +613,7 @@ index 21c8523..00bf2b1 100644 optional($.implements_member_clause), optional(seq("=", field("initializer", $._expression))), choice( -@@ -1001,7 +1034,7 @@ module.exports = grammar({ +@@ -1001,7 +1039,7 @@ module.exports = grammar({ property_getter: ($) => seq( @@ -518,7 +622,7 @@ index 21c8523..00bf2b1 100644 optional(field("modifiers", repeat1($.member_modifier))), ci("Get"), $._block_terminator, -@@ -1013,7 +1046,7 @@ module.exports = grammar({ +@@ -1013,7 +1051,7 @@ module.exports = grammar({ property_setter: ($) => seq( @@ -527,7 +631,7 @@ index 21c8523..00bf2b1 100644 optional(field("modifiers", repeat1($.member_modifier))), ci("Set"), optional(seq("(", field("parameter", $.parameter), ")")), -@@ -1028,7 +1061,7 @@ module.exports = grammar({ +@@ -1028,7 +1066,7 @@ module.exports = grammar({ prec( 1, seq( @@ -536,7 +640,7 @@ index 21c8523..00bf2b1 100644 optional(field("modifiers", repeat1($.member_modifier))), choice( seq( -@@ -1063,7 +1096,7 @@ module.exports = grammar({ +@@ -1063,7 +1101,7 @@ module.exports = grammar({ prec( 100, seq( @@ -545,7 +649,7 @@ index 21c8523..00bf2b1 100644 optional(field("modifiers", repeat1($.member_modifier))), $._sub_new, optional(field("parameters", $.parameter_list)), -@@ -1087,7 +1120,7 @@ module.exports = grammar({ +@@ -1087,7 +1125,7 @@ module.exports = grammar({ event_declaration: ($) => seq( @@ -554,7 +658,7 @@ index 21c8523..00bf2b1 100644 optional(field("modifiers", repeat1($.member_modifier))), // Changed ci("Event"), field("name", $.identifier), -@@ -1098,7 +1131,7 @@ module.exports = grammar({ +@@ -1098,7 +1136,7 @@ module.exports = grammar({ operator_declaration: ($) => seq( @@ -563,7 +667,7 @@ index 21c8523..00bf2b1 100644 optional(field("modifiers", repeat1($.member_modifier))), // Changed ci("Operator"), field( -@@ -1152,7 +1185,7 @@ module.exports = grammar({ +@@ -1152,7 +1190,7 @@ module.exports = grammar({ interface_method_declaration: ($) => seq( @@ -572,7 +676,7 @@ index 21c8523..00bf2b1 100644 optional(field("modifiers", repeat1($.member_modifier))), // Changed choice(ci("Sub"), ci("Function")), field("name", $.identifier), -@@ -1164,7 +1197,7 @@ module.exports = grammar({ +@@ -1164,7 +1202,7 @@ module.exports = grammar({ interface_property_declaration: ($) => seq( @@ -581,7 +685,7 @@ index 21c8523..00bf2b1 100644 optional(field("modifiers", repeat1($.member_modifier))), // Changed ci("Property"), field("name", $.identifier), -@@ -1175,7 +1208,7 @@ module.exports = grammar({ +@@ -1175,7 +1213,7 @@ module.exports = grammar({ interface_event_declaration: ($) => seq( @@ -590,7 +694,7 @@ index 21c8523..00bf2b1 100644 optional(field("modifiers", repeat1($.member_modifier))), // Changed ci("Event"), field("name", $.identifier), -@@ -1209,7 +1242,7 @@ module.exports = grammar({ +@@ -1209,7 +1247,7 @@ module.exports = grammar({ parameter: ($) => seq( @@ -599,7 +703,7 @@ index 21c8523..00bf2b1 100644 optional( field( "modifiers", -@@ -1273,7 +1306,7 @@ module.exports = grammar({ +@@ -1273,7 +1311,7 @@ module.exports = grammar({ declaration_statement: ($) => prec(1, seq( // Add precedence @@ -608,7 +712,7 @@ index 21c8523..00bf2b1 100644 field("modifiers", choice( $.local_declaration_modifier, repeat1($.local_declaration_modifier) -@@ -1282,6 +1315,65 @@ module.exports = grammar({ +@@ -1282,6 +1320,65 @@ module.exports = grammar({ $._terminator )), @@ -674,7 +778,7 @@ index 21c8523..00bf2b1 100644 expression_statement: ($) => seq($._expression, $._terminator), assignment_statement: ($) => -@@ -1301,21 +1393,96 @@ module.exports = grammar({ +@@ -1301,21 +1398,96 @@ module.exports = grammar({ $._terminator ) ), @@ -775,7 +879,7 @@ index 21c8523..00bf2b1 100644 $._block_terminator, field("then_branch", repeat($._statement)), repeat($.elseif_clause), -@@ -1331,7 +1498,7 @@ module.exports = grammar({ +@@ -1331,7 +1503,7 @@ module.exports = grammar({ seq( ci("ElseIf"), field("condition", $._expression), @@ -784,7 +888,7 @@ index 21c8523..00bf2b1 100644 $._block_terminator, field("body", repeat($._statement)) ), -@@ -1445,7 +1612,7 @@ module.exports = grammar({ +@@ -1445,7 +1617,7 @@ module.exports = grammar({ using_statement: ($) => seq( ci("Using"), @@ -793,7 +897,7 @@ index 21c8523..00bf2b1 100644 $._block_terminator, field("body", repeat($._statement)), ci("End"), -@@ -1590,14 +1757,25 @@ module.exports = grammar({ +@@ -1590,14 +1762,25 @@ module.exports = grammar({ $._terminator ), // LINQ Query expressions query_expression: ($) => @@ -826,7 +930,7 @@ index 21c8523..00bf2b1 100644 ), query_body_clause: ($) => choice( -@@ -1606,48 +1784,62 @@ module.exports = grammar({ +@@ -1606,48 +1789,62 @@ module.exports = grammar({ $.where_clause, $.join_clause, $.order_by_clause, @@ -914,7 +1018,7 @@ index 21c8523..00bf2b1 100644 aggregate_function: ($) => seq( field( -@@ -1668,42 +1860,44 @@ module.exports = grammar({ +@@ -1668,42 +1865,44 @@ module.exports = grammar({ select_or_group_clause: ($) => choice($.select_clause, $.group_by_clause), select_clause: ($) => seq(ci("Select"), commaSep1($.select_element)), select_element: ($) => @@ -973,7 +1077,7 @@ index 21c8523..00bf2b1 100644 // Comments comment: ($) => token(prec(100, choice( -@@ -1714,7 +1908,7 @@ module.exports = grammar({ +@@ -1714,7 +1913,7 @@ module.exports = grammar({ ))), // Preprocessor Directives diff --git a/src/extraction/languages/vbnet.ts b/src/extraction/languages/vbnet.ts index e8502b2e30..35f6349538 100644 --- a/src/extraction/languages/vbnet.ts +++ b/src/extraction/languages/vbnet.ts @@ -87,9 +87,12 @@ export const vbnetExtractor: LanguageExtractor = { // this, calls inside every Sub/Function would be skipped. resolveBody: (node: SyntaxNode) => node, getReturnType: extractVbnetReturnType, + // `Protected Friend` and `Private Protected` are two modifiers each, so they + // read as protected and private, like C#'s `protected internal` and + // `private protected`. getVisibility: (node) => { if (hasModifier(node, /^private$/i)) return 'private'; - if (hasModifier(node, /^protected(\s+friend)?$/i)) return 'protected'; + if (hasModifier(node, /^protected$/i)) return 'protected'; if (hasModifier(node, /^friend$/i)) return 'internal'; return 'public'; // VB members default to Public in practice }, diff --git a/src/extraction/wasm/tree-sitter-vbnet.wasm b/src/extraction/wasm/tree-sitter-vbnet.wasm index 365a6c6035cfca1ce761e7ad02ae99ea54f47625..c09cc4746ab28b809b2f13a3cea91a880dcbb1b8 100755 GIT binary patch literal 6614160 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�T#n&xZT;yHD5>VB-k-Aezb)wAx6;@FPgTSs!* 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�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 z zXx{+sQ=-19z+Vu*CE|aD{Tp};>emqc|A7Bj^q(4>20Rw=M`1mDgnw(~-w64HLA}Ny zepuKWqkR)_Ec6!+?aPD1gPS7Wc;vGJ>uCb)5fHB#;!Q-oCV?k|pX0hX9qOANTn3*n zn2vaZVV_~xJ${euoyxl}JFHaMtmgC4<``ECa7NT61M-ZBI;}G5>hb#rc{r@p*KB4U ztBrQ@9sJ0nE!IOuCl7Z&_W0d)`T;8?-%B8md4G>*1@`Go7+)*&y9Rl+!+2Z6za8?7 z1phYhZx8>q=&vpOGok*O!CAna5I-yInKAx$=r0@mvx7S${vY5j;2db56MPfr@m#Ry z2Im3i1$RaNd!6|1I#Ftv^SwWsQ{(zOpA%2pN5VgiCnC) z+IPeFB4fQx#QbIf7e>4&XkP^OqTt`a>#=^jBfoF(4@7^(U@s1CkM)@e?f(FGfd4eu zTY!5Y-;(IRC+wwQ{~cT!yaDx@fc4%B@uR`s8}?0z*9Z2#;04BcLaA2H`1ShThVx1p z0`3al zi}7`Xy*s$Slb@cDM!4SIhU2~m+8=_wC+tUH4@Nx(fM;P{4TOCVxEK06js9X|Us{Rv zG8pmpp?-Z3e?RPfVV{V7>IdxQg3Q;Ul7aidKO^jOP@iD<=Z1X%>;u6!QLj8`KMy<@ z?Z2V@P}svF|6#Bvfqew*$-r50o)`uD0_2+)JOuMS2JOe-_#O)X`RG3%;^zl10v7;} zL;pX)i{U>E`3wgq#CjhA`$+Hv^fwCjv8cy5@FcV^fclJw|77@&Mt@UaUxM*Zg?$?M zPx$vhKA+$}9Xtm4j0G=6{5FW64LlL!pW*bU_uJXnZ^xm(NoYSF_Q|kM0WU+oiJkS~ z_U{S6-w}hAnuYp|!uV#xz7G5AX!y^C|9bfUg?y7>Jx{>+CxW|RKS_%A$-wiG&lcpf z6}$lc+h8A${%3&qfa4@la?{H}l>;w@e>&K=qyL4-uNwS!z<(0zHyOMW{ZE1YH^eUu zZUp{{c-_H0!M(x#z#GAfF#b)jZw7AxZv{`qc>hHF{qR2ko`&{^VLt|*4*wgD-J{&w zg)G+pcwZk)kkV$?D&IRDWb$M11RRf_VE+Z42!9XeGdwsKI1e}2~=jG$zbKvE8z41Bh*|A^zjqy&!^~p5w4D5e1 z!PDsvUWNV+;Q88W*blw zW+T5j;0^Gfi+Hi{cdY3#o}IX!n2Y%H5N{X!=fQtIcmX&*^4X1eAB^8&@PxKLuUW~b zUK=sqFaP3S*~dRQ*7I46e-q+u2A_lf9^^Y8_1S{nio@os=m!2cxp z4*XBSej0oRd=|VF@m_*ogWrJ9A>MiLLad*hIDXzCUPg!A6OhNx`g~;^pX=K=ct7<5 z`nw2@ivE^j{T0IgyA1Z|X#W@NnUH^M_%Fivm!th95c|U+@M6S24EquA68Im5 z{TTQ-cnHRK1^J$U|5ezpfvrdpL2>v$^?H_v^C|EV_@_XA&k_Fx_$Bxi_$cC^M*piY{

n1Nb%K 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 literal 6477499 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ΠcfReXS;W`Z1)~wC=2G(lVo@w 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 z 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�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 Date: Tue, 6 Oct 2026 05:54:08 +0000 Subject: [PATCH 02/23] fix(js,ts): find a store exported on a later line when its name contains $ (#2366) TreeSitterExtractor.isExportedLater put the binding name into its regex unescaped. A `$` in the name (`items$`, `$store`, `a$b`) became an end-of-line anchor, so `const items$ = create(...)` + `export default items$;` never matched and the store's actions (e.g. `function inc`) were not extracted, while the kernel mirror escapes the name with regex::escape and extracts them. The same anchor also matched where it should not: a store named `items$` read as exported when a multi-line `export { ... }` ended a line with `items`. The kernel routes TS/TSX/JS/JSX by default, so the wasm path is what files with parse errors (deferred to wasm), Svelte/Vue/Astro script blocks and runs without the kernel get. Escape the name the way regex::escape does; the guard limits names to [A-Za-z0-9_$], so only `$` changes. `\b` stays as is on both sides: next to a leading or trailing `$` it never matches (`export { items$ }`), the same in both engines. Adds a kernel/wasm parity case (ts/tsx/js/jsx) for `items$`, `$store` and `a$b` plus the false-positive shape; all 16 fail with the name unescaped and pass with the fix. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/kernel-tsjs-parity.test.ts | 27 +++++++++++++++++++++++++++ src/extraction/tree-sitter.ts | 6 +++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e066c8f62..b7b80ad26c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In JavaScript and TypeScript, the functions written inside a named object literal are now symbols of their own even when the object isn't exported: a plain `const api = { load() {…} }`, an object declared inside an IIFE or a function, and a namespace hung on the page or on another object, like `window.App = { init() {…} }`, `App.utils = {…}` or `dw_page = {…}`. Calls such as `api.load()`, `window.App.init()`, `App.utils.pad()`, a sibling's `this.render()`, and `App.init()` from another script on the page now reach them, the calls made inside a member belong to that member instead of the object, and a bare `init()` is no longer taken for `App.init`, so script-tag apps no longer lose most of their code from `callers` and impact. A member's qualified name now carries its object, exported or not (`api::load`, `window.App::init`), so asking for `App.init` finds it. Re-index JavaScript and TypeScript projects after upgrading. Thanks @tkhoaaa for the report and @danusha2345. (#2300) - In JavaScript and TypeScript files with Windows (CRLF) line endings, as a Windows checkout usually has them, a store exported on a later line, like `const useStore = create(…)` followed by `export default useStore;`, now has its actions indexed, as it already did with Unix line endings. Before, those actions were missing from the graph on Windows, so their callers and impact came back empty. Re-index JavaScript and TypeScript projects after upgrading. - In VB.NET, a name that begins with a keyword, like `SharedCache`, `Dimension`, `PublicKey` or `FriendlyName`, is now indexed whole, and a method like `Sub NewItem()` is no longer taken for a constructor. Before, the keyword was cut off (`Cache`, `ension`, `Key`) or the declaration was lost, and a line in a method that starts with such a name, like `Constants.Reload()` or `ConstVBV.Value = False`, was misread as a declaration, so reads of and calls to these names didn't link. A `Private Protected` member now counts as private instead of public. Re-index VB.NET projects after upgrading. +- In JavaScript and TypeScript, a store whose name contains a `$`, like `const items$ = create(…)` exported on a later line with `export default items$;`, now has its actions indexed. Before, they could be missing from the graph, for example in a file that also had a syntax error. Re-index JavaScript and TypeScript projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/kernel-tsjs-parity.test.ts b/__tests__/kernel-tsjs-parity.test.ts index 3cf974fcec..9bf906f144 100644 --- a/__tests__/kernel-tsjs-parity.test.ts +++ b/__tests__/kernel-tsjs-parity.test.ts @@ -151,6 +151,33 @@ describe.skipIf(!kernelBuilt)('kernel TS/JS extraction parity', () => { }); }); + describe.each([ + ['ts', 'typescript'], ['tsx', 'tsx'], ['js', 'javascript'], ['jsx', 'jsx'], + ] as const)('a store whose name has a `$`, exported by a later statement: %s', (ext, language) => { + // The later-export check builds a regex from the name. Its `$` must match + // the character, as the kernel's escaped pattern does, not a line end. + const store = (name: string, ...exportLines: string[]) => [ + 'import { create } from "zustand";', + `const ${name} = create((set) => ({ inc: () => set({}) }));`, + ...exportLines, + '', + ].join('\n'); + + it.each([ + ['items$', 'export default items$;'], + ['$store', 'export default $store;'], + ['a$b', 'export { a$b };'], + ])('keeps its actions (%s)', (name, exportLine) => { + const result = assertParity(`store.${ext}`, store(name, exportLine), language); + expect(result.nodes.some((n) => n.kind === 'function' && n.name === 'inc')).toBe(true); + }); + + it('is not exported by a different name at a line end', () => { + const result = assertParity(`store.${ext}`, store('items$', 'const items = 1;', 'export {', ' items', '};'), language); + expect(result.nodes.some((n) => n.kind === 'function' && n.name === 'inc')).toBe(false); + }); + }); + it.each([ ['ts', 'typescript'], ['tsx', 'tsx'], ['js', 'javascript'], ['jsx', 'jsx'], ] as const)('same-line accessors retain distinct identities after Unicode: %s (#1349)', (ext, language) => { diff --git a/src/extraction/tree-sitter.ts b/src/extraction/tree-sitter.ts index 031f200cf9..4964f396ce 100644 --- a/src/extraction/tree-sitter.ts +++ b/src/extraction/tree-sitter.ts @@ -2803,8 +2803,12 @@ export class TreeSitterExtractor { */ private isExportedLater(name: string): boolean { if (!/^[A-Za-z_$][\w$]*$/.test(name)) return false; + // Unescaped, a `$` in the name (`items$`, `$store`) is a line-end anchor, + // not the character. Escaped as the kernel's `regex::escape` does, so + // both paths decide the same. + const n = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const re = new RegExp( - `^[ \\t]*export\\s+(?:default\\s+${name}\\s*;?[ \\t]*$|\\{[^}]*\\b${name}\\b[^}]*\\})`, + `^[ \\t]*export\\s+(?:default\\s+${n}\\s*;?[ \\t]*$|\\{[^}]*\\b${n}\\b[^}]*\\})`, 'm' ); return re.test(this.source); From 6421644ef292d0e6decd968e249c18bd648a9078 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 05:55:25 +0000 Subject: [PATCH 03/23] fix(dart): link calls in top-level and field initializers (#2367) Both Dart extractors (the TS walker and the native kernel) skipped the code in initializers. A `final`/`const` declaration minted its constant and stopped, and a field's or `var`'s initializer only had its types recorded (#2360). In Riverpod apps, where most wiring lives in provider closures (`final repoProvider = Provider((ref) => Repository(ref.watch(dioProvider)));`), what a provider builds with had no callers, and impact and explore flows stopped at the provider. - A `final`/`const` initializer is walked like a body, for its constant: calls, instantiations, static and member reads, types, closures with block bodies and local functions, function values. - A field's (instance, `static var`, typed, `late`) or a top-level `var`/`late final` initializer is walked for its class or the file, since neither mints a node. A local declaration's second variable (`for (var i = 0, j = n(); ...)`) stays its function's. - Each initializer is walked once: a new `walkInitializer` context method marks it, and the dispatcher's function-as-value scan skips it. Other languages' hooks are unchanged. - Resolver: a Dart call through a type's static constant (`FutureProvider.autoDispose(...)` on `static const autoDispose = ...Builder();`) links that constant, not another type's same-named method. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/dart-initializer-calls.test.ts | 245 ++++++++++++++++++ __tests__/dart-type-positions.test.ts | 3 +- .../kernel-parity/TortureInitializers.dart | 89 +++++++ __tests__/kernel-dart-parity.test.ts | 10 +- codegraph-kernel/src/dart.rs | 90 ++++--- docs/design/dart-kernel-port-checklist.md | 73 ++++-- src/extraction/languages/dart.ts | 60 +++-- src/extraction/tree-sitter-types.ts | 7 + src/extraction/tree-sitter.ts | 17 +- src/resolution/name-matcher.ts | 18 ++ 11 files changed, 517 insertions(+), 96 deletions(-) create mode 100644 __tests__/dart-initializer-calls.test.ts create mode 100644 __tests__/fixtures/kernel-parity/TortureInitializers.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index b7b80ad26c..5216219e96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In JavaScript and TypeScript files with Windows (CRLF) line endings, as a Windows checkout usually has them, a store exported on a later line, like `const useStore = create(…)` followed by `export default useStore;`, now has its actions indexed, as it already did with Unix line endings. Before, those actions were missing from the graph on Windows, so their callers and impact came back empty. Re-index JavaScript and TypeScript projects after upgrading. - In VB.NET, a name that begins with a keyword, like `SharedCache`, `Dimension`, `PublicKey` or `FriendlyName`, is now indexed whole, and a method like `Sub NewItem()` is no longer taken for a constructor. Before, the keyword was cut off (`Cache`, `ension`, `Key`) or the declaration was lost, and a line in a method that starts with such a name, like `Constants.Reload()` or `ConstVBV.Value = False`, was misread as a declaration, so reads of and calls to these names didn't link. A `Private Protected` member now counts as private instead of public. Re-index VB.NET projects after upgrading. - In JavaScript and TypeScript, a store whose name contains a `$`, like `const items$ = create(…)` exported on a later line with `export default items$;`, now has its actions indexed. Before, they could be missing from the graph, for example in a file that also had a syntax error. Re-index JavaScript and TypeScript projects after upgrading. +- In Dart, what a top-level variable's or a field's initializer calls, creates and reads is now linked. In Riverpod apps, where most wiring lives in provider closures like `final repoProvider = Provider((ref) => Repository(ref.watch(dioProvider)));`, `callers`, impact and `codegraph_explore` now follow a provider to the code it builds instead of stopping at the provider. A `final` or `const` initializer belongs to its constant, and a `var`'s or a field's to its file or class. A call through a type's static constant, like `FutureProvider.autoDispose(…)`, now links to that constant instead of an unrelated method that shares its name. Re-index Dart projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/dart-initializer-calls.test.ts b/__tests__/dart-initializer-calls.test.ts new file mode 100644 index 0000000000..74c532aa90 --- /dev/null +++ b/__tests__/dart-initializer-calls.test.ts @@ -0,0 +1,245 @@ +/** + * Dart initializers are code: calls written in a top-level variable's or a + * field's initializer belong to the declaration. + * + * Both extractors skipped them. A `final`/`const` declaration minted its + * constant and stopped, and a field's or a `var`'s initializer only had its + * types recorded (#2327). So in a Riverpod app, where most wiring is written + * in provider closures — `final repoProvider = Provider((ref) => + * Repository(ref.watch(dioProvider)));` — `Repository` and every function a + * provider builds with had no callers, and impact and flows stopped at the + * provider. + * + * A `final`/`const` initializer belongs to its constant. A field's or a + * `var`'s initializer belongs to its class or to the file, because Dart mints + * no node for those declarations. + * + * A call through a type's static constant — `Provider.autoDispose(…)` on + * `static const autoDispose = AutoDisposeProviderBuilder();` — calls that + * constant, not a same-named method another type declares. + * + * Runs against the native kernel (when built) and the wasm extractor, which + * must agree. + */ +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; +import type { Node } from '../src/types'; + +const FILES: Record = { + 'pubspec.yaml': 'name: app\nenvironment:\n sdk: ">=3.0.0 <4.0.0"\n', + 'lib/riverpod.dart': `class Ref { + T watch(Object provider) => throw 0; + T read(Object provider) => throw 0; +} + +class Provider { + Provider(T Function(Ref ref) create); + + static const autoDispose = AutoDisposeProviderBuilder(); +} + +class AutoDisposeProviderBuilder { + const AutoDisposeProviderBuilder(); + + Provider call(T Function(Ref ref) create) => Provider(create); +} + +class ProviderFamilyBuilder { + Object autoDispose() => this; +} + +class StateNotifierProvider { + StateNotifierProvider(N Function(Ref ref) create); +} + +class FutureProvider { + FutureProvider(Future Function(Ref ref) create); + + static const family = FutureProviderFamilyBuilder(); +} + +class FutureProviderFamilyBuilder { + const FutureProviderFamilyBuilder(); + + FutureProvider call(Future Function(Ref ref, A arg) create) => throw 0; +} +`, + // A method named like `FutureProvider.family`, on another type in another file. + 'lib/builders.dart': `class AutoDisposeFutureProviderBuilder { + Object family() => this; +} +`, + 'lib/data.dart': `class Dio {} + +class Api { + Api(Dio dio); +} + +class Repository { + Repository(Dio dio); +} + +class Counter { + Counter(Api api); +} + +Dio createDio() => Dio(); +void register(void Function() cb) {} +int start() => 0; +`, + // The usual Riverpod provider shapes, and the providers they read. + 'lib/providers.dart': `import 'riverpod.dart'; +import 'data.dart'; + +final dioProvider = Provider((ref) => createDio()); +final apiProvider = Provider((ref) => Api(ref.watch(dioProvider))); +final repoProvider = Provider((ref) => Repository(ref.watch(dioProvider))); +final counterProvider = StateNotifierProvider((ref) => Counter(ref.read(apiProvider))); +`, + 'lib/more.dart': `import 'riverpod.dart'; +import 'data.dart'; +import 'providers.dart'; + +final typedProvider = Provider((Ref ref) => ref.read(dioProvider)); +final blockProvider = Provider((ref) { + final dio = createDio(); + return Repository(dio); +}); +void onTap() {} +final wired = register(onTap); +var cache = createDio(); +late final lazyRepo = Repository(createDio()); +final autoProvider = Provider.autoDispose((ref) => createDio()); +final userProvider = FutureProvider.family((ref, int id) async => Api(createDio())); + +Provider makeAuto() => Provider.autoDispose((ref) => Dio()); + +class Service { + static final instance = Service._(createDio()); + static var shared = Api(createDio()); + final repo = Repository(Dio()); + final Dio dio; + Service._(this.dio); + + int run() { + var total = 0; + for (var i = 0, j = start(); i < j; i++) { + total += i; + } + return total; + } +} +`, +}; + +describe('Dart initializer calls', () => { + let root = ''; + let cg: CodeGraph | undefined; + let kernel: string | undefined; + + beforeEach(() => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-initializers-')); + for (const [rel, content] of Object.entries(FILES)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + kernel = process.env.CODEGRAPH_KERNEL; + }); + + afterEach(() => { + cg?.close(); + cg = undefined; + fs.rmSync(root, { recursive: true, force: true }); + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; + }); + + it.each(['default', 'wasm'])('belong to the constant, class or file they initialize (%s)', async (backend) => { + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; + cg = await CodeGraph.init(root, { index: true }); + const graph = cg; + const node = (file: string, qualifiedName: string): Node => { + const found = graph.getNodesInFile(file).find((n) => n.qualifiedName === qualifiedName); + expect(found, `${file} ${qualifiedName}`).toBeDefined(); + return found!; + }; + const targets = (from: Node, kind: string): string[] => + [...new Set(graph + .getOutgoingEdgesFrom([from.id]) + .filter((e) => e.kind === kind) + .map((e) => graph.getNode(e.target)!.qualifiedName))] + .sort(); + const sources = (to: Node, kind: string): string[] => + [...new Set(graph + .getIncomingEdgesTo([to.id], [kind]) + .map((e) => graph.getNode(e.source)!) + .map((n) => `${n.kind} ${n.qualifiedName}`))] + .sort(); + + // The issue's providers construct what they build and call what they build it with. + expect(targets(node('lib/providers.dart', 'dioProvider'), 'calls')).toEqual(['createDio']); + expect(targets(node('lib/providers.dart', 'apiProvider'), 'instantiates')).toEqual(['Api', 'Provider']); + expect(targets(node('lib/providers.dart', 'repoProvider'), 'instantiates')).toEqual(['Provider', 'Repository']); + expect(targets(node('lib/providers.dart', 'counterProvider'), 'instantiates')).toEqual(['Counter', 'StateNotifierProvider']); + + // A typed closure parameter types its receiver; a block-bodied closure is walked whole. + expect(targets(node('lib/more.dart', 'typedProvider'), 'calls')).toEqual(['Ref::read']); + expect(targets(node('lib/more.dart', 'blockProvider'), 'calls')).toEqual(['createDio']); + expect(targets(node('lib/more.dart', 'blockProvider'), 'instantiates')).toEqual(['Provider', 'Repository']); + + // A function passed as a value is the constant's reference, captured once. + expect(targets(node('lib/more.dart', 'wired'), 'calls')).toEqual(['register']); + expect(sources(node('lib/more.dart', 'onTap'), 'references')).toEqual(['constant wired']); + + // `var` and `late final` mint no node: the file runs them. + const file = node('lib/more.dart', 'lib/more.dart'); + expect(targets(file, 'calls')).toEqual(['createDio']); + expect(targets(file, 'instantiates')).toEqual(['Repository']); + + // A `static final` is the class's constant; a `static var` and an instance + // field mint no node, so they are the class's. + expect(targets(node('lib/more.dart', 'Service::instance'), 'calls')).toEqual(['Service::_', 'createDio']); + const service = node('lib/more.dart', 'Service'); + expect(targets(service, 'calls')).toEqual(['createDio']); + expect(targets(service, 'instantiates')).toEqual(['Api', 'Dio', 'Repository']); + + // `Provider.autoDispose(…)` calls the static constant, whose own + // initializer constructs the builder — from a provider and from a body + // alike — and not a same-named method of another type, in its file or not. + const autoDispose = node('lib/riverpod.dart', 'Provider::autoDispose'); + expect(autoDispose.kind).toBe('constant'); + expect(targets(node('lib/more.dart', 'autoProvider'), 'calls')).toEqual(['Provider::autoDispose', 'createDio']); + expect(targets(node('lib/more.dart', 'makeAuto'), 'calls')).toEqual(['Provider::autoDispose']); + expect(targets(autoDispose, 'instantiates')).toEqual(['AutoDisposeProviderBuilder']); + expect(sources(node('lib/riverpod.dart', 'ProviderFamilyBuilder::autoDispose'), 'calls')).toEqual([]); + expect(targets(node('lib/more.dart', 'userProvider'), 'calls')).toEqual(['FutureProvider::family', 'createDio']); + expect(sources(node('lib/builders.dart', 'AutoDisposeFutureProviderBuilder::family'), 'calls')).toEqual([]); + + // Each provider and declaration above is a caller of what it builds. + expect(sources(node('lib/data.dart', 'createDio'), 'calls')).toEqual([ + 'class Service', + 'constant Service::instance', + 'constant autoProvider', + 'constant blockProvider', + 'constant dioProvider', + 'constant userProvider', + 'file lib/more.dart', + ]); + expect(sources(node('lib/data.dart', 'Repository'), 'instantiates')).toEqual([ + 'class Service', + 'constant blockProvider', + 'constant repoProvider', + 'file lib/more.dart', + ]); + + // A local declaration's second variable is its function's, once. + const run = node('lib/more.dart', 'Service::run'); + expect(targets(run, 'calls')).toEqual(['start']); + expect(graph.getOutgoingEdgesFrom([run.id]).filter((e) => e.kind === 'calls')).toHaveLength(1); + expect(sources(node('lib/data.dart', 'start'), 'calls')).toEqual(['method Service::run']); + }); +}); diff --git a/__tests__/dart-type-positions.test.ts b/__tests__/dart-type-positions.test.ts index 79ead5c731..5eb6401c55 100644 --- a/__tests__/dart-type-positions.test.ts +++ b/__tests__/dart-type-positions.test.ts @@ -119,7 +119,8 @@ describe('Dart type positions (#2327)', () => { const body = cg.getNodesByQualifiedName('body')[0]!; const refs = cg.getOutgoingEdgesFrom([body.id], ['references']).filter((e) => cg.getNode(e.target)!.name === 'Score'); expect([...new Set(refs.map((e) => e.line))].sort()).toEqual([26, 27]); - expect(referrers('Score', 'instantiates')).toEqual(['function body']); + // `static const Score zero = Score(0);` constructs one too, from its constant. + expect(referrers('Score', 'instantiates')).toEqual(['constant Board::zero', 'function body']); const prefixRefs = cg.getUnresolvedReferencesInFile('lib/more.dart').filter((r) => r.referenceName === 'm'); expect(prefixRefs).toEqual([]); }); diff --git a/__tests__/fixtures/kernel-parity/TortureInitializers.dart b/__tests__/fixtures/kernel-parity/TortureInitializers.dart new file mode 100644 index 0000000000..35d71ff68d --- /dev/null +++ b/__tests__/fixtures/kernel-parity/TortureInitializers.dart @@ -0,0 +1,89 @@ +// Calls, instantiations, reads and function values written in initializers: +// top-level variables and constants, and fields of every member body kind. +import 'package:app/model.dart'; + +int compute(int n) => n; +void onTap() {} +void register(Object o) {} +Widget build() => Widget(0); + +// final / const: the constant owns its initializer. +final repoProvider = Provider((ref) => Repository(ref.watch(dioProvider))); +final counterProvider = StateNotifierProvider((ref) => Counter(ref.read(apiProvider))); +final blockProvider = Provider((ref) { + final dio = Dio.create(compute(1)); + void local(int x) { + register(x); + } + local(2); + return Repository(dio)..init()..start(); +}); +const shared = Widget.named(3); +const made = const Pair(1, Widget(2)); +final created = new Widget(compute(4)); +final chained = Widget.factory().configure().run(); +final reads = Config.instance.name; +final label = 'total ${compute(5)} of $shared'; +final cb = onTap; +final wired = register(onTap); +final table = [onTap, build]; +final byName = {'tap': onTap, 'build': build}; +final first = compute(6), second = Widget(7); +final Provider typed = Provider((ref) => build()); +final asyncProvider = FutureProvider((ref) async => await load(ref)); +final viaTypedParam = Provider((Ref ref) => ref.watch(dioProvider).value); + +// var / typed / late: the file owns the initializer. +var counter = compute(8); +Widget top = build(); +late final lazy = Widget(compute(9)); +var list = [Widget(10), build()], other = compute(11); +int plain = 0; + +class Holder { + static final instance = Holder._(compute(12)); + static const empty = Holder._(0); + static var cache = Widget(compute(13)); + static Widget typedStatic = build(); + final made = Widget(14); + late final lazyField = compute(size); + var callbacks = [onTap]; + final Widget other = Widget.named(15), more = build(); + final int size; + Holder._(this.size); + + int run() { + var total = 0; + for (var i = 0, j = compute(16); i < j; i++) { + total += i; + } + final local = Widget(17), again = compute(18); + return total; + } +} + +mixin Tracking { + static var tracker = Tracker.start(); + final events = [Event('init')]; +} + +extension Formatting on String { + static final formatter = Formatter(compute(19)); + static var counter = compute(20); +} + +enum Mode { + fast, + slow; + + static final byName = {for (final m in Mode.values) m.name: m}; + static const fallback = Mode.fast; + final weight = 1; +} + +extension type Meters(int value) { + static var unit = Unit.create('m'); +} + +// Positions after multi-byte text are UTF-16 columns on both arms. +final emoji = 'é😀'; final afterEmoji = compute(21); var alsoAfter = Widget(22); diff --git a/__tests__/kernel-dart-parity.test.ts b/__tests__/kernel-dart-parity.test.ts index ad3396d833..cc8fd008e3 100644 --- a/__tests__/kernel-dart-parity.test.ts +++ b/__tests__/kernel-dart-parity.test.ts @@ -21,8 +21,10 @@ * twins; TortureMini/TortureSigs/TortureCtors/TortureVrefDart: signatures * verbatim, prefixed-return-type prefix bug, const factories invisible, * value-ref matrix with `$X` vs `${X}` asymmetry; TortureReadsTypes.dart: - * getter-read refs and the type positions outside signatures — #2338/#2327) - * and their CRLF variants + * getter-read refs and the type positions outside signatures — #2338/#2327; + * TortureInitializers.dart: initializers walked as the code their constant, + * class or file runs, every member-body kind, and a local declaration's + * second variable left to its function) and their CRLF variants * (derived in-memory — #1329), plus defer and generated-file pins. * * The full-repo sweeps live in scripts/kernel-parity.mjs (shelf/bloc/flutter @@ -116,6 +118,10 @@ describe.skipIf(!kernelBuilt)('kernel Dart extraction parity', () => { // extension `on` types, field / enum-field / top-level types, constant and // field initializers, body types, and the read shapes that are not reads. ['TortureReadsTypes.dart', 20], + // Initializers (top-level, static and instance) walked as code: calls, + // instantiations, reads, closures with block bodies and local functions, + // and function values captured once, for the declaration. + ['TortureInitializers.dart', 30], ] as const; for (const [file, minNodes] of FIXTURES) { diff --git a/codegraph-kernel/src/dart.rs b/codegraph-kernel/src/dart.rs index 9deb1cbfff..b423a8f6ef 100644 --- a/codegraph-kernel/src/dart.rs +++ b/codegraph-kernel/src/dart.rs @@ -20,7 +20,9 @@ //! `method ""`; the unnamed constructor is skipped //! (isMisparsedFunction) while named ctors/factories are named by the CTOR //! name with the class as returnType; instance fields mint NO nodes (only -//! static_final_declaration → constant, via the hook); prefixed return +//! static_final_declaration → constant, via the hook); every initializer is +//! body-walked once — a constant's from the constant, a field's or a +//! top-level variable's from the class or the file; prefixed return //! types keep the PREFIX (`other.OtherClass f()` → returnType `other` — //! bug, preserved); enum `with` mixins emit nothing while enum `implements` //! works; deferred imports are invisible; named-argument callbacks are NOT @@ -629,24 +631,34 @@ impl<'t> Walker<'t> { }); let name = self.text(name_node).to_string(); let constant = self.create_node("constant", &name, node, Extra { signature, ..Default::default() }); - // The types its initializer names are the constant's (#2327). + // The initializer is code the constant runs — its calls, + // instantiations, reads and the types it names (#2327) are + // the constant's. walkInitializer: the body walk, and the + // dispatcher's fn-ref scan skips what it walked. if let Some(constant) = constant { - let mut value = name_node.next_named_sibling(); - while let Some(v) = value { - self.type_refs_dart(v, constant); - value = v.next_named_sibling(); - } + self.stack.push(Scope { row: constant, kind: "constant", name }); + self.visit_body(node); + self.stack.pop(); + return; } } self.scan_fn_ref_subtree(node, 0); return; } - // A field's declared type and initializer types are its class's (Dart - // fields mint no nodes); a top-level variable's are the file's (#2327). - // The visitNode hook's `declaration` / `program` rows (dart.ts). - // (Parent lookups walk down from the root, so only the node kinds that - // can be these positions ask for theirs.) + // A field's or top-level variable's initializer is code its class or + // the file runs (neither mints a node) — the hook's + // `initialized_identifier` row, walked like a body (walkInitializer). + if node.kind() == "initialized_identifier" && self.is_field_or_top_level_entry(node) { + self.visit_body(node); + return; + } + + // A field's declared type is its class's (Dart fields mint no nodes); + // a top-level variable's is the file's (#2327). The visitNode hook's + // `declaration` / `program` rows (dart.ts). (Parent lookups walk down + // from the root, so only the node kinds that can be these positions + // ask for theirs.) if node.kind() == "declaration" { let in_body = node .parent() @@ -661,26 +673,16 @@ impl<'t> Walker<'t> { if is_field { let owner = self.top_row(); for child in kids { - match child.kind() { - "initialized_identifier_list" => self.initializer_type_refs_dart(child, owner), - "static_final_declaration_list" => {} - _ => self.type_refs_dart(child, owner), + if !matches!(child.kind(), "initialized_identifier_list" | "static_final_declaration_list") { + self.type_refs_dart(child, owner); } } } - } else { - let top_level_type = - matches!(node.kind(), "type_identifier" | "type_arguments" | "function_type" | "record_type"); - if (top_level_type || node.kind() == "initialized_identifier_list") - && node.parent().map(|p| p.kind() == "program").unwrap_or(false) - { - let owner = self.top_row(); - if top_level_type { - self.type_refs_dart(node, owner); - } else { - self.initializer_type_refs_dart(node, owner); - } - } + } else if matches!(node.kind(), "type_identifier" | "type_arguments" | "function_type" | "record_type") + && node.parent().map(|p| p.kind() == "program").unwrap_or(false) + { + let owner = self.top_row(); + self.type_refs_dart(node, owner); } // maybeCaptureFnRefs (:990) — the double-walk fn-ref twin source. @@ -1387,21 +1389,23 @@ impl<'t> Walker<'t> { } } - /// pushDartInitializerTypeRefs (dart.ts) — each `initialized_identifier`'s - /// value (every named child after its name). - fn initializer_type_refs_dart(&mut self, list: Node<'t>, from_row: u32) { - let mut cursor = list.walk(); - let entries: Vec> = list.named_children(&mut cursor).collect(); - for entry in entries { - if entry.kind() != "initialized_identifier" { - continue; - } - let mut ec = entry.walk(); - let parts: Vec> = entry.named_children(&mut ec).skip(1).collect(); - for part in parts { - self.type_refs_dart(part, from_row); - } + /// isDartFieldOrTopLevelEntry (dart.ts) — an `initialized_identifier` + /// declaring a field or a top-level variable, not the second variable of + /// a local declaration (`for (var i = 0, j = n(); …)`). + fn is_field_or_top_level_entry(&self, node: Node<'t>) -> bool { + let Some(list) = node.parent() else { return false }; + if list.kind() != "initialized_identifier_list" { + return false; + } + let Some(owner) = list.parent() else { return false }; + if owner.kind() == "program" { + return true; } + owner.kind() == "declaration" + && owner + .parent() + .map(|p| matches!(p.kind(), "class_body" | "extension_body" | "enum_body")) + .unwrap_or(false) } /// dartMemberRead (dart.ts) — `x.area` / `x?.area` not followed by a call's diff --git a/docs/design/dart-kernel-port-checklist.md b/docs/design/dart-kernel-port-checklist.md index d354281eb9..6048396c4d 100644 --- a/docs/design/dart-kernel-port-checklist.md +++ b/docs/design/dart-kernel-port-checklist.md @@ -269,12 +269,31 @@ Hooks PRESENT (port each exactly — anchors into languages/dart.ts): expression node); initValue = its text `.slice(0,100)` (UTF-16); `ctx.createNode('constant', name, node, { signature: initValue ? \`= ${initValue}${initValue.length >= 100 ? '...' : ''}\` : undefined })`. - Return **true** (consumed — even when nameNode missing? NO: name found is - required for createNode but the hook returns true for EVERY + When the constant is minted, the hook pushes it and walks the WHOLE + declaration with the body walker (`ctx.walkInitializer(node)` — + visitFunctionBody that records the node as walked), then pops: the + initializer's calls, instantiations, static and member reads, types, + closures (block bodies and local functions included) and fn-ref + candidates (the `varinit` capture of the declaration itself included) are + the CONSTANT's. Return **true** (consumed — even when nameNode missing? NO: + name found is required for createNode but the hook returns true for EVERY static_final_declaration reached, node minted or not — transcribe the - early-return shape exactly: `if (nameNode) {…}; return true`). The - dispatcher then runs `scanFnRefSubtree(node, 0)` and never descends → - §Function-as-value for what still gets captured. Everything else → false. + early-return shape exactly: `if (nameNode) {…; if (constant) walk}; return + true`). The dispatcher then runs `scanFnRefSubtree(node, 0, walked)` — + which skips a walked declaration outright, so only an unminted one is + scanned — and never descends. +- **visitNode — the field / top-level variable branch.** `node.type === + 'initialized_identifier'` whose parent is an `initialized_identifier_list` + directly under `program`, or under a `declaration` in a + class_body/extension_body/enum_body → `ctx.walkInitializer(node)` with no + push (the stack top is the file or the class/enum), return **true**. These + declarations mint no node, so their initializers are the FILE's or the + CLASS's. An `initialized_identifier` anywhere else — the second variable of + a local `for (var i = 0, j = n(); …)`, under `initialized_variable_definition` + — is left to its function's body walk (the double-walk's pass 2a reaches it + too, so the parent check is load-bearing). The `declaration` and `program` + type rows push only the DECLARED type's refs; initializer types come from + the walk. Everything else → false. **Reality of the node type (probed, `probe2-cst.txt`):** `static_final_declaration` = a `final`/`const` declaration WITH an initializer that is **top-level** (`const SHARED_MAX = 10;`, `final @@ -412,7 +431,7 @@ Registration: `EXTRACTORS.dart` (languages/index.ts:56), `FN_REF_SPECS.dart` | Node | Branch | Behavior | |---|---|---| -| every node | visitNode hook first (:943) | `static_final_declaration` consumed (§Constants); handled → scanFnRefSubtree + STOP | +| every node | visitNode hook first (:943) | `static_final_declaration` consumed and body-walked for its constant; a field's or top-level variable's `initialized_identifier` consumed and body-walked for the class/file (§Constants); handled → scanFnRefSubtree (skipping what was walked) + STOP | | every node | maybeCaptureFnRefs (:990) | fires for `arguments`/`assignment_expression`/`pair`/`list_literal`/`static_final_declaration` in visitNode context — the source of the file/class-attributed fn-ref twins (§double-walk) | | `function_signature` | functionTypes:994 | methodTypes does NOT include it → **always extractFunction:1517**, even inside a class (isInsideClassLike && !methodTypes.includes → else-arm). In-class function_signatures occur only for ABSTRACT/bodiless methods, reached via their `declaration` wrapper (`declaration > function_signature`, probed) → **kind `function` contained by the class** (pinned: `AbstractT::mustImpl` is a function; the sibling `declaration > getter_signature` abstract getter stays invisible). skipChildren | | `class_definition` | classTypes:1005 | no classifyClassNode → always extractClass:1679 (abstract/sealed/base/etc. included) | @@ -423,7 +442,7 @@ Registration: `EXTRACTORS.dart` (languages/index.ts:56), `FN_REF_SPECS.dart` | `import_or_export` | importTypes:1209 → extractImport:3170 | §Extractor config | | `new_expression` | INSTANTIATION_KINDS:1255 (`new_expression` ∈ :354-361) | extractInstantiation:4610 → ctor field lookups null → namedChild(0) = type_identifier → `instantiates` ref from stack top; `<`-strip + last-`.`-segment apply (`new p.Foo()` → `Foo`). findAnonymousClassBody → always null for dart. Children still recursed | | `function_body` (sibling of a consumed signature) | **no branch** | recursed → THE DOUBLE-WALK (§below) | -| `declaration` (fields, bodiless ctors) | no branch | recursed → constructor_signature hits methodTypes; initialized_identifier/list, constant_constructor_signature, redirecting_factory_constructor_signature, initializers, annotations-in-place: nothing | +| `declaration` (fields, bodiless ctors) | no branch | recursed → constructor_signature hits methodTypes; each field `initialized_identifier` hits the hook (body-walked for the class); constant_constructor_signature, redirecting_factory_constructor_signature, initializers, annotations-in-place: nothing | | `getter_signature` / `setter_signature` BARE (top level) | no branch | **top-level getters/setters are INVISIBLE** (no node; their sibling function_body is visitNode-recursed where calls don't extract) — in classes they're method_signature-wrapped → methods | | `const_object_expression`, `selector`, `cascade_section`, `assignment_expression`, `local_variable_declaration`, patterns, `extension_type_declaration`, `part_directive`, `library_name`, lambdas | no branch | recursed; calls only extract in the BODY walker (`extractBareCall` is not consulted by visitNode!) — §Calls for the consequences | | `property_signature`/`method_signature` TS branch (:1282) | **shadowed** | method_signature is consumed at :1027 first; property_signature isn't a dart kind — branch unreachable | @@ -625,14 +644,19 @@ constant under the class, sig `= WidgetT`; multi-declarations → one node each with own columns. **NO nodes ever**: instance fields (typed/untyped/ late/var), `static var`, top-level var/typed vars, top-level getters/ setters, const constructors, redirecting factories, extension_type -containers, `part`/`part of`/`library`/deferred imports. **Initializer -side-effects:** hook-consumed constants' initializers are NOT walked → no -calls/instantiates from them (only scanFnRefSubtree capture — §fn-refs); -initialized_identifier fields' initializers ARE recursed by visitNode but -only INSTANTIATION_KINDS fires there → `int counter = 0;` emits nothing, -but a field `final w = new Widget();` would emit `instantiates Widget` from -the CLASS (and a top-level `var w = new Widget();` from the FILE). No -static-member refs from any of these contexts (body-walker only). +containers, `part`/`part of`/`library`/deferred imports. **Initializers +are code:** every initializer is walked with the body walker — a +constant's for the constant (riverpod's `final repoProvider = +Provider((ref) => Repository(ref.watch(dioProvider)));` → calls +`Provider`, `Repository`, `ref.watch` from `repoProvider`), a field's +(instance, `static var`, typed, `late`) for its class, a top-level +`var`/typed/`late final` one for the FILE. The full body matrix applies: +calls, instantiates, static-member and member reads, type refs, closures +with block bodies (a local function inside one mints a `function` under +the constant, with the double-walk's pass 2b on its body), interpolation +calls, fn-ref candidates. Each is walked ONCE: the hook consumes the entry, +so the visitNode recursion that used to reach `new_expression` / +maybeCaptureFnRefs inside a field initializer no longer does. ### Calls — extractBareCall (dart.ts:305-379) in the body walker (:5159-5173) @@ -664,7 +688,8 @@ extract-mini.txt): | `throw StateError('bad')` | recursion | `StateError` | | `'sum ${a + compute()}'` | template_substitution recursion | `compute` (interpolation calls EMIT); `$name` → identifier_dollar_escaped → nothing | | local-lambda body `final lam = (int a) { helper(a); }` | function_expression recursed transparently | `helper` attributed to the ENCLOSING function; `lam(5)` → `lam` | -| ctor initializers (`: size = seed()`), enum-constant args (`ok(200)`), default param values, hook-consumed constant initializers | never body-walked | NOTHING | +| `final p = Provider((ref) => Repo(ref.watch(d)))`, `static var s = make()`, `final _c = Controller();` in a class, `var v = load();` | the hook's walkInitializer (§Constants) | the full matrix, from the constant / the class / the file | +| ctor initializers (`: size = seed()`), enum-constant args (`ok(200)`), default param values | never body-walked | NOTHING | extractCall (:3684), LITERAL_RECEIVER_TYPES (:373-388), SKIP_RECEIVERS, the parenthesized-conversion regex (:4530), template-strip — ALL UNREACHABLE for @@ -690,7 +715,8 @@ previousNamedSibling is an `identifier` matching `/^[A-Z][A-Za-z0-9_]*$/` → - `this.x` → prev is a `this` node → nothing. Case patterns (`case ColorT.blue:`) → `constant_pattern > qualified` shape, no selector → NOTHING (pinned gap). Cascade sections → no selector → nothing. - Class-field/constant initializers and visitNode contexts → never called. + visitNode contexts → never called; initializers are body-walked, so a + read written in one emits from its constant / class / file. ### Type-annotation references — dart ∈ TYPE_ANNOTATION_LANGUAGES (:5753), the dart branch (:5819-5833) is LIVE @@ -857,14 +883,17 @@ NO unwrap, NO ungatedModes, NO addressOfOnly. Pins: - `[topLevel, blockDoc]` list ✓ (locals' list_literals capture too — the dispatch fires wherever the node is walked); `{'k': topLevel}` pair ✓; `final aliasTop = aliased;` top-level/static → varinit bare-identifier ✓ - (pinned from=file / from=class); a LOCAL `final alias = topLevel;` → + (from the constant `aliasTop` — the hook walks the declaration with it + pushed); a LOCAL `final alias = topLevel;` → initialized_variable_definition NOT in dispatch → not captured. - obj.method member values (`final g = obj.method`) → the last child is a selector → normalizeValue [] → nothing (no member special for dart). -- Capture points: visitFunctionBody:5137 (bodies), visitNode:990 (the - §double-walk twins from file/class scope), scanFnRefSubtree (hook-consumed - constant initializers — halts at `function_expression` :609, so lambdas - inside a constant's initializer don't leak candidates). +- Capture points: visitFunctionBody:5137 (bodies, and every initializer + the hook walks — from the constant / class / file, lambdas included), + visitNode:990 (the §double-walk twins from file/class scope), + scanFnRefSubtree (only a `static_final_declaration` whose constant wasn't + minted — the scan skips what the hook walked, so nothing is captured + twice; it halts at `function_expression` :609). - **Flush gate (:639-728): effectively "defined in this file" ONLY** — dart import refs are URIs (`package:foo/util.dart`, `dart:async`) which match neither SIMPLE_NAME nor QUALIFIED_IMPORT (`:` and `/` excluded) → diff --git a/src/extraction/languages/dart.ts b/src/extraction/languages/dart.ts index 13583b983c..ad5b8c4bd0 100644 --- a/src/extraction/languages/dart.ts +++ b/src/extraction/languages/dart.ts @@ -49,16 +49,18 @@ const DART_MEMBER_BODIES: ReadonlySet = new Set(['class_body', 'extensio /** The named nodes a top-level variable's declared type is written as (`Report? x;`, `List xs = [];`). */ const DART_TOP_LEVEL_TYPES: ReadonlySet = new Set(['type_identifier', 'type_arguments', 'function_type', 'record_type']); -/** Type refs from `fromNodeId` for the initializers in an `initialized_identifier_list` (each entry is its name, then its value). */ -function pushDartInitializerTypeRefs( - list: SyntaxNode, - fromNodeId: string, - push: (ref: UnresolvedReference) => void, -): void { - for (const entry of list.namedChildren) { - if (entry.type !== 'initialized_identifier') continue; - for (const part of entry.namedChildren.slice(1)) pushDartTypeRefs(part, fromNodeId, push); - } +/** + * Whether an `initialized_identifier` declares a field or a top-level + * variable — `var cache = load();`, `final _ctl = TextEditingController();` + * in a class — rather than the second variable of a local declaration + * (`for (var i = 0, j = n(); …)`), which a function body's walk covers. + */ +function isDartFieldOrTopLevelEntry(node: SyntaxNode): boolean { + const list = node.parent; + if (list?.type !== 'initialized_identifier_list') return false; + const owner = list.parent; + if (owner?.type === 'program') return true; + return owner?.type === 'declaration' && owner.parent !== null && DART_MEMBER_BODIES.has(owner.parent.type); } /** @@ -238,17 +240,21 @@ export const dartExtractor: LanguageExtractor = { const constant = ctx.createNode('constant', getNodeText(nameNode, ctx.source), node, { signature: initValue ? `= ${initValue}${initValue.length >= 100 ? '...' : ''}` : undefined, }); - // The types its initializer names are the constant's — riverpod's - // `final reportProvider = Family();` (#2327). + // The initializer is code the constant runs: riverpod's `final + // repoProvider = Provider((ref) => Repository(ref.watch(dioProvider)));` + // calls `Provider`, `Repository` and `ref.watch`, and the types it + // names (`Family()`, #2327) are the constant's too. if (constant) { - for (let value = valueNode; value; value = value.nextNamedSibling) pushDartTypeRefs(value, constant.id, push); + ctx.pushScope(constant.id); + ctx.walkInitializer(node); + ctx.popScope(); } } return true; } - // A field's declared type, and the types its initializer names, are its - // class's: Dart fields mint no nodes of their own (`final Report report;`, - // #2327). A `static final` / `const` field's initializer is its constant's. + // A field's declared type is its class's: Dart fields mint no nodes of + // their own (`final Report report;`, #2327). Each initializer is walked + // as its entry is reached, below. if (node.type === 'declaration') { const owner = ctx.nodeStack[ctx.nodeStack.length - 1]; const inBody = node.parent !== null && DART_MEMBER_BODIES.has(node.parent.type); @@ -257,19 +263,25 @@ export const dartExtractor: LanguageExtractor = { ); if (owner && isField) { for (const child of node.namedChildren) { - if (child.type === 'initialized_identifier_list') pushDartInitializerTypeRefs(child, owner, push); - else if (child.type !== 'static_final_declaration_list') pushDartTypeRefs(child, owner, push); + if (child.type !== 'initialized_identifier_list' && child.type !== 'static_final_declaration_list') { + pushDartTypeRefs(child, owner, push); + } } } return false; } - // A top-level variable's declared type and its (non-constant) initializer - // are the file's — the grammar lays them out directly under `program`. - const topLevelType = DART_TOP_LEVEL_TYPES.has(node.type); - if ((topLevelType || node.type === 'initialized_identifier_list') && node.parent?.type === 'program') { + // A field's initializer, or a top-level variable's, is code its class or + // the file runs — neither declaration mints a node to own it. A `static + // final` / `const` one is its constant's (above). + if (node.type === 'initialized_identifier' && isDartFieldOrTopLevelEntry(node)) { + ctx.walkInitializer(node); + return true; + } + // A top-level variable's declared type is the file's — the grammar lays + // it out directly under `program`. + if (DART_TOP_LEVEL_TYPES.has(node.type) && node.parent?.type === 'program') { const owner = ctx.nodeStack[ctx.nodeStack.length - 1]; - if (owner && topLevelType) pushDartTypeRefs(node, owner, push); - else if (owner) pushDartInitializerTypeRefs(node, owner, push); + if (owner) pushDartTypeRefs(node, owner, push); } return false; }, diff --git a/src/extraction/tree-sitter-types.ts b/src/extraction/tree-sitter-types.ts index 619dc097f1..1c2d4f374f 100644 --- a/src/extraction/tree-sitter-types.ts +++ b/src/extraction/tree-sitter-types.ts @@ -54,6 +54,13 @@ export interface ExtractorContext { visitNode(node: SyntaxNode): void; /** Visit a function body to extract calls */ visitFunctionBody(body: SyntaxNode, functionId: string): void; + /** + * Walk a declaration's initializer as code the scope on top of the stack + * runs, the way a function body is walked. When the hook then reports the + * node handled, the function-as-value scan the dispatcher runs over it skips + * what was walked here: the walk captured those candidates already. + */ + walkInitializer(node: SyntaxNode): void; /** Add an unresolved reference */ addUnresolvedReference(ref: UnresolvedReference): void; /** Push a node ID onto the scope stack (for containment/qualified name building) */ diff --git a/src/extraction/tree-sitter.ts b/src/extraction/tree-sitter.ts index 4964f396ce..da8dc9bbee 100644 --- a/src/extraction/tree-sitter.ts +++ b/src/extraction/tree-sitter.ts @@ -1160,8 +1160,9 @@ export class TreeSitterExtractor { // The hook consumed this subtree, so the walkers below never descend // into it — scan it for function-as-value candidates (#756). Scala's // hook handles val/var definitions (`val table = Seq(targetCb)`), for - // example. The scan is capture-only and halts at nested functions. - this.scanFnRefSubtree(node, 0); + // example. The scan is capture-only and halts at nested functions; + // an initializer the hook walked has captured its own. + this.scanFnRefSubtree(node, 0, ctx.walked ?? undefined); return; } } @@ -1764,14 +1765,21 @@ export class TreeSitterExtractor { /** * Build an ExtractorContext for passing to language-specific visitNode hooks. + * `walked` collects the initializers the hook walks, for the dispatcher's + * function-as-value scan to skip. */ - private makeExtractorContext(): ExtractorContext { + private makeExtractorContext(): ExtractorContext & { walked: Set | null } { // eslint-disable-next-line @typescript-eslint/no-this-alias const self = this; - return { + const ctx: ExtractorContext & { walked: Set | null } = { + walked: null, createNode: (kind, name, node, extra) => self.createNode(kind, name, node, extra), visitNode: (node) => self.visitNode(node), visitFunctionBody: (body, functionId) => self.visitFunctionBody(body, functionId), + walkInitializer: (node) => { + (ctx.walked ??= new Set()).add(node.id); + self.visitFunctionBody(node, ''); + }, addUnresolvedReference: (ref) => self.unresolvedReferences.push(ref), pushScope: (nodeId) => self.nodeStack.push(nodeId), popScope: () => self.nodeStack.pop(), @@ -1780,6 +1788,7 @@ export class TreeSitterExtractor { get nodeStack() { return self.nodeStack; }, get nodes() { return self.nodes; }, }; + return ctx; } /** diff --git a/src/resolution/name-matcher.ts b/src/resolution/name-matcher.ts index cf151c7aa8..c7d7a0e072 100644 --- a/src/resolution/name-matcher.ts +++ b/src/resolution/name-matcher.ts @@ -8927,6 +8927,24 @@ export function matchMethodCall( if (classNode.language !== ref.language) continue; const nodesInFile = context.getNodesInFile(classNode.filePath); + // Dart: a call through a type's static constant invokes the value the + // constant holds. riverpod's `FutureProvider.autoDispose(…)` calls + // `static const autoDispose = AutoDisposeFutureProviderBuilder();`, + // which the lookups below gave to another builder's `autoDispose` + // method. A Dart type can't also declare a method of that name, and its + // static members are not inherited, so its own constant is the callee. + if (ref.language === 'dart') { + const holder = nodesInFile.find((n) => + n.kind === 'constant' && n.name === methodName && n.qualifiedName === `${classNode.qualifiedName}::${methodName}`); + if (holder) { + return { + original: ref, + targetNodeId: holder.id, + confidence: 0.85, + resolvedBy: 'qualified-name', + }; + } + } const methodNode = nodesInFile.find( (n) => n.kind === 'method' && From b7e05f3ccd3f0277f56de972accf5987edf163e5 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 14:36:56 +0000 Subject: [PATCH 04/23] fix(dart): link a chained call only through its receiver's declared types (#750) (#2376) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Dart extractor keeps one receiver level, so the later links of a call chain reach the resolver by their bare name (`Provider.autoDispose.family(…)` → `family`, `events.map(mapper).transform(…)` → `transform`). They then fell to name matching and bound to whichever project method shared the name: on felangel/bloc a Stream's `transform` went to angular_bloc's `BlocPipe::transform`, and on rrousselGit/riverpod every `X.autoDispose.family(…)` went to one builder's `family` whatever X was. A chain link now reaches only the member of what the chain before it evaluates to, typed from evidence: the head (a type, a constructor call, a string, `this` / `super`, an import prefix, a local, parameter, field or getter with a declared type) and each link's declared type (a method's or getter's return type with the method's own type parameters substituted, a field's or abstract getter's type, a static constant's initializer). A lookup nothing declared answers for hands back its one type argument (`context.read()`). Without evidence it links nothing. Along the way: an annotated extension (`@internal extension X on Y`) is recognized as one, so its members reach member reads and chains; `super.m()` reaches the superclass's method instead of the caller itself; an extension on a type parameter of its own applies to the project's types; a spread's `...foo()` is a receiver-less call. Validated before/after with the native kernel: bloc 337 name-only chain edges on main → 123 kept (now typed), 106 retargeted, 106 removed (68 on a typed receiver lacking the member), +75 `super.` calls; riverpod 1,254 → 171 kept, 383 retargeted, 696 removed (137 provably wrong), +263. Kernel and wasm graphs are identical with the fix. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/dart-chain-links.test.ts | 242 +++++++++ src/resolution/index.ts | 6 +- src/resolution/name-matcher.ts | 842 ++++++++++++++++++++++++++++- 4 files changed, 1075 insertions(+), 16 deletions(-) create mode 100644 __tests__/dart-chain-links.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 5216219e96..a25c1a90ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In VB.NET, a name that begins with a keyword, like `SharedCache`, `Dimension`, `PublicKey` or `FriendlyName`, is now indexed whole, and a method like `Sub NewItem()` is no longer taken for a constructor. Before, the keyword was cut off (`Cache`, `ension`, `Key`) or the declaration was lost, and a line in a method that starts with such a name, like `Constants.Reload()` or `ConstVBV.Value = False`, was misread as a declaration, so reads of and calls to these names didn't link. A `Private Protected` member now counts as private instead of public. Re-index VB.NET projects after upgrading. - In JavaScript and TypeScript, a store whose name contains a `$`, like `const items$ = create(…)` exported on a later line with `export default items$;`, now has its actions indexed. Before, they could be missing from the graph, for example in a file that also had a syntax error. Re-index JavaScript and TypeScript projects after upgrading. - In Dart, what a top-level variable's or a field's initializer calls, creates and reads is now linked. In Riverpod apps, where most wiring lives in provider closures like `final repoProvider = Provider((ref) => Repository(ref.watch(dioProvider)));`, `callers`, impact and `codegraph_explore` now follow a provider to the code it builds instead of stopping at the provider. A `final` or `const` initializer belongs to its constant, and a `var`'s or a field's to its file or class. A call through a type's static constant, like `FutureProvider.autoDispose(…)`, now links to that constant instead of an unrelated method that shares its name. Re-index Dart projects after upgrading. +- In Dart, a call further down a chain, like Riverpod's `FutureProvider.autoDispose.family(…)` or `events.map(mapper).transform(…)` on a stream, now links to the method of the type the chain before it produces, worked out from what each step is declared to return, and to nothing when that type can't be worked out. Before, it linked to whichever project method shared its name, so `X.autoDispose.family(…)` reached the same provider builder whatever `X` was, and a stream's `transform` reached an unrelated `transform` method. `super.` calls now reach the superclass's method, `context.read().add(…)` reaches the bloc's own `add`, and the members of an extension marked `@internal` are found too. Re-index Dart projects after upgrading. (#750) ## [1.6.2] - 2026-10-03 diff --git a/__tests__/dart-chain-links.test.ts b/__tests__/dart-chain-links.test.ts new file mode 100644 index 0000000000..e5e24a7e95 --- /dev/null +++ b/__tests__/dart-chain-links.test.ts @@ -0,0 +1,242 @@ +/** + * A later link of a Dart call chain — `Provider.autoDispose.family(…)`, + * `events.map(mapper).transform(…)` — reaches the resolver by its bare name: + * the extractor keeps one receiver level. It calls a member of what the chain + * before it evaluates to, typed from the chain's head and each link's + * declared type, or nothing — never a member found by its name alone. + * + * Without that, bloc's `events.map(mapper).transform(…)` on a Stream went to + * angular_bloc's `BlocPipe.transform`, riverpod's `X.autoDispose.family(…)` + * went to one builder's `family` whatever X was, and a sign-up test's + * `SignUpState().withEmail(e).withPassword(p)` to the login form's state. + */ +import { describe, it, expect, afterAll, beforeAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; + +let root = ''; +let cg: CodeGraph; + +beforeAll(async () => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-chain-')); + const files: Record = { + 'pubspec.yaml': 'name: app\n', + // angular_bloc's pipe: the one project `transform` a by-name guess finds. + 'lib/pipe.dart': `class BlocPipe { + Object? transform(Object? value) => value; +} +`, + 'lib/bloc.dart': `import 'dart:async'; + +class Bloc { + Stream transformEvents(Stream events, Stream Function(E) mapper) { + return events + .map(mapper) + .transform(const _FlatMap()); + } +} + +class _FlatMap { + const _FlatMap(); +} +`, + 'lib/builders.dart': `class FutureProviderBuilder { + const FutureProviderBuilder(); + + FutureProviderFamilyBuilder get family => const FutureProviderFamilyBuilder(); +} + +class FutureProviderFamilyBuilder { + const FutureProviderFamilyBuilder(); + + Object call(Object create) => create; +} + +class StateProviderBuilder { + const StateProviderBuilder(); + + StateProviderFamilyBuilder get family => const StateProviderFamilyBuilder(); +} + +class StateProviderFamilyBuilder { + const StateProviderFamilyBuilder(); + + Object call(Object create) => create; +} +`, + 'lib/providers.dart': `import 'builders.dart'; + +class FutureProvider { + static const autoDispose = FutureProviderBuilder(); +} + +class StateProvider { + static const autoDispose = StateProviderBuilder(); +} +`, + 'lib/app.dart': `import 'providers.dart'; + +final users = FutureProvider.autoDispose.family((ref, id) => 0); +final counts = StateProvider.autoDispose + .family((ref, id) => 0); +`, + 'lib/sign_up/sign_up_state.dart': `class SignUpState { + const SignUpState(); + + SignUpState withEmail(String email) => this; + SignUpState withPassword(String password) => this; +} +`, + 'test/sign_up/login_state.dart': `class LoginState { + const LoginState(); + + LoginState withEmail(String email) => this; + LoginState withPassword(String password) => this; +} +`, + 'test/sign_up/sign_up_state_test.dart': `import 'package:app/sign_up/sign_up_state.dart'; + +void main() { + final constructed = SignUpState().withEmail('a').withPassword('b'); + final constant = const SignUpState().withEmail('a'); +} +`, + 'lib/counter.dart': `abstract class BlocEventSink { + void add(E event); +} + +abstract class BlocBase { + Future close() async {} +} + +abstract class Bloc extends BlocBase implements BlocEventSink { + @override + void add(E event) {} + + @override + Future close() async { + await super.close(); + } +} + +class CounterBloc extends Bloc { + void increment() {} +} +`, + 'lib/counter_view.dart': `import 'package:flutter/widgets.dart'; +import 'counter.dart'; + +class CounterView { + void onTap(BuildContext context) { + context.read().add(1); + } +} +`, + 'lib/todo.dart': `class Todo { + const Todo(); + + Todo copyWith({String? title}) => this; +} +`, + 'lib/edit_todo.dart': `import 'todo.dart'; + +class EditTodoState { + const EditTodoState({this.initialTodo}); + + final Todo? initialTodo; + + EditTodoState copyWith({Todo? initialTodo}) => this; +} + +class EditTodoBloc { + EditTodoState state = const EditTodoState(); + + void submit() { + final todo = (state.initialTodo ?? const Todo()).copyWith(title: 'x'); + } +} +`, + 'lib/container.dart': `import 'package:meta/meta.dart'; + +class ProviderPointerManager { + void readPointer(Object provider) {} +} + +class ProviderContainer { + final ProviderPointerManager _pointerManager = ProviderPointerManager(); +} + +@internal +extension ProviderContainerTest on ProviderContainer { + ProviderPointerManager get pointerManager => _pointerManager; +} + +void probe(ProviderContainer container) { + container.pointerManager.readPointer(1); +} +`, + 'lib/other_manager.dart': `class OtherManager { + void readPointer(Object provider) {} +} +`, + }; + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + cg = await CodeGraph.init(root, { index: true }); +}); + +afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true }); +}); + +/** `from -> Owner::name` for every call edge out of a file. */ +function callsFrom(file: string): string[] { + const ids = cg.getNodesInFile(file).map((n) => n.id); + return cg + .getOutgoingEdgesFrom(ids) + .filter((e) => e.kind === 'calls') + .map((e) => `${cg.getNode(e.source)!.name} -> ${cg.getNode(e.target)!.qualifiedName}`) + .sort(); +} + +describe('Dart call chains link through their receiver’s declared types', () => { + it('a Stream’s `transform` is not a project method of that name', () => { + expect(callsFrom('lib/bloc.dart')).toEqual([]); + }); + + it('`X.autoDispose.family(…)` is the family getter of the builder X’s constant holds', () => { + expect(callsFrom('lib/app.dart')).toEqual([ + 'counts -> StateProviderBuilder::family', + 'users -> FutureProviderBuilder::family', + ]); + }); + + it('every link of a fluent chain stays on the type each link returns', () => { + expect(callsFrom('test/sign_up/sign_up_state_test.dart')).toEqual([ + 'main -> SignUpState::withEmail', + 'main -> SignUpState::withEmail', + 'main -> SignUpState::withPassword', + ]); + }); + + it('`super.close()` is the superclass’s, and `context.read()` hands back a T', () => { + expect(callsFrom('lib/counter.dart')).toEqual(['close -> BlocBase::close']); + expect(callsFrom('lib/counter_view.dart')).toEqual(['onTap -> Bloc::add']); + }); + + it('a parenthesized receiver is what its last operand is', () => { + expect(callsFrom('lib/edit_todo.dart')).toEqual(['submit -> Todo::copyWith']); + }); + + it('a getter an annotated extension adds is in the chain, and is called', () => { + expect(callsFrom('lib/container.dart')).toEqual([ + 'probe -> ProviderContainerTest::pointerManager', + 'probe -> ProviderPointerManager::readPointer', + ]); + }); +}); diff --git a/src/resolution/index.ts b/src/resolution/index.ts index 7364c3e254..198446483c 100644 --- a/src/resolution/index.ts +++ b/src/resolution/index.ts @@ -21,7 +21,7 @@ import { isImportableKind, CPP_DEFINE_SIGNATURE, } from './types'; -import { isPythonSelfCall, matchJsStoreBindingCall, isUnresolvedJsMemberCall, matchObjectPathCall, thisScopeCaller, isVisibleAcrossFiles, matchReference, matchFunctionRef, matchDottedCallChain, matchScopedCallChain, matchMethodCall, sameLanguageFamily, crossesCodeBoundary, gateLanguageMatch, dumpNameMatcherProfile, clearNameMatcherMemos, isRustNameInScope, CASE_INSENSITIVE_LANGUAGES, isDartMemberRead, matchDartMemberRead } from './name-matcher'; +import { isPythonSelfCall, matchJsStoreBindingCall, isUnresolvedJsMemberCall, matchObjectPathCall, thisScopeCaller, isVisibleAcrossFiles, matchReference, matchFunctionRef, matchDottedCallChain, matchScopedCallChain, matchMethodCall, sameLanguageFamily, crossesCodeBoundary, gateLanguageMatch, dumpNameMatcherProfile, clearNameMatcherMemos, isRustNameInScope, CASE_INSENSITIVE_LANGUAGES, isDartMemberRead, matchDartMemberRead, isDartChainLink, matchDartChainLink } from './name-matcher'; import { isVisibleCppMacro, clearCppMacroVisibility } from './cpp-macro-visibility'; import { isCppConstructorRef, matchCppConstructor } from './cpp-constructor'; import { gateSwiftTypeTarget, clearSwiftTypeVisibility, swiftExtendedConformances } from './swift-type-visibility'; @@ -1136,6 +1136,10 @@ export class ReferenceResolver { // A Dart member read (`x.area`) links the getter the receiver's type // reaches, as a call, or nothing — never a guess by name (#2338). if (isDartMemberRead(ref)) return matchDartMemberRead(ref, this.context); + // So does a later link of a Dart call chain (`X.autoDispose.family(…)`, + // `events.map(f).transform(…)`), which arrives by its bare name: a member + // of what the chain's head and links are declared to be, or nothing (#750). + if (isDartChainLink(ref, this.context)) return matchDartChainLink(ref, this.context); // Skip built-in/external references if (this.isBuiltInOrExternal(ref)) { diff --git a/src/resolution/name-matcher.ts b/src/resolution/name-matcher.ts index c7d7a0e072..1b844ed84a 100644 --- a/src/resolution/name-matcher.ts +++ b/src/resolution/name-matcher.ts @@ -2893,6 +2893,8 @@ function dartMemberDepth(method: Node, ref: UnresolvedRef, context: ResolutionCo /** Past any real member's depth: an extension member only applies when no instance member does. */ const DART_EXTENSION_RANK = 1000; +/** Past any lineage's depth (at most 40): an extension on a type parameter is the least specific. */ +const DART_UNIVERSAL_RANK = 100; const DART_HIERARCHIES = new WeakMap>>(); /** Every type the classes around a Dart call site are, by supertype distance (at most 40). */ @@ -2943,7 +2945,8 @@ function isDartMember(n: Node): boolean { * extractor keeps one receiver level, so the later links of a chain — * `LoginState().withEmail(e).withPassword(p)` — arrive as bare names; their * line shows `.withPassword(` all the same. (A Dart ref's column sits just - * past the name; the name's start is found either way.) + * past the name; the name's start is found either way.) A spread's + * `...items()` is no receiver. */ function isReceiverLessDartCall(ref: UnresolvedRef, context: ResolutionContext): boolean { const line = context.getFileLines?.(ref.filePath)?.[ref.line - 1] ?? context.readFile(ref.filePath)?.split('\n')[ref.line - 1]; @@ -2954,7 +2957,767 @@ function isReceiverLessDartCall(ref: UnresolvedRef, context: ResolutionContext): else if (ref.column >= name.length && line.startsWith(name, ref.column - name.length)) start = ref.column - name.length; else start = line.indexOf(name); if (start < 0) return true; - return !/\.\s*$/.test(line.slice(0, start)); + const before = line.slice(0, start); + return !/\.\s*$/.test(before) || /(?:^|[^.])\.\.\.\s*$/.test(before); +} + +/** + * A later link of a Dart call chain — `Provider.autoDispose.family<…>(…)`, + * `events.map(mapper).transform(…)`, `const LoginState().withEmail(e)` — which + * the extractor records by its bare name, its receiver dropped. + */ +export function isDartChainLink(ref: UnresolvedRef, context: ResolutionContext): boolean { + return ref.language === 'dart' && ref.referenceKind === 'calls' && /^[A-Za-z_$][\w$]*$/.test(ref.referenceName) && + !isReceiverLessDartCall(ref, context); +} + +/** + * A Dart chain link calls a member of what the chain before it evaluates to, + * typed from evidence alone: the chain's head (a type, a constructor call, a + * string, `this` / `super`, a variable, field or getter with a declared type) + * and each link's declared type (a method's or getter's return type, a + * field's type, what a static constant is initialized with). Without that + * evidence it links nothing — never a member found by its name: bloc's + * `events.map(mapper).transform(…)` is a Stream's, not angular_bloc's + * `BlocPipe.transform`, and riverpod's `FutureProvider.autoDispose.family(…)` + * is the `family` getter of the builder `autoDispose` holds, not whichever + * builder's `family` sat nearest (#750). + */ +export function matchDartChainLink(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null { + if (!context.getNodesByName(ref.referenceName).some((n) => n.language === 'dart')) return null; + const code = dartCodeOf(ref.filePath, context); + const start = code ? dartNameStart(ref, code) : -1; + if (!code || start < 0) return null; + // `x.name` / `x?.name`: the receiver ends before the dot. `..name` is a cascade's. + let end = start - 1; + while (end >= 0 && /\s/.test(code.text[end]!)) end--; + if (code.text[end] !== '.' || code.text[end - 1] === '.') return null; + end--; + if (code.text[end] === '?') end--; + while (end >= 0 && /\s/.test(code.text[end]!)) end--; + const chain = readDartChain(code.text, end); + const receiver = chain ? typeDartChain(chain, ref, context, 0) : null; + if (!receiver) return null; + // Static members are the type's own: `p.Provider.autoDispose(…)` calls the + // constant, as `Provider.autoDispose(…)` does. + if (receiver.static) { + const member = dartStaticMember(receiver.type, ref.referenceName, ref, context); + return member && member.kind !== 'enum_member' + ? { original: ref, targetNodeId: member.id, confidence: 0.85, resolvedBy: 'qualified-name' } : null; + } + const member = dartMemberOf(receiver.type, ref.referenceName, ref, context, (n) => !isDartSetter(n, context), receiver.viaSuper ? 1 : 0)?.node; + return member ? { original: ref, targetNodeId: member.id, confidence: 0.85, resolvedBy: 'instance-method' } : null; +} + +/** + * Lookups that hand back an instance of the one type they are given: + * provider's and flutter_bloc's `context.read()` / `watch()` / + * `BlocProvider.of(context)`, get_it's `get()`, GetX's `find()`, and + * Flutter's `findAncestorStateOfType()` family. + */ +const DART_TYPE_ARGUMENT_LOOKUPS: ReadonlySet = new Set([ + 'read', 'watch', 'get', 'find', 'of', 'maybeOf', 'call', 'dependOnInheritedWidgetOfExactType', + 'getInheritedWidgetOfExactType', 'findAncestorStateOfType', 'findAncestorWidgetOfExactType', 'findRootAncestorStateOfType', +]); + +/** Words that can stand before a Dart name without being its declared type. */ +const DART_NON_TYPE_WORDS: ReadonlySet = new Set([ + 'final', 'var', 'late', 'const', 'required', 'covariant', 'static', 'external', 'return', 'await', 'yield', 'throw', + 'new', 'in', 'is', 'as', 'case', 'else', 'if', 'for', 'while', 'do', 'switch', 'assert', 'this', 'super', 'get', 'set', + 'operator', 'async', 'sync', 'show', 'hide', 'typedef', 'extends', 'with', 'implements', 'on', +]); + +/** A link of a Dart chain: `.name`, `.name<…>(…)` (`call`), or a subscript `[…]` (`index`). */ +interface DartChainLink { name: string; typeArgs: string[]; call: boolean; index: boolean } + +/** + * What a Dart chain starts from: a name (`x`, `Foo`, `foo(…)`, `Foo(…)`, + * with the keyword written before it — `const`, `new`, `as`, `await`), a + * string literal, or a parenthesized expression. + */ +type DartChainHead = + | { kind: 'name'; name: string; typeArgs: string[]; call: boolean; keyword: string } + | { kind: 'string' } + | { kind: 'paren'; open: number; close: number }; + +interface DartChain { head: DartChainHead; links: DartChainLink[] } + +/** What a Dart chain evaluates to: an instance of `type`, or (`static`) the type itself, before a static member. */ +interface DartValue { type: string; static: boolean; viaSuper?: boolean } + +/** + * A Dart file's code with comments and string contents blanked, where each + * line starts, the import prefixes it declares, and the files of its library + * it names: its `part`s and the file it is `part of`. + */ +interface DartCode { text: string; lineStarts: number[]; prefixes: Set; parts: string[]; partOf: string | null } + +const DART_CODE = new WeakMap>(); + +function dartCodeOf(filePath: string, context: ResolutionContext): DartCode | null { + let memo = DART_CODE.get(context); + if (!memo) DART_CODE.set(context, (memo = new Map())); + const hit = memo.get(filePath); + if (hit !== undefined) return hit; + const source = context.readFile(filePath); + let code: DartCode | null = null; + if (source !== null) { + const text = blankDartCode(source); + const lineStarts = [0]; + for (let i = 0; i < text.length; i++) if (text[i] === '\n') lineStarts.push(i + 1); + const prefixes = new Set([...text.matchAll(/^\s*import\s+['"][^'"]*['"]\s+(?:deferred\s+)?as\s+([A-Za-z_$][\w$]*)/gm)].map((m) => m[1]!)); + const sibling = (uri: string): string => path.posix.normalize(path.posix.join(path.posix.dirname(filePath), uri)); + const parts = [...source.matchAll(/^\s*part\s+['"]([^'"]+)['"]\s*;/gm)].map((m) => sibling(m[1]!)); + const partOf = /^\s*part\s+of\s+['"]([^'"]+)['"]\s*;/m.exec(source)?.[1]; + code = { text, lineStarts, prefixes, parts, partOf: partOf ? sibling(partOf) : null }; + } + // Refs arrive file by file, so a few files' worth is enough. + if (memo.size >= 64) memo.delete(memo.keys().next().value!); + memo.set(filePath, code); + return code; +} + +/** + * Dart source with comments and string contents blanked, offsets kept: a + * literal keeps its quotes, and an interpolation's code (`'${a.b()}'`) stays, + * so a chain inside one reads like any other. + */ +function blankDartCode(source: string): string { + const out = source.split(''); + const n = source.length; + const blank = (from: number, to: number): void => { + for (let k = from; k < to && k < n; k++) if (out[k] !== '\n' && out[k] !== '\r') out[k] = ' '; + }; + type Literal = { quote: string; triple: boolean; raw: boolean }; + // The literals an open `${…}` returns to, with the brace depth around each. + const outer: Array<{ literal: Literal; depth: number }> = []; + let literal: Literal | null = null; + let depth = 0; + let i = 0; + while (i < n) { + const c = source[i]!; + if (literal) { + if (!literal.raw && c === '\\') { + blank(i, i + 2); + i += 2; + } else if (!literal.raw && c === '$' && source[i + 1] === '{') { + blank(i, i + 2); + outer.push({ literal, depth }); + literal = null; + depth = 0; + i += 2; + } else if (source.startsWith(literal.triple ? literal.quote.repeat(3) : literal.quote, i)) { + i += literal.triple ? 3 : 1; + literal = null; + } else if (!literal.triple && c === '\n') { + literal = null; + i++; + } else { + blank(i, i + 1); + i++; + } + continue; + } + if (c === '/' && source[i + 1] === '/') { + const eol = source.indexOf('\n', i); + const stop = eol < 0 ? n : eol; + blank(i, stop); + i = stop; + } else if (c === '/' && source[i + 1] === '*') { + let nest = 1; + let j = i + 2; + while (j < n && nest > 0) { + if (source[j] === '/' && source[j + 1] === '*') { nest++; j += 2; } + else if (source[j] === '*' && source[j + 1] === '/') { nest--; j += 2; } + else j++; + } + blank(i, j); + i = j; + } else if (c === "'" || c === '"') { + const triple = source.startsWith(c.repeat(3), i); + literal = { quote: c, triple, raw: source[i - 1] === 'r' && !/[\w$]/.test(source[i - 2] ?? '') }; + i += triple ? 3 : 1; + } else { + if (outer.length > 0 && c === '{') depth++; + else if (outer.length > 0 && c === '}') { + if (depth === 0) { + blank(i, i + 1); + ({ literal, depth } = outer.pop()!); + i++; + continue; + } + depth--; + } + i++; + } + } + return out.join(''); +} + +/** Where a Dart ref's name starts in its file's code. Its column sits just past the name (or on it). */ +function dartNameStart(ref: UnresolvedRef, code: DartCode): number { + const from = code.lineStarts[ref.line - 1]; + if (from === undefined) return -1; + const line = code.text.slice(from, code.lineStarts[ref.line] ?? code.text.length); + const name = ref.referenceName; + let start = -1; + if (line.startsWith(name, ref.column)) start = ref.column; + else if (ref.column >= name.length && line.startsWith(name, ref.column - name.length)) start = ref.column - name.length; + else start = line.indexOf(name); + return start < 0 ? -1 : from + start; +} + +/** The offset of the `open` bracket matching the `close` one at `at`, read backwards; -1 past `limit` characters. */ +function dartOpening(text: string, at: number, open: string, close: string, limit = 20000): number { + let depth = 0; + for (let k = at; k >= 0 && at - k < limit; k--) { + if (text[k] === close) depth++; + else if (text[k] === open && --depth === 0) return k; + else if (open === '<' && /[;{}=]/.test(text[k]!)) return -1; + } + return -1; +} + +/** The simple name a Dart type is written as: `Foo` for `p.Foo?`. */ +function dartSimpleTypeName(text: string): string | null { + const name = text.replace(/<[\s\S]*$/, '').replace(/\?/g, '').trim().split('.').pop()!.trim(); + return /^[A-Za-z_$][\w$]*$/.test(name) ? name : null; +} + +/** + * The links and head of the Dart expression whose last character is at + * `end`, read backwards: `FutureProvider.autoDispose` → `FutureProvider` + * then `.autoDispose`; `events.map(mapper)` → `events` then `.map(…)`. Null + * for a shape the walk does not read — a cascade section, a number, a call + * of an expression. + */ +function readDartChain(text: string, end: number): DartChain | null { + const links: DartChainLink[] = []; + let i = end; + const skip = (): void => { + while (i >= 0 && /\s/.test(text[i]!)) i--; + }; + for (let step = 0; step < 32; step++) { + skip(); + while (text[i] === '!') { + i--; + skip(); + } + if (text[i] === ']') { + const open = dartOpening(text, i, '[', ']'); + if (open < 0) return null; + links.push({ name: '', typeArgs: [], call: false, index: true }); + i = open - 1; + continue; + } + if (text[i] === "'" || text[i] === '"') return { head: { kind: 'string' }, links: links.reverse() }; + let call = false; + let typeArgs: string[] = []; + if (text[i] === ')') { + const close = i; + const open = dartOpening(text, i, '(', ')'); + if (open < 0) return null; + i = open - 1; + skip(); + if (text[i] === '>') { + const lt = dartOpening(text, i, '<', '>', 400); + if (lt < 0) return null; + typeArgs = splitCppTopLevel(text.slice(lt + 1, i)); + i = lt - 1; + skip(); + } + if (!/[\w$]/.test(text[i] ?? '')) { + // `(…)` with no name before it is the head — unless an expression is called: `f()(…)`. + if (typeArgs.length > 0 || text[i] === ')' || text[i] === ']') return null; + return { head: { kind: 'paren', open, close }, links: links.reverse() }; + } + call = true; + } else if (text[i] === '>') { + // `BlocProvider.value(…)`: a type written with its arguments. + const lt = dartOpening(text, i, '<', '>', 400); + if (lt < 0) return null; + typeArgs = splitCppTopLevel(text.slice(lt + 1, i)); + i = lt - 1; + skip(); + } + const nameEnd = i + 1; + while (i >= 0 && /[\w$]/.test(text[i]!)) i--; + const name = text.slice(i + 1, nameEnd); + if (!/^[A-Za-z_$][\w$]*$/.test(name)) return null; + let j = i; + while (j >= 0 && /\s/.test(text[j]!)) j--; + if (text[j] === '.') { + // `obj..a().b()`: a cascade section's receiver is the cascade's target. + if (text[j - 1] === '.') return null; + links.push({ name, typeArgs, call, index: false }); + i = j - 1; + if (text[i] === '?') i--; + continue; + } + const keyword = /([A-Za-z_]\w*)$/.exec(text.slice(Math.max(0, j - 10), j + 1))?.[1] ?? ''; + return { head: { kind: 'name', name, typeArgs, call, keyword }, links: links.reverse() }; + } + return null; +} + +/** What a Dart chain evaluates to, link by link, or null where the evidence runs out. */ +function typeDartChain(chain: DartChain, ref: UnresolvedRef, context: ResolutionContext, depth: number): DartValue | null { + if (depth > 3) return null; + const head = chain.head; + let links = chain.links; + let value: DartValue | null; + if (head.kind === 'string') value = { type: 'String', static: false }; + else if (head.kind === 'paren') value = typeDartParen(head, ref, context, depth); + else { + let name = head; + // `p.Provider.autoDispose`: an import prefix names a library, so the chain + // starts at the link after it. + const first = links[0]; + if (!name.call && name.typeArgs.length === 0 && first && !first.index && dartCodeOf(ref.filePath, context)?.prefixes.has(name.name)) { + name = { kind: 'name', name: first.name, typeArgs: first.typeArgs, call: first.call, keyword: '' }; + links = links.slice(1); + } + // `const Foo.named(…)`: the named constructor is the head's own link. + if ((name.keyword === 'const' || name.keyword === 'new') && !name.call && links[0]?.call) links = links.slice(1); + value = typeDartHead(name, ref, context, depth); + } + for (const link of links) { + // Every Dart object's `toString()` returns a String, whatever it is. + if (link.name === 'toString' && link.call && link.typeArgs.length === 0) { + value = { type: 'String', static: false }; + continue; + } + const next = value ? typeDartLink(value, link, ref, context, depth) : null; + // A lookup nothing declared answers for hands back the type it is given, + // whatever it is called on: `context.read()` on Flutter's + // BuildContext, or on an untyped `(context) =>` parameter. + const given = !next && link.call && link.typeArgs.length === 1 && DART_TYPE_ARGUMENT_LOOKUPS.has(link.name) && + !(value && dartLinkDeclared(value, link, ref, context)) ? dartSimpleTypeName(link.typeArgs[0]!) : null; + // An untyped value stays untyped until a link says what it makes. + value = next ?? (given ? { type: given, static: false } : null); + } + return value; +} + +/** Whether the type a Dart chain has reached declares the member a link names. */ +function dartLinkDeclared(value: DartValue, link: DartChainLink, ref: UnresolvedRef, context: ResolutionContext): boolean { + return value.static + ? dartStaticMember(value.type, link.name, ref, context) !== null + : dartMemberOf(value.type, link.name, ref, context, (n) => !isDartSetter(n, context), value.viaSuper ? 1 : 0) !== null; +} + +/** `(x as Foo)` is a Foo; any other parenthesized expression is what its last operand is: `(a ?? Todo(…))`. */ +function typeDartParen(head: { open: number; close: number }, ref: UnresolvedRef, context: ResolutionContext, depth: number): DartValue | null { + const code = dartCodeOf(ref.filePath, context); + if (!code) return null; + const inner = code.text.slice(head.open + 1, head.close); + const cast = /\bas\s+((?:[A-Za-z_$][\w$]*\.)?[A-Za-z_$][\w$]*)\s*(?:<[^()]*>)?\s*\??\s*$/.exec(inner); + if (cast) { + const type = dartSimpleTypeName(cast[1]!); + return type ? { type, static: false } : null; + } + let end = head.close - 1; + while (end > head.open && /\s/.test(code.text[end]!)) end--; + return dartExpressionValue(code.text, end, ref, context, depth); +} + +/** The value of the Dart expression ending at `end`: an instance, never a type, and never an awaited one. */ +function dartExpressionValue(text: string, end: number, ref: UnresolvedRef, context: ResolutionContext, depth: number): DartValue | null { + const chain = readDartChain(text, end); + if (!chain || (chain.head.kind === 'name' && chain.head.keyword === 'await')) return null; + const value = typeDartChain(chain, ref, context, depth + 1); + return value && !value.static ? value : null; +} + +/** What a Dart chain's head evaluates to. */ +function typeDartHead( + head: { name: string; typeArgs: string[]; call: boolean; keyword: string }, + ref: UnresolvedRef, + context: ResolutionContext, + depth: number, +): DartValue | null { + const name = head.name; + if (name === 'this' || name === 'super') { + const own = dartEnclosingType(ref, context); + return own ? { type: own.name, static: false, viaSuper: name === 'super' } : null; + } + if (head.keyword === 'const' || head.keyword === 'new' || head.keyword === 'as') return { type: name, static: false }; + if (head.keyword === 'is') return null; + const isType = context.getNodesByName(name).some((n) => n.language === 'dart' && DART_TYPE_KINDS.has(n.kind)); + if (head.call) { + // `Foo(…)` constructs a Foo; `foo(…)` is what the function says it returns, + // or — a variable holding a callable, riverpod's `family(0)` — what its `call` does. + if (isType) return { type: name, static: false }; + const fn = dartFunctionNamed(name, ref, context); + if (fn) { + const type = dartReturnType(fn, head.typeArgs, context); + return type ? { type, static: false } : null; + } + const held = dartVariableType(name, ref, context, depth); + return held ? dartCallResult(held, head.typeArgs, ref, context) : null; + } + // `Foo.` before a static member — a type outside the project included, whose members nothing reaches. + if (isType || (/^[A-Z]/.test(name) && !context.getNodesByName(name).some((n) => n.language === 'dart' && (n.kind === 'constant' || n.kind === 'variable')))) { + return { type: name, static: true }; + } + const type = dartVariableType(name, ref, context, depth); + return type ? { type, static: false } : null; +} + +/** What one link of a Dart chain makes of the value before it. */ +function typeDartLink(value: DartValue, link: DartChainLink, ref: UnresolvedRef, context: ResolutionContext, depth: number): DartValue | null { + if (link.index) return null; + if (value.static) { + const member = dartStaticMember(value.type, link.name, ref, context); + if (!member) { + // `BlocProvider.value(…)`, `AsyncValue.data(…)`: a constructor the index holds no node for. + return link.call && context.getNodesByName(value.type).some((n) => n.language === 'dart' && DART_TYPE_KINDS.has(n.kind)) + ? { type: value.type, static: false } : null; + } + if (member.kind === 'enum_member') return link.call ? null : { type: value.type, static: false }; + if (member.kind === 'constant') { + // `FutureProvider.autoDispose`: the value the static constant holds. + const held = dartConstantType(member, ref, context, depth); + if (!held) return null; + return link.call ? dartCallResult(held, link.typeArgs, ref, context) : { type: held, static: false }; + } + return typeDartMemberUse(member, link, ref, context); + } + const member = dartMemberOf(value.type, link.name, ref, context, (n) => !isDartSetter(n, context), value.viaSuper ? 1 : 0)?.node; + if (member) return typeDartMemberUse(member, link, ref, context); + // A field mints no node: its declared type is read from its class. + if (link.call) return null; + const field = dartFieldType(value.type, link.name, ref, context, depth); + return field ? { type: field, static: false } : null; +} + +/** What using a member makes: a method's call or a getter's read is its declared return type; a getter called is its value called. */ +function typeDartMemberUse(member: Node, link: DartChainLink, ref: UnresolvedRef, context: ResolutionContext): DartValue | null { + const getter = isDartGetter(member, context); + const type = dartReturnType(member, getter ? [] : link.typeArgs, context); + if (!type) return null; + if (getter) return link.call ? dartCallResult(type, link.typeArgs, ref, context) : { type, static: false }; + // A method named without a call is a tear-off: a function, not its result. + return link.call ? { type, static: false } : null; +} + +/** What calling a value of `type` returns — its `call` method's declared return type. */ +function dartCallResult(type: string, typeArgs: string[], ref: UnresolvedRef, context: ResolutionContext): DartValue | null { + const call = dartMemberOf(type, 'call', ref, context, (n) => !isDartGetter(n, context))?.node; + const result = call ? dartReturnType(call, typeArgs, context) : null; + return result ? { type: result, static: false } : null; +} + +const DART_RETURN_TYPES = new WeakMap>(); + +/** + * A Dart function's declared return type as a simple name, a type parameter + * of its own replaced by the type argument the call gives (`T read()` + * called as `read()` is a Foo); a type parameter of its class + * (`State get state` in `BlocBase`) says nothing without the + * receiver's own arguments. + */ +function dartReturnType(fn: Node, typeArgs: string[], context: ResolutionContext): string | null { + let memo = DART_RETURN_TYPES.get(context); + if (!memo) DART_RETURN_TYPES.set(context, (memo = new Map())); + let info = memo.get(fn.id); + if (info === undefined) { + info = null; + const type = fn.returnType ? dartSimpleTypeName(fn.returnType) : null; + if (type) { + // `static T of(…)` in `BlocProvider`: the function's own parameter is the one meant. + const own = declaredTypeParameters(fn, context); + const cut = fn.qualifiedName.lastIndexOf('::'); + const owner = cut > 0 && !own.includes(type) ? context.getNodesInFile(fn.filePath).find((n) => DART_TYPE_KINDS.has(n.kind) && + n.qualifiedName === fn.qualifiedName.slice(0, cut) && n.startLine <= fn.startLine && n.endLine >= fn.endLine) : undefined; + if (!owner || !declaredTypeParameters(owner, context).includes(type)) info = { type, own }; + } + memo.set(fn.id, info); + } + if (!info) return null; + const at = info.own.indexOf(info.type); + if (at < 0) return info.type; + return typeArgs[at] ? dartSimpleTypeName(typeArgs[at]!) : null; +} + +/** The innermost Dart class, mixin, enum or extension a reference sits in. */ +function dartEnclosingType(ref: UnresolvedRef, context: ResolutionContext): Node | null { + let own: Node | null = null; + for (const n of context.getNodesInFile(ref.filePath)) { + if (DART_TYPE_KINDS.has(n.kind) && n.startLine <= ref.line && n.endLine >= ref.line && (!own || n.startLine >= own.startLine)) own = n; + } + return own; +} + +/** + * The static member `name` the Dart type `typeName` itself declares — a + * static method or getter, a named constructor or factory, a static + * constant, an enum value — preferring the call site's file, then the + * nearest. Static members are not inherited. + */ +function dartStaticMember(typeName: string, name: string, ref: UnresolvedRef, context: ResolutionContext): Node | null { + const owners = context.getNodesByName(typeName).filter((n) => n.language === 'dart' && DART_TYPE_KINDS.has(n.kind)); + if (owners.length === 0) return null; + const found = context.getNodesByName(name).filter((m) => m.language === 'dart' && + (m.kind === 'method' || m.kind === 'function' || m.kind === 'constant' || m.kind === 'enum_member') && + owners.some((o) => o.filePath === m.filePath && m.qualifiedName === `${o.qualifiedName}::${name}`) && + !isDartSetter(m, context) && isDartStaticMember(m, typeName, context)); + if (found.length <= 1) return found[0] ?? null; + return found.find((m) => m.filePath === ref.filePath) ?? + found.reduce((a, b) => (computePathProximity(ref.filePath, b.filePath) > computePathProximity(ref.filePath, a.filePath) ? b : a)); +} + +/** + * Whether a member of the Dart type `owner` is reached through the type + * itself: a static member, constant or enum value, or a named constructor or + * factory (`factory ProviderContainer.test(…)`) — not an instance member + * sharing a constructor's name (`AsyncValue`'s `error` getter beside its + * `AsyncValue.error(…)` factory). + */ +function isDartStaticMember(m: Node, owner: string, context: ResolutionContext): boolean { + if (m.isStatic || m.kind === 'constant' || m.kind === 'enum_member') return true; + const lines = context.getFileLines?.(m.filePath) ?? context.readFile(m.filePath)?.split(/\r?\n/) ?? []; + const head = `${(lines[m.startLine - 1] ?? '').slice(m.startColumn)} ${lines[m.startLine] ?? ''} ${lines[m.startLine + 1] ?? ''}`; + const esc = (s: string): string => s.replace(/\$/g, '\\$'); + return new RegExp(`(?:^|[^\\w$.])${esc(owner)}\\s*\\.\\s*${esc(m.name)}\\s*[(<]`).test(head); +} + +/** + * The function a bare Dart call `name(…)` means: a member of the type around + * it (an implicit `this.`), else a function of the file, else the one + * function of that name the project declares. + */ +function dartFunctionNamed(name: string, ref: UnresolvedRef, context: ResolutionContext): Node | null { + const own = dartEnclosingType(ref, context); + const member = own ? dartMemberOf(own.name, name, ref, context, (n) => !isDartGetter(n, context) && !isDartSetter(n, context))?.node : undefined; + if (member) return member; + return dartLibraryPick(context.getNodesByName(name).filter((n) => n.language === 'dart' && n.kind === 'function' && !n.qualifiedName.includes('::')), ref, context); +} + +/** + * Of same-named top-level Dart declarations, the one the call's library + * holds — its own file, then a `part` of it (riverpod_generator's + * `depFamilyProvider` in `missing_dependencies.g.dart`) — else the only one. + */ +function dartLibraryPick(nodes: Node[], ref: UnresolvedRef, context: ResolutionContext): Node | null { + const own = nodes.find((n) => n.filePath === ref.filePath); + if (own) return own; + const library = dartLibraryFiles(ref.filePath, context); + const shared = nodes.filter((n) => library.has(n.filePath)); + if (shared.length === 1) return shared[0]!; + return nodes.length === 1 ? nodes[0]! : null; +} + +/** The files of a Dart file's library: itself, its `part`s, and the file it is `part of` with that file's parts. */ +function dartLibraryFiles(filePath: string, context: ResolutionContext): Set { + const files = new Set([filePath]); + const code = dartCodeOf(filePath, context); + for (const part of code?.parts ?? []) files.add(part); + if (code?.partOf) { + files.add(code.partOf); + for (const part of dartCodeOf(code.partOf, context)?.parts ?? []) files.add(part); + } + return files; +} + +/** + * The declared type of a Dart variable a chain starts from: a local or + * parameter the code around the call declares (the nearest declaration wins, + * and an untyped one ends the search), a field or getter of the class around + * it, or a top-level variable. + */ +function dartVariableType(name: string, ref: UnresolvedRef, context: ResolutionContext, depth: number): string | null { + const local = dartLocalType(name, ref, context, depth); + if (local !== undefined) return local; + const field = inferMemberReceiverType(name, ref, context); + if (field) return dartSimpleTypeName(field); + const own = dartEnclosingType(ref, context); + const getter = own ? dartMemberOf(own.name, name, ref, context, (n) => isDartGetter(n, context))?.node : undefined; + if (getter) return dartReturnType(getter, [], context); + const top = dartLibraryPick(context.getNodesByName(name).filter((n) => n.language === 'dart' && n.kind === 'constant' && !n.qualifiedName.includes('::')), ref, context); + return top ? dartConstantType(top, ref, context, depth) : null; +} + +/** + * The type of the nearest declaration of `name` before the call, within the + * function around it: its declared type (`final Ticker _ticker`, `Foo? x`, + * `(BuildContext context)`), else what its initializer evaluates to (`final + * todo = Todo(…)`). Null for a declaration that says no type (a `for (final + * x in …)` variable, an untyped closure parameter); undefined for none. + */ +function dartLocalType(name: string, ref: UnresolvedRef, context: ResolutionContext, depth: number): string | null | undefined { + const code = dartCodeOf(ref.filePath, context); + const at = code ? dartNameStart(ref, code) : -1; + if (!code || at < 0) return undefined; + const start = code.lineStarts[enclosingScopeStartLine(ref, context) - 1] ?? 0; + const scope = code.text.slice(start, at); + const uses = dartNameUses(code, ref.filePath, name, context); + // The last use before the call: uses are in file order. + let lo = 0; + let hi = uses.length; + while (lo < hi) { + const mid = (lo + hi) >> 1; + if (uses[mid]! < at) lo = mid + 1; + else hi = mid; + } + for (let u = lo - 1; u >= 0 && uses[u]! >= start; u--) { + const pos = uses[u]! - start; + const before = scope.slice(Math.max(0, pos - 120), pos); + const after = scope.slice(pos + name.length); + const declared = /([A-Za-z_$][\w$]*)\s*(<[^;{}()=]*>)?\s*\??\s+$/.exec(before); + const typed = declared && !DART_NON_TYPE_WORDS.has(declared[1]!) && /^\s*(?:[=;,)}]|in\b)/.test(after) && + !/^\s*==/.test(after) ? declared[1]! : null; + if (typed) return typed; + // `final x = …`, `var x = …`: the initializer says the type. + if (/(?:^|[^\w$])(?:final|var|late|const)\s+$/.test(before)) { + const init = /^\s*=(?![=>])/.exec(after); + return init ? dartInitializerType(code.text, start + pos + name.length + init[0].length, ref, context, depth) : null; + } + // A closure's untyped parameter — `(context, state) =>` — or a `catch (e)`; + // not an argument of a call, `foo(x, (a) {…})`, nor an `if (x) {`. + if (/^\s*[,)]/.test(after) && /[(,]\s*$/.test(before)) { + const open = dartGroupOpen(code.text, start + pos); + const close = open < 0 ? -1 : dartGroupClose(code.text, open); + const callee = /([\w$]*)\s*(?:<[^;{}()]*>)?\s*$/.exec(code.text.slice(Math.max(0, open - 60), Math.max(0, open)))?.[1] ?? ''; + if (callee === 'catch') return null; + if (close >= 0 && !/[\w$>)\]]\s*$/.test(code.text.slice(Math.max(0, open - 60), Math.max(0, open))) && + /^\)\s*(?:async\s*\*?|sync\s*\*)?\s*(?:=>|\{)/.test(code.text.slice(close, close + 30))) return null; + } + } + return undefined; +} + +/** + * The `>` closing a Dart type argument list opened at `open` — one followed + * by a call, a member or another `>`, which a comparison's `<` never is — or -1. + */ +function dartTypeArgumentsEnd(text: string, open: number): number { + let depth = 0; + for (let k = open; k < text.length && k - open < 400; k++) { + const ch = text[k]; + if (ch === '<') depth++; + else if (ch === '>' && --depth === 0) return /^\s*[(.>?]/.test(text.slice(k + 1, k + 4)) ? k : -1; + else if (ch === ';' || ch === '{' || ch === '}' || ch === '=') return -1; + } + return -1; +} + +/** The `(` of the parenthesized group around offset `at`, read backwards; -1 when there is none nearby. */ +function dartGroupOpen(text: string, at: number): number { + let parens = 0; + let braces = 0; + for (let k = at - 1; k >= 0 && at - k < 4000; k--) { + const ch = text[k]; + if (ch === '}') braces++; + else if (ch === '{') { + if (braces-- === 0) return -1; + } else if (braces > 0) continue; + else if (ch === ')') parens++; + else if (ch === '(') { + if (parens-- === 0) return k; + } else if (ch === ';') return -1; + } + return -1; +} + +/** The `)` closing the `(` at `open`; -1 when it is not found nearby. */ +function dartGroupClose(text: string, open: number): number { + let depth = 0; + for (let k = open; k < text.length && k - open < 8000; k++) { + if (text[k] === '(') depth++; + else if (text[k] === ')' && --depth === 0) return k; + } + return -1; +} + +const DART_NAME_USES = new WeakMap>(); + +/** Where a name is written in a Dart file's code — not as a member (`.name`) — read once per file and name. */ +function dartNameUses(code: DartCode, filePath: string, name: string, context: ResolutionContext): number[] { + let memo = DART_NAME_USES.get(context); + if (!memo) DART_NAME_USES.set(context, (memo = new Map())); + const key = `${filePath}|${name}`; + const hit = memo.get(key); + if (hit) return hit; + const uses = [...code.text.matchAll(new RegExp(`(? m.index!); + if (memo.size >= 4096) memo.delete(memo.keys().next().value!); + memo.set(key, uses); + return uses; +} + +/** What the Dart expression starting at `from` evaluates to, read back from where its statement ends. */ +function dartInitializerType(text: string, from: number, ref: UnresolvedRef, context: ResolutionContext, depth: number): string | null { + let nest = 0; + let k = from; + for (; k < text.length && k - from < 4000; k++) { + const ch = text[k]!; + // `AsyncNotifierProvider.family(…)`: a type argument list's commas end nothing. + if (ch === '<' && /[\w$]/.test(text[k - 1] ?? '')) { + const close = dartTypeArgumentsEnd(text, k); + if (close > 0) { + k = close; + continue; + } + } + if (ch === '(' || ch === '[' || ch === '{') nest++; + else if (ch === ')' || ch === ']' || ch === '}') { + if (nest === 0) break; + nest--; + } else if ((ch === ';' || ch === ',') && nest === 0) break; + } + let end = k - 1; + while (end >= from && /\s/.test(text[end]!)) end--; + if (end < from) return null; + return dartExpressionValue(text, end, ref, context, depth)?.type ?? null; +} + +/** + * The type a Dart constant is declared with — `static const Foo x = …`, + * `final Foo? x` — or, with none written, what its initializer evaluates to: + * riverpod's `static const autoDispose = AutoDisposeFutureProviderBuilder();`. + */ +function dartConstantType(constant: Node, ref: UnresolvedRef, context: ResolutionContext, depth: number): string | null { + const code = dartCodeOf(constant.filePath, context); + const from = code?.lineStarts[constant.startLine - 1]; + if (!code || from === undefined) return null; + const head = new RegExp(`\\b(?:const|final|var)\\s+(?:([A-Za-z_$][\\w$.]*)\\s*(?:<[^;=]*>)?\\s*\\??\\s+)?${constant.name.replace(/\$/g, '\\$')}\\s*=(?![=>])`) + .exec(code.text.slice(from, from + 600)); + if (!head) return null; + if (head[1] && !DART_NON_TYPE_WORDS.has(head[1])) return dartSimpleTypeName(head[1]); + const site: UnresolvedRef = { ...ref, filePath: constant.filePath, line: constant.startLine, column: 0 }; + return dartInitializerType(code.text, from + head.index + head[0].length, site, context, depth + 1); +} + +/** + * The type a Dart class — or a type it extends, mixes in or implements — + * declares a field `name` with (`final ProviderPointerManager _pointerManager`), + * or what the field is initialized with (`final _cache = Cache()`). + */ +function dartFieldType(typeName: string, name: string, ref: UnresolvedRef, context: ResolutionContext, depth: number): string | null { + const lineage = [...dartLineage(typeName, context)].sort((a, b) => a[1] - b[1]); + for (const [owner] of lineage) { + for (const decl of context.getNodesByName(owner)) { + if (decl.language !== 'dart' || !DART_TYPE_KINDS.has(decl.kind)) continue; + const declared = classMemberType(decl, name, context); + if (declared) return dartSimpleTypeName(declared); + // An abstract getter mints no node: `ProviderElement? get _listenedElement;`. + const getter = new RegExp(String.raw`(?:^|[\s;{}])([A-Za-z_$][\w$]*)\s*(?:<[^;{}=]*>)?\s*\??\s+get\s+${name.replace(/\$/g, '\\$')}\s*;`); + for (const { text } of classMemberLines(decl, context)) { + const m = text.includes(name) ? getter.exec(text) : null; + if (m && !DART_NON_TYPE_WORDS.has(m[1]!)) return dartSimpleTypeName(m[1]!); + } + const code = dartCodeOf(decl.filePath, context); + const from = code?.lineStarts[decl.startLine - 1]; + const to = code?.lineStarts[decl.endLine]; + if (!code || from === undefined) continue; + const init = new RegExp(`\\b(?:final|var|late)\\s+${name.replace(/\$/g, '\\$')}\\s*=(?![=>])`).exec(code.text.slice(from, to)); + if (init) { + const site: UnresolvedRef = { ...ref, filePath: decl.filePath, line: decl.startLine, column: 0 }; + return dartInitializerType(code.text, from + init.index + init[0].length, site, context, depth + 1); + } + } + } + return null; } /** The simple names a Dart type's declarations extend, mix in, implement, or (an extension / mixin) sit `on`. */ @@ -3013,7 +3776,7 @@ function dartHeadOf(decl: Node, context: ResolutionContext): { supers: string[]; } const DART_LINEAGES = new WeakMap>>(); -const DART_EXTENSION_OWNERS = new WeakMap>(); +const DART_EXTENSION_OWNERS = new WeakMap>(); const DART_GETTERS = new WeakMap>(); /** A Dart type and every type it extends, mixes in or implements, by supertype distance (at most 40). */ @@ -3034,20 +3797,30 @@ function dartLineage(typeName: string, context: ResolutionContext): Map on T`, which every type has) — or null for a class's, mixin's or + * enum's member. + */ +interface DartExtensionOwner { on: string[]; named: boolean; universal: boolean } + +function dartExtensionOwner(member: Node, context: ResolutionContext): DartExtensionOwner | null { let memo = DART_EXTENSION_OWNERS.get(context); if (!memo) DART_EXTENSION_OWNERS.set(context, (memo = new Map())); const hit = memo.get(member.id); if (hit !== undefined) return hit; - let found: { on: string[]; named: boolean } | null = null; + let found: DartExtensionOwner | null = null; const cut = member.qualifiedName.lastIndexOf('::'); if (cut > 0) { const ownerQn = member.qualifiedName.slice(0, cut); const owner = context.getNodesInFile(member.filePath).find((n) => n.qualifiedName === ownerQn && n.kind === 'class' && n.startLine <= member.startLine && n.endLine >= member.startLine); const decl = owner ? dartExtensionDecl(owner, context) : null; - if (owner && decl) found = { on: dartHeadOf(owner, context).supers, named: decl.named }; + if (owner && decl) { + const on = dartHeadOf(owner, context).supers; + found = { on, named: decl.named, universal: on.length === 1 && declaredTypeParameters(owner, context).includes(on[0]!) }; + } } memo.set(member.id, found); return found; @@ -3068,6 +3841,21 @@ function isDartGetter(n: Node, context: ResolutionContext): boolean { return getter; } +const DART_SETTERS = new WeakMap>(); + +/** Whether a Dart member is a setter — declared `set (…)`, which no call or read runs. */ +function isDartSetter(n: Node, context: ResolutionContext): boolean { + if (n.language !== 'dart' || n.kind !== 'method') return false; + let memo = DART_SETTERS.get(context); + if (!memo) DART_SETTERS.set(context, (memo = new Map())); + const hit = memo.get(n.id); + if (hit !== undefined) return hit; + const line = (context.getFileLines?.(n.filePath) ?? context.readFile(n.filePath)?.split(/\r?\n/) ?? [])[n.startLine - 1] ?? ''; + const setter = new RegExp(String.raw`^[^={;]*?\bset\s+${n.name.replace(/\$/g, '\\$')}\s*\(`).test(line.slice(n.startColumn)); + memo.set(n.id, setter); + return setter; +} + /** * The Dart member `name` a value of type `typeName` reaches, as Dart finds it: * the nearest one the type or a type it extends, mixes in or implements @@ -3075,7 +3863,8 @@ function isDartGetter(n: Node, context: ResolutionContext): boolean { * only where no instance member answers, and an unnamed one only in its own * library. `accept` narrows the candidates (a read wants a getter). Ties go to * the call site's own file, then the nearest directory — riverpod's translated - * docs carry their own copy of each example's extension. + * docs carry their own copy of each example's extension. `minDepth` 1 skips + * the type's own members, as `super.` does. */ function dartMemberOf( typeName: string, @@ -3083,23 +3872,35 @@ function dartMemberOf( ref: UnresolvedRef, context: ResolutionContext, accept: (n: Node) => boolean, + minDepth = 0, ): { node: Node; viaExtension: boolean } | null { const lineage = dartLineage(typeName, context); + const depthOf = (t: string): number => { + const depth = lineage.get(t); + return depth === undefined || depth < minDepth ? Infinity : depth; + }; let best: Node[] = []; let bestRank = Infinity; + let isProjectType: boolean | undefined; for (const m of context.getNodesByName(name)) { if (m.language !== 'dart' || !isDartMember(m) || !accept(m)) continue; const extension = dartExtensionOwner(m, context); let rank: number; if (extension) { if (!extension.named && m.filePath !== ref.filePath) continue; - const on = Math.min(...extension.on.map((t) => lineage.get(t) ?? Infinity)); + // `extension ObjectX on T` reaches every type, after every extension + // that names one of its lineage — when the type is the project's, so + // what it declares is known: a List's own `cast` is not ObjectX's. + const on = extension.universal + ? (isProjectType ??= context.getNodesByName(typeName).some((n) => n.language === 'dart' && DART_TYPE_KINDS.has(n.kind))) + ? DART_UNIVERSAL_RANK : Infinity + : Math.min(...extension.on.map(depthOf)); if (on === Infinity) continue; rank = DART_EXTENSION_RANK + on; } else { const owner = m.qualifiedName.slice(0, Math.max(0, m.qualifiedName.lastIndexOf('::'))).split('::').pop()!; - const depth = lineage.get(owner); - if (depth === undefined) continue; + const depth = depthOf(owner); + if (depth === Infinity) continue; rank = depth; } if (rank < bestRank) { @@ -3394,12 +4195,19 @@ function receiverNamesOwner(receiver: string, method: Node, context: ResolutionC return sharesReceiverWord(receiver, method); } -/** The Dart `extension` declaration a class node stands for, read from its line: `named` false for `extension on X`. */ +/** + * The Dart `extension` declaration a class node stands for, read from its + * head past the annotations the node starts with (riverpod's `@internal + * extension ContainerReadElement on ProviderContainer`): `named` false for + * `extension on X`. + */ function dartExtensionDecl(n: Node, context: ResolutionContext): { named: boolean } | null { if (n.language !== 'dart' || n.kind !== 'class') return null; - const line = (context.getFileLines?.(n.filePath) ?? context.readFile(n.filePath)?.split(/\r?\n/) ?? [])[n.startLine - 1] ?? ''; - if (!/^\s*extension\b(?!\s+type\b)/.test(line)) return null; - return { named: !/^\s*extension\s+on\b/.test(line) }; + const lines = context.getFileLines?.(n.filePath) ?? context.readFile(n.filePath)?.split(/\r?\n/) ?? []; + const head = lines.slice(n.startLine - 1, Math.min(n.endLine, n.startLine + 5)).join('\n') + .replace(/^\s*(?:(?:@[\w$.]+(?:\s*\((?:[^()]|\([^()]*\))*\))?|\/\/[^\n]*)\s*)*/, ''); + if (!/^extension\b(?!\s+type\b)/.test(head)) return null; + return { named: !/^extension\s+on\b/.test(head) }; } /** Whether a Dart method belongs to an unnamed `extension on X`, visible only in its own library. */ @@ -7579,6 +8387,10 @@ export function clearNameMatcherMemos(context: ResolutionContext): void { DART_LINEAGES.delete(context); DART_EXTENSION_OWNERS.delete(context); DART_GETTERS.delete(context); + DART_SETTERS.delete(context); + DART_CODE.delete(context); + DART_RETURN_TYPES.delete(context); + DART_NAME_USES.delete(context); SWIFT_DECLS.delete(context); KOTLIN_RECEIVER_TYPES.delete(context); KOTLIN_HIERARCHIES.delete(context); From 5a11cd7ab7e6b05dba2ad429a0042074996b300c Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 14:39:26 +0000 Subject: [PATCH 05/23] fix(vbnet): link fields and properties read or written through a value (#2377) VB.NET linked a member read only through a type or module name (#2355), so a read or write through an instance -- a parameter `x.Normal = 3`, a local `h.Normal`, a field `_h.Title`, `Me._h.Normal` -- produced no edge, and `codegraph callers` on an instance field or property listed almost none of its uses. - Extraction (TS only; VB.NET is not kernel-routed): every member read or write is sent with its receiver as a path, whatever the receiver's case: `x.Normal`, `Me._h.Normal`, `MyBase.Count`, `.Value` in a `With` block (nested `With .Inner` included), `.Switch` in an object initializer `New BoolParam With {...}`, and `{T}.X` for a value whose type the code writes (`DirectCast(o, T).X`, `New T().X`). A `With` block's `.Run()` call, which recorded nothing, is sent the same way. The grammar splits `New System.Drawing.Size(...)` into members read through `New System`; those, anonymous types' `New With {.X = 1}`, and paths that start with System, Microsoft or My are not sent. - Resolution (vbnet-receivers.ts): each link of the path is typed by the rules calls use since #2351 -- declarations, casts, `For Each` over a typed collection, call results, type-parameter constraints, Module variables, namespaces and Imports -- and the read links the member the type declares or inherits. A method named without parentheses is called (unless AddressOf or NameOf only names it), and `x.Items(0)`, an index that VB.NET writes as a call, reads `Items`. An outside, `Object`-typed, ambiguous or untyped receiver links nothing; nothing is guessed by name. - "Color Color": a value named like its type (`theme As Theme`) now reads an instance member through the value, so only the member is linked; a Shared member, a Const (read from its declaration) or an Enum case still links the type as well, as #2355 did for every such read. - membersNamed looks a type's members up in its parts' files rather than with one query per member name. The graph is identical on SCrawler; on staxrip, whose AutoCrop tool redeclares `ServerInfo`, 35 reads that main typed through the other project's field, and so left unlinked, now link (70 edges). Verification: vbnet-instance-member-refs.test.ts (11 tests) fails 9/11 on main and passes; one vbnet-shared-member-refs assertion now expects `OtherSession::SessionId` from `Shadowed(appSession As OtherSession)`; the VB.NET suites, tsc and the full suite pass (462 files, 5,859 tests; 22 kernel/platform files skipped). The issue's repro on the built CLI links every read and write, and `codegraph callers` lists `Run` for `SharedCache`, `Normal` and `Title`. Validation, main vs this branch: nodes unchanged, self-loops unchanged. SCrawler 17,437 -> 31,344 edges, 1 removed (same edge, new metadata). staxrip 32,569 -> 71,362 edges, 585 removed: 318 same edge with new metadata (Color Color reads of instance members, qualified-name -> instance-method) and 267 class links of those reads, every one beside an instance member. About 42k added two-link reads were re-derived from the source text by a separate check; its 837 disagreements were all its own blind spots (constraints, Imports aliases, sibling-block locals, call results, staxrip's global `p`). No added edge crosses between staxrip and its AutoCrop tool. Cost (5-run medians): CPU 16.1 -> 19.3 s and 20.2 -> 25.4 s, DB 28.1 -> 43.2 MB and 34.9 -> 59.0 MB; the DB growth is the new edges plus reads through outside types kept as failed refs for re-resolution (#1240). Not covered: unqualified reads, reads through an index or a call result (`list(0).X`), Handles clauses, and calls through a chained receiver written directly (`g.MainForm.Update()`), which still resolve by name. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/vbnet-instance-member-refs.test.ts | 338 +++++++++++++++++++ __tests__/vbnet-shared-member-refs.test.ts | 13 +- src/extraction/tree-sitter.ts | 155 +++++++-- src/resolution/index.ts | 17 +- src/resolution/name-matcher.ts | 2 +- src/resolution/vbnet-receivers.ts | 272 +++++++++++++-- 7 files changed, 729 insertions(+), 69 deletions(-) create mode 100644 __tests__/vbnet-instance-member-refs.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index a25c1a90ae..8fd0b0a6cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In JavaScript and TypeScript, a store whose name contains a `$`, like `const items$ = create(…)` exported on a later line with `export default items$;`, now has its actions indexed. Before, they could be missing from the graph, for example in a file that also had a syntax error. Re-index JavaScript and TypeScript projects after upgrading. - In Dart, what a top-level variable's or a field's initializer calls, creates and reads is now linked. In Riverpod apps, where most wiring lives in provider closures like `final repoProvider = Provider((ref) => Repository(ref.watch(dioProvider)));`, `callers`, impact and `codegraph_explore` now follow a provider to the code it builds instead of stopping at the provider. A `final` or `const` initializer belongs to its constant, and a `var`'s or a field's to its file or class. A call through a type's static constant, like `FutureProvider.autoDispose(…)`, now links to that constant instead of an unrelated method that shares its name. Re-index Dart projects after upgrading. - In Dart, a call further down a chain, like Riverpod's `FutureProvider.autoDispose.family(…)` or `events.map(mapper).transform(…)` on a stream, now links to the method of the type the chain before it produces, worked out from what each step is declared to return, and to nothing when that type can't be worked out. Before, it linked to whichever project method shared its name, so `X.autoDispose.family(…)` reached the same provider builder whatever `X` was, and a stream's `transform` reached an unrelated `transform` method. `super.` calls now reach the superclass's method, `context.read().add(…)` reaches the bloc's own `add`, and the members of an extension marked `@internal` are found too. Re-index Dart projects after upgrading. (#750) +- In VB.NET, reading or setting a field or property through a variable, parameter, field, `Me` or `MyBase`, like `x.Normal = 3`, `Me._h.Title`, `.Value` inside a `With` block or `.Switch` in `New BoolParam With {…}`, now counts as a use of that member, and so do calls inside a `With` block, functions called without parentheses and reads through a class whose name starts in lower case. Before, `codegraph callers` on an instance field or property missed most of its uses. Only a member that the value's declared type has or inherits is linked, nothing when that type comes from outside your project, and a value named after its class, like `theme As Theme`, counts as a use of the class only when it reads a `Shared` member. Re-index VB.NET projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/vbnet-instance-member-refs.test.ts b/__tests__/vbnet-instance-member-refs.test.ts new file mode 100644 index 0000000000..b7199a1604 --- /dev/null +++ b/__tests__/vbnet-instance-member-refs.test.ts @@ -0,0 +1,338 @@ +/** + * VB.NET: a field or property read or written through a value — a parameter + * (`x.Normal = 3`), a local (`h.Normal`), a field (`_h.Title`), `Me._h.Normal`, + * `MyBase.Count`, a `With` block's `.Value`, an object initializer's + * `.Switch` — is a use of the member of the type that value is declared as. + * Before, calls through a typed receiver linked (#2351) and reads through a + * type's name (#2305), but no read through a value, so `codegraph callers` on + * an instance field or property listed almost none of its uses. + * + * The receiver is typed by the rules calls use — its declaration (`As`, `As + * New`, a cast, a `For Each` over a typed collection, a type parameter's + * constraint, a Module variable), the namespaces around the read, what the + * type inherits — and a path (`Me._h.Normal`, `n.Child.Value`) one link at a + * time. An outside type, `Object`, an untyped name or an index links nothing: + * a value's member is never guessed by name. + */ +import { describe, it, expect, afterAll, beforeAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; +import { extractFromSource } from '../src/extraction'; +import { initGrammars, loadGrammarsForLanguages } from '../src/extraction/grammars'; + +let root = ''; +let cg: CodeGraph; + +const files: Record = { + // The issue's two files, verbatim. + 'Holder.vb': `Public Class Holder + Public Shared SharedCache As Integer + Public Normal As Integer + Public Property Title As String + Public Sub EndSession() + End Sub +End Class +`, + 'User.vb': `Public Class User + Private _h As New Holder() + Public Sub Run(x As Holder) + Dim b As Integer = x.SharedCache + Dim n As Integer = x.Normal + x.Normal = 3 + Dim t As String = _h.Title + Me._h.Normal = 4 + Dim h As New Holder() + Dim m As Integer = h.Normal + x.EndSession() + End Sub +End Class +`, + 'Node.vb': `Public Class Node + Public Value As Integer + Public Property Child As Node + Public Items As New List(Of String) + Public Event Changed As EventHandler + Public Sub Reset() + End Sub + Public Function Describe() As String + Return "" + End Function +End Class +`, + // Me, MyBase, a path through members, an inherited member; an index into a + // field, a method named without parentheses, an event, AddressOf. + 'Views.vb': `Public Class BaseView + Protected Caption As String + Public Overridable Property Count As Integer +End Class + +Public Class DerivedView + Inherits BaseView + Private _node As Node + Public Sub New(caption As String) + Me.Caption = caption + End Sub + Public Overrides Property Count As Integer + Get + Return MyBase.Count + Me._node.Child.Value + End Get + Set(value As Integer) + MyBase.Count = value + End Set + End Property + Public Sub Watch(n As Node) + Dim first = n.Items(0) + Dim text = n.Describe + AddHandler n.Changed, AddressOf OnChanged + Dim reset As Action = AddressOf n.Reset + Dim nodes As New List(Of Node) + For Each child In nodes + child.Value = 1 + Next + End Sub + Private Sub OnChanged(sender As Object, e As EventArgs) + End Sub +End Class +`, + // With blocks (nested, through Me, through a cast), an object initializer, a + // cast; an anonymous type declares its own members. + 'Builder.vb': `Public Class Builder + Private _node As New Node() + Property Seed As New Node With {.Value = 7} + Public Sub Fill(o As Object, n As Node) + With n + .Value = 1 + Dim d = .Describe() + With .Child + .Reset() + End With + End With + With Me._node + .Child = Nothing + End With + With DirectCast(o, Node) + .Items.Clear() + End With + Dim v = TryCast(o, Node).Value + Dim anonymous = New With {.Value = 2} + End Sub +End Class +`, + // A Module variable, a type parameter's constraint. + 'Globals.vb': `Public Module Globals + Public Current As Node +End Module +`, + 'Repo.vb': `Public Class Repo(Of T As Node) + Private _item As T + Public Function Peek() As Integer + Return _item.Value + Current.Value + End Function +End Class +`, + // A field's type is the one the namespace around it declares. + 'Sites/Reddit.vb': `Namespace API.Reddit + Friend Class SiteSettings + Friend Property Header As String + End Class + Friend Class UserData + Private _settings As SiteSettings + Friend Function Key() As String + Return _settings.Header + End Function + End Class +End Namespace +`, + 'Sites/Twitter.vb': `Namespace API.Twitter + Friend Class SiteSettings + Friend Property Header As String + End Class +End Namespace +`, + // staxrip's encoder options: a property an initializer sets up, written later. + 'Encoder.vb': `Public MustInherit Class CommandLineParam + Property Switch As String + Property Text As String +End Class + +Public Class BoolParam + Inherits CommandLineParam + Property Value As Boolean +End Class + +Public Class x265Enc + Property ConstVBV As New BoolParam With { + .Switch = "--const-vbv", + .Text = "Enable VBV algorithm to be consistent across runs"} + Sub Apply() + ConstVBV.Value = False + End Sub +End Class +`, + // "Color Color": a value named like its type reads an instance member + // through itself, a Shared member and an Enum case through the type. And + // staxrip names enums in lower case. + 'Theme.vb': `Public Class Theme + Public Shared Current As Theme + Public Const Version As String = "1" + Public Property General As String +End Class + +Public Enum Mode + Fast +End Enum + +Public Enum x265RateMode + Bitrate +End Enum + +Public Class Painter + Public Property Mode As Mode + Public Sub Paint(theme As Theme) + Dim g = theme.General + Dim c = theme.Current + Dim v = theme.Version + Dim f = Mode.Fast + Dim r = x265RateMode.Bitrate + End Sub +End Class +`, + // What links nothing: an outside type, Object, an untyped name, an index's + // element; and a parameter named like a type is read as the parameter. + 'Lookalike.vb': `Public Class Lookalike + Public Length As Integer + Public Count As Integer + Public Value As Integer +End Class +`, + 'Negatives.vb': `Public Class Negatives + Public Sub Go(s As String, o As Object, list As List(Of Node), ByVal untyped) + Dim a = s.Length + Dim b = list.Count + Dim c = o.Value + Dim d = untyped.Value + Dim e = list(0).Value + End Sub + Public Sub Shadowed(holder As Node) + Dim f = Holder.SharedCache + Dim g = holder.Value + End Sub +End Class +`, +}; + +beforeAll(async () => { + await initGrammars(); + await loadGrammarsForLanguages(['vbnet']); + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-vb-instance-')); + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + cg = await CodeGraph.init(root, { index: true }); +}); + +afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true }); +}); + +function nodeId(qualifiedName: string): string { + const found = cg.getNodesInFiles(Object.keys(files)).filter((n) => n.qualifiedName === qualifiedName); + if (found.length !== 1) throw new Error(`${found.length} nodes named ${qualifiedName}`); + return found[0]!.id; +} + +/** The qualified names of what links to `qualifiedName` with an edge of `kind`, one per edge. */ +function linkedFrom(qualifiedName: string, kind: 'references' | 'calls'): string[] { + return cg + .getIncomingEdgesTo([nodeId(qualifiedName)], [kind]) + .map((e) => cg.getNode(e.source)!.qualifiedName) + .sort(); +} + +describe('VB.NET members read and written through a value', () => { + it('link each read and write of the issue to the member', () => { + expect(linkedFrom('Holder::SharedCache', 'references')).toEqual(['User::Run']); + expect(linkedFrom('Holder::Normal', 'references')).toEqual(['User::Run', 'User::Run', 'User::Run', 'User::Run']); + expect(linkedFrom('Holder::Title', 'references')).toEqual(['User::Run']); + expect(linkedFrom('Holder::EndSession', 'calls')).toEqual(['User::Run']); + expect(cg.getCallers(nodeId('Holder::Normal')).map((c) => c.node.qualifiedName)).toEqual(['User::Run']); + }); + + it('link the member alone: the type is not written at the read', () => { + expect(linkedFrom('Holder', 'references')).toEqual([]); + expect(linkedFrom('Node', 'references')).toEqual([]); + }); + + it('read through Me, MyBase and a path of members, one link at a time', () => { + expect(linkedFrom('BaseView::Caption', 'references')).toEqual(['DerivedView::New']); + expect(linkedFrom('BaseView::Count', 'references')).toEqual(['DerivedView::Count', 'DerivedView::Count']); + expect(linkedFrom('DerivedView::_node', 'references')).toEqual(['DerivedView::Count']); + expect(linkedFrom('Node::Child', 'references')).toEqual(['Builder::Fill', 'Builder::Fill', 'DerivedView::Count']); + }); + + it('index a field, run a method named without parentheses, name an event and a method', () => { + expect(linkedFrom('Node::Items', 'references')).toEqual(['Builder::Fill', 'DerivedView::Watch']); + expect(linkedFrom('Node::Describe', 'calls')).toEqual(['Builder::Fill', 'DerivedView::Watch']); + expect(linkedFrom('Node::Changed', 'references')).toEqual(['DerivedView::Watch']); + expect(linkedFrom('Node::Reset', 'references')).toEqual(['DerivedView::Watch']); + expect(linkedFrom('Node::Reset', 'calls')).toEqual(['Builder::Fill']); + }); + + it('read through With blocks, an object initializer, a cast, a loop variable, a Module variable and a type parameter', () => { + expect(linkedFrom('Node::Value', 'references')).toEqual([ + 'Builder::Fill', 'Builder::Fill', 'Builder::Seed', 'DerivedView::Count', 'DerivedView::Watch', + 'Negatives::Shadowed', 'Repo::Peek', 'Repo::Peek', + ]); + }); + + it('read the type the namespace around the declaration sees', () => { + expect(linkedFrom('API.Reddit::SiteSettings::Header', 'references')).toEqual(['API.Reddit::UserData::Key']); + expect(linkedFrom('API.Twitter::SiteSettings::Header', 'references')).toEqual([]); + }); + + it('link an initializer and a later write to the members the type declares or inherits', () => { + expect(linkedFrom('CommandLineParam::Switch', 'references')).toEqual(['x265Enc::ConstVBV']); + expect(linkedFrom('CommandLineParam::Text', 'references')).toEqual(['x265Enc::ConstVBV']); + expect(linkedFrom('BoolParam::Value', 'references')).toEqual(['x265Enc::Apply']); + }); + + it('read an instance member of a value named like its type through the value, a Shared one through the type', () => { + expect(linkedFrom('Theme::General', 'references')).toEqual(['Painter::Paint']); + expect(linkedFrom('Theme::Current', 'references')).toEqual(['Painter::Paint']); + expect(linkedFrom('Theme::Version', 'references')).toEqual(['Painter::Paint']); + // `theme.Current` and the Const `theme.Version`; not `theme.General`. + expect(linkedFrom('Theme', 'references')).toEqual(['Painter::Paint', 'Painter::Paint']); + expect(linkedFrom('Mode::Fast', 'references')).toEqual(['Painter::Paint']); + expect(linkedFrom('Mode', 'references')).toEqual(['Painter::Paint']); + }); + + it('read through a type whose name is in lower case', () => { + expect(linkedFrom('x265RateMode::Bitrate', 'references')).toEqual(['Painter::Paint']); + expect(linkedFrom('x265RateMode', 'references')).toEqual(['Painter::Paint']); + }); + + it('send no read for a qualified type after New, which the grammar splits into members', () => { + // `New System.Windows.Forms.ListBox()` parses as `.Windows.Forms` read through `New System`. + const reads = extractFromSource('Designer.vb', `Public Class Form1 + Sub InitializeComponent() + Me.ListBox1 = New System.Windows.Forms.ListBox() + Dim h = New Sites.Holder + Dim n = New Holder().Normal + Dim p = DirectCast(sender, System.Windows.Forms.Control).Parent + End Sub +End Class +`).unresolvedReferences.filter((r) => r.referenceKind === 'references').map((r) => r.referenceName); + expect(reads).toEqual(['Me.ListBox1', '{Holder}.Normal']); + }); + + it('link nothing through an outside type, Object, an untyped name or an index', () => { + for (const member of ['Lookalike::Length', 'Lookalike::Count', 'Lookalike::Value']) { + expect(linkedFrom(member, 'references')).toEqual([]); + } + expect(linkedFrom('Holder::SharedCache', 'references')).not.toContain('Negatives::Shadowed'); + }); +}); diff --git a/__tests__/vbnet-shared-member-refs.test.ts b/__tests__/vbnet-shared-member-refs.test.ts index bbcfa77ffe..21a5b40fd6 100644 --- a/__tests__/vbnet-shared-member-refs.test.ts +++ b/__tests__/vbnet-shared-member-refs.test.ts @@ -6,9 +6,10 @@ * the class itself, came back empty. * * The name is looked up as VB.NET does, without regard to case: a local, a - * parameter or a field of that name holds a value, and links nothing here (a - * member typed as its own name's type, `Property Settings As Settings`, reads - * that type's members either way); a type is the one the namespaces around + * parameter or a field of that name holds a value, read as the type it is + * declared as (vbnet-instance-member-refs.test.ts; a member typed as its own + * name's type, `Property Settings As Settings`, reads that type's members + * either way); a type is the one the namespaces around * the read, its `Imports` and aliases see — SCrawler declares a * `SiteSettings` in every site's namespace. A method named without * parentheses is called, unless `AddressOf` only names it, and an index into @@ -199,8 +200,10 @@ describe('VB.NET Shared members read through their type (#2305)', () => { expect(linkedFrom('Mode', 'references')).toEqual(['Form1::Setup']); }); - it('link nothing through a local, parameter or field, whatever its case', () => { - expect(linkedFrom('OtherSession::SessionId', 'references')).toEqual([]); + it('read through a local, parameter or field, whatever its case, the type it holds', () => { + // `AppSession.SessionId` in `Shadowed(ByVal appSession As OtherSession)` + // reads the parameter: OtherSession's field, never AppSession's. + expect(linkedFrom('OtherSession::SessionId', 'references')).toEqual(['Form1::Shadowed']); expect(linkedFrom('OtherSession::Size', 'references')).toEqual([]); expect(linkedFrom('Size', 'references')).toEqual([]); expect(linkedFrom('OtherSession', 'references')).toEqual([]); diff --git a/src/extraction/tree-sitter.ts b/src/extraction/tree-sitter.ts index da8dc9bbee..893fd07aab 100644 --- a/src/extraction/tree-sitter.ts +++ b/src/extraction/tree-sitter.ts @@ -381,8 +381,8 @@ const MEMBER_ACCESS_TYPES: ReadonlySet = new Set([ * static read is pure duplication) — while adding real graph noise (+1813 edges / * +2448 `references` on excalidraw, the retrieval-perf benchmark, all pointing at * already-covered types). Don't re-add `member_expression`/`attribute` here. - * VB.NET (#2305) sends the member with its receiver instead, and its resolver - * decides whether the receiver is a type (see extractVbMemberRead). + * VB.NET (#2305) sends every member read with its receiver instead, and its + * resolver decides whether the receiver is a type (see extractVbMemberRead). * Rust imports too, but a variant is usually written through a path that names * its module, not its enum (`mode::Mode::A` under `use crate::mode;`), so no * `use` names the enum at all (#2328). @@ -403,7 +403,8 @@ const RUST_NON_MEMBER_PATH_PARENTS: ReadonlySet = new Set([ /** * VB.NET receivers no project type can be named: the namespace roots * (`System.IO.Path`, `My.Settings`, `Global.X`) and the built-in type keywords - * (`String.Empty`, `Integer.MaxValue`). A read through one is never sent. + * (`String.Empty`, `Integer.MaxValue`). A read through one, or a path that + * starts with one, is never sent. */ const VB_NON_TYPE_RECEIVERS = /^(?:Global|System|Microsoft|My|Boolean|Byte|Char|Date|Decimal|Double|Integer|Long|Object|SByte|Short|Single|String|UInteger|ULong|UShort)$/i; @@ -4531,6 +4532,15 @@ export class TreeSitterExtractor { } } else if (fn.type === 'identifier') { calleeName = getNodeText(fn, this.source); + } else if (fn.type === 'with_member_access_expression') { + // `.Run()` in a `With x` block is `x.Run()`; through a longer path + // (`Me._h`, `{T}` for `With DirectCast(o, T)`) the resolver types each link. + const member = fn.namedChild(0); + const target = this.vbWithTarget(fn); + const receiver = target ? this.vbReceiverPath(target) : null; + if (member?.type !== 'identifier' || !receiver || VB_NON_TYPE_RECEIVERS.test(receiver.split('.')[0]!)) return; + const memberName = getNodeText(member, this.source); + calleeName = /^(?:me|mybase|myclass)$/i.test(receiver) ? memberName : `${receiver}.${memberName}`; } else { return; // parenthesized/chained receivers: no static name to link } @@ -5809,6 +5819,11 @@ export class TreeSitterExtractor { return; } + if (this.language === 'vbnet') { + this.extractVbMemberRead(node, knownParent, ownerId); + return; + } + if (!MEMBER_ACCESS_TYPES.has(node.type)) return; // Skip `Type.method()` — the access is the callee of a call, already linked. @@ -5830,10 +5845,6 @@ export class TreeSitterExtractor { getChildByField(node, 'scope') ?? node.namedChild(0); if (!recv) return; - if (this.language === 'vbnet') { - this.extractVbMemberRead(node, recv, ownerId); - return; - } const t = recv.type; if ( t === 'identifier' || t === 'type_identifier' || t === 'simple_identifier' || @@ -5855,30 +5866,130 @@ export class TreeSitterExtractor { } /** - * VB.NET: a value read or write through a name — `AppSession.SessionId`, - * `AppSession.CurrentUser = "demo"`, `Logger.Level`, `Mode.Fast` — is a use - * of the member as well as of what the name names (#2305). One `references` - * ref carries both, as `Name.Member` (the receiver kept, as a call's is); - * the resolver links the member and the type when the name means a project - * type or module there, and nothing when it holds a value (a local, a - * parameter, a field), which only it can tell in case-insensitive VB.NET - * (see vbnet-receivers' matchVbMemberRead). Its types are Capitalized all - * the same, so a lowercase receiver — a local, nearly always — is skipped. + * VB.NET: a value read or write through a receiver — `AppSession.SessionId`, + * `AppSession.CurrentUser = "demo"`, `x.Normal = 3`, `Me._h.Title`, `.Value` + * in a `With` block, `.Switch` in `New BoolParam With {.Switch = "--x"}` — + * is a use of the member, and through a type name of the type (#2305). One + * `references` ref carries the member with its receiver as a path: + * `x.Normal`, `Me._h.Title`, or `{T}.Switch` for a value whose type the code + * writes (a cast's, a `New`'s). The resolver decides what the receiver is — + * a project type, or a value of the type it is declared as — which only it + * can tell in case-insensitive VB.NET (see vbnet-receivers' + * matchVbMemberRead). A call through the access is the call extractor's. */ - private extractVbMemberRead(node: SyntaxNode, recv: SyntaxNode, ownerId: string): void { - const member = getChildByField(node, 'member'); - if (recv.type !== 'identifier' || member?.type !== 'identifier') return; - const name = getNodeText(recv, this.source); - if (!/^[A-Z]\w*$/.test(name) || VB_NON_TYPE_RECEIVERS.test(name)) return; + private extractVbMemberRead(node: SyntaxNode, knownParent: SyntaxNode | undefined, ownerId: string): void { + let receiver: string | null; + let member: SyntaxNode | null; + if (node.type === 'member_access_expression') { + member = getChildByField(node, 'member'); + const object = getChildByField(node, 'object'); + receiver = object && !this.isVbSplitNew(object) ? this.vbReceiverPath(object) : null; + } else if (node.type === 'with_member_access_expression') { + member = node.namedChild(0); + const target = this.vbWithTarget(node); + receiver = target ? this.vbReceiverPath(target) : null; + } else if (node.type === 'member_initializer') { + member = getChildByField(node, 'name'); + const creation = (knownParent ?? node.parent)?.parent; + receiver = creation?.type === 'object_creation_expression' ? this.vbReceiverPath(creation) : null; + } else return; + if (!receiver || member?.type !== 'identifier' || VB_NON_TYPE_RECEIVERS.test(receiver.split('.')[0]!)) return; + // `x.Method()`: the access is the callee of a call, which the call extractor links. + const parent = node.type === 'member_initializer' ? null : knownParent ?? node.parent; + if (parent && this.extractor!.callTypes.includes(parent.type)) { + const callee = getChildByField(parent, 'function') ?? getChildByField(parent, 'method') ?? parent.namedChild(0); + if (callee && callee.startIndex === node.startIndex) return; + } this.unresolvedReferences.push({ fromNodeId: ownerId, - referenceName: `${name}.${getNodeText(member, this.source)}`, + referenceName: `${receiver}.${getNodeText(member, this.source)}`, referenceKind: 'references', line: node.startPosition.row + 1, column: node.startPosition.column, }); } + /** + * A VB.NET receiver as the resolver reads it: a name, `Me` / `MyClass` / + * `MyBase`, a member of one (`Me._h`, `user.Settings`), a `With` block's + * `.Inner`, or `{T}` for a value whose type the code writes there + * (`DirectCast(o, T)`, `New T(…)`). Null for anything else — an index, a + * call's result, a built-in type — which no declaration here types. + */ + private vbReceiverPath(node: SyntaxNode, depth = 0): string | null { + if (depth > 6) return null; + switch (node.type) { + case 'identifier': + return getNodeText(node, this.source); + case 'me_expression': + return 'Me'; + case 'myclass_expression': + return 'MyClass'; + case 'mybase_expression': + return 'MyBase'; + case 'parenthesized_expression': { + const inner = node.namedChild(0); + return inner ? this.vbReceiverPath(inner, depth + 1) : null; + } + case 'member_access_expression': + case 'with_member_access_expression': { + const through = node.type === 'member_access_expression'; + const member = through ? getChildByField(node, 'member') : node.namedChild(0); + if (member?.type !== 'identifier') return null; + const object = through ? getChildByField(node, 'object') : this.vbWithTarget(node); + if (through && object && this.isVbSplitNew(object)) return null; + const head = object ? this.vbReceiverPath(object, depth + 1) : null; + return head ? `${head}.${getNodeText(member, this.source)}` : null; + } + case 'cast_expression': + case 'object_creation_expression': { + let type = getChildByField(node, 'type'); + // `New T()` parses as an array type whose rank is the constructor's empty parentheses. + if (node.type === 'object_creation_expression' && type?.type === 'array_type') { + const rank = type.namedChildren.find((c: SyntaxNode) => c.type === 'array_rank_specifier'); + type = rank && /^\(\s*\)$/.test(getNodeText(rank, this.source)) ? getChildByField(type, 'element_type') : null; + } + if (!type || type.type === 'predefined_type' || type.type === 'array_type') return null; + const written = getNodeText(type, this.source).replace(/\s+/g, ' '); + // .NET's own types (`System.Drawing.Point`) are never the project's. + return /^(?:System|Microsoft|My)\./i.test(written) ? null : `{${written}}`; + } + default: + return null; + } + } + + /** + * Whether `node`, a member access's object, is `New System` of `New + * System.Drawing.Size(…)` or `New Ns` of `New Ns.Holder`: the grammar reads + * a qualified type after `New` as members read through a `New` of its first + * name. A value's `New` has its parentheses (`New Holder().Normal`). + */ + private isVbSplitNew(node: SyntaxNode): boolean { + return node.type === 'object_creation_expression' && !getChildByField(node, 'arguments') && + !getChildByField(node, 'initializer') && getChildByField(node, 'type')?.type !== 'array_type'; + } + + /** + * What a VB.NET `.Member` is read through: the expression of the `With` + * block it is in (a nested block's own `With .Inner` is read through the + * block around it), or the object an initializer sets up (`New T With {.X = + * 1}`). Null in an anonymous type's `New With {.X = 1}`, which declares X. + */ + private vbWithTarget(node: SyntaxNode): SyntaxNode | null { + let child = node; + for (let p = node.parent; p; child = p, p = p.parent) { + if (p.type === 'with_statement') { + const expression = getChildByField(p, 'expression'); + if (expression && expression.startIndex === child.startIndex && expression.endIndex === child.endIndex) continue; + return expression; + } + if (p.type === 'object_initializer') return p.parent?.type === 'object_creation_expression' ? p.parent : null; + if (p.type === 'anonymous_object_creation_expression') return null; + } + return null; + } + /** * Find a `class_body` child of an `object_creation_expression` — the * marker for an anonymous class (`new T() { ... }`). Returns the body diff --git a/src/resolution/index.ts b/src/resolution/index.ts index 198446483c..0b952a6410 100644 --- a/src/resolution/index.ts +++ b/src/resolution/index.ts @@ -21,11 +21,11 @@ import { isImportableKind, CPP_DEFINE_SIGNATURE, } from './types'; -import { isPythonSelfCall, matchJsStoreBindingCall, isUnresolvedJsMemberCall, matchObjectPathCall, thisScopeCaller, isVisibleAcrossFiles, matchReference, matchFunctionRef, matchDottedCallChain, matchScopedCallChain, matchMethodCall, sameLanguageFamily, crossesCodeBoundary, gateLanguageMatch, dumpNameMatcherProfile, clearNameMatcherMemos, isRustNameInScope, CASE_INSENSITIVE_LANGUAGES, isDartMemberRead, matchDartMemberRead, isDartChainLink, matchDartChainLink } from './name-matcher'; +import { isPythonSelfCall, matchJsStoreBindingCall, isUnresolvedJsMemberCall, matchObjectPathCall, thisScopeCaller, isVisibleAcrossFiles, matchReference, matchFunctionRef, matchDottedCallChain, matchScopedCallChain, matchMethodCall, sameLanguageFamily, crossesCodeBoundary, gateLanguageMatch, dumpNameMatcherProfile, clearNameMatcherMemos, isRustNameInScope, CASE_INSENSITIVE_LANGUAGES, isDartMemberRead, matchDartMemberRead, isDartChainLink, matchDartChainLink, isStdMethodName } from './name-matcher'; import { isVisibleCppMacro, clearCppMacroVisibility } from './cpp-macro-visibility'; import { isCppConstructorRef, matchCppConstructor } from './cpp-constructor'; import { gateSwiftTypeTarget, clearSwiftTypeVisibility, swiftExtendedConformances } from './swift-type-visibility'; -import { clearVbnetReceiverMemos, isVbMemberRead, matchVbMemberRead } from './vbnet-receivers'; +import { clearVbnetReceiverMemos, isVbMemberRead, isVbPathCall, matchVbMemberRead, matchVbPathCall } from './vbnet-receivers'; import { gateTypeParameter, clearTypeParameterMemos } from './type-parameters'; import { resolveViaImport, resolvePhpImportedStaticCall, resolvePhpQualifiedClassRef, resolveJvmImport, extractImportMappings, extractReExports, loadCppIncludeDirs, isPhpIncludePathRef, isCobolCopybookRef, isNixPathImportRef, isJsPathImportRef, isBoundToOutOfRepoImport, clearImportResolverMemos, resolveImportPath, isExternalImport } from './import-resolver'; import { ResolverPool, minRefsForPool, shouldEngageAdaptively } from './resolver-pool'; @@ -1204,11 +1204,16 @@ export class ReferenceResolver { return this.gateLanguage(matchJsStoreBindingCall(ref, this.context), ref); } - // A VB.NET value read through a name (`AppSession.SessionId`, #2305) means - // what VB.NET's scoping says the name is — a project type, whose member - // and the type itself it links, or a value, which links nothing here — and - // no framework, import or name strategy guesses past that. + // A VB.NET member read (`AppSession.SessionId`, #2305; `x.Normal`, + // `Me._h.Title`) means what VB.NET's scoping says its receiver is — a + // project type, whose member and the type itself it links, or a value, + // whose declared type's member it links — and no framework, import or + // name strategy guesses past that. Nor past a `With` block's call through + // a receiver path (`.Run()` in `With Me._h`). if (isVbMemberRead(ref)) return this.gateLanguage(matchVbMemberRead(ref, this.context), ref); + if (isVbPathCall(ref)) { + return this.gateLanguage(matchVbPathCall(ref, this.context, (name) => isStdMethodName('vbnet', name)), ref); + } // Function-as-value refs (#756) get a dedicated, strictly-gated path: // import-based resolution first (an imported callback resolves through its diff --git a/src/resolution/name-matcher.ts b/src/resolution/name-matcher.ts index 1b844ed84a..7569c6c109 100644 --- a/src/resolution/name-matcher.ts +++ b/src/resolution/name-matcher.ts @@ -4163,7 +4163,7 @@ function stdMethodNames(language: string): ReadonlySet | null { } /** Whether `name` is one of `language`'s standard-library method names (VB.NET's in any case). */ -function isStdMethodName(language: string, name: string): boolean { +export function isStdMethodName(language: string, name: string): boolean { return stdMethodNames(language)?.has(language === 'vbnet' ? name.toLowerCase() : name) ?? false; } diff --git a/src/resolution/vbnet-receivers.ts b/src/resolution/vbnet-receivers.ts index f252dfc979..b78704a85a 100644 --- a/src/resolution/vbnet-receivers.ts +++ b/src/resolution/vbnet-receivers.ts @@ -17,7 +17,9 @@ * `Dim x = obj.GetString(…)` returns. A typed receiver's call is the * type's own method or one it inherits, else an extension method declared * for the type, else nothing of the project's: a type the project does - * not define (`SFile`, `String`, `List(Of T)`) has none of its methods. + * not define (`SFile`, `String`, `List(Of T)`) has none of its methods. A + * member read through it (`x.Normal`, `Me._h.Title`, a `With` block's + * `.Value`) is the type's member in the same way, link by link. * 2. Which type a name means where it is written: the namespaces around it, * outward, then its file's and project's `Imports` (aliases included), * then the project a file belongs to — the `.vbproj` above it, whose @@ -437,16 +439,46 @@ function projectTypesNamed(name: string, context: ResolutionContext, kinds: Read return context.getNodesByLowerName(name.toLowerCase()).filter((n) => n.language === 'vbnet' && kinds.has(n.kind)); } +const VB_FILE_QNS = new WeakMap>>(); + +/** A file's VB.NET nodes by lowercased qualified name, indexed once. */ +function nodesByQualifiedName(file: string, context: ResolutionContext): Map { + let memo = VB_FILE_QNS.get(context); + if (!memo) VB_FILE_QNS.set(context, (memo = new Map())); + const hit = memo.get(file); + if (hit) return hit; + const index = new Map(); + for (const n of context.getNodesInFile(file)) { + if (n.language !== 'vbnet') continue; + const key = n.qualifiedName.toLowerCase(); + const list = index.get(key); + if (list) list.push(n); + else index.set(key, [n]); + } + if (memo.size >= 1024) memo.delete(memo.keys().next().value!); + memo.set(file, index); + return index; +} + const VB_MEMBERS = new WeakMap>(); -/** Members named `name` declared directly in `type` (any partial part of it), case aside. */ +/** + * Members named `name` declared directly in `type` (any partial part of it), + * case aside. A member is declared inside a part of its type, so it is looked + * up in those parts' files: one lookup per type name, not one per member name. + */ function membersNamed(type: Node, name: string, context: ResolutionContext): Node[] { let memo = VB_MEMBERS.get(context); if (!memo) VB_MEMBERS.set(context, (memo = new Map())); const qn = `${type.qualifiedName}::${name}`.toLowerCase(); const hit = memo.get(qn); if (hit) return hit; - const members = context.getNodesByLowerName(name.toLowerCase()).filter((n) => n.language === 'vbnet' && n.qualifiedName.toLowerCase() === qn); + const own = type.qualifiedName.toLowerCase(); + const files = new Set([type.filePath]); + for (const part of context.getNodesByLowerName(type.name.toLowerCase())) { + if (part.language === 'vbnet' && part.qualifiedName.toLowerCase() === own) files.add(part.filePath); + } + const members = [...files].flatMap((file) => nodesByQualifiedName(file, context).get(qn) ?? []); if (memo.size >= 65536) memo.delete(memo.keys().next().value!); memo.set(qn, members); return members; @@ -1253,9 +1285,31 @@ export function matchVbTypedCall( const owners = ownersOf(type, context); // A type name that leaves two of the project's types: no guess between them. if (owners === null) return null; + return callOnValue(type, owners, method, ref, context, isStdMethod); +} + +/** + * A call of `method` on a value of type `type` (`owners`, the project type + * it names; none for an outside type): the type's own method or one it + * inherits; an index into its field or property (`x.Items(0)`), which VB.NET + * writes as a call, reads the member; else an extension method for the type. + */ +function callOnValue( + type: VbType, + owners: Node[], + method: string, + ref: UnresolvedRef, + context: ResolutionContext, + isStdMethod: (name: string) => boolean, +): ResolvedRef | null { if (owners.length > 0) { const own = memberOn(owners, method, ref, context, false, type); if (own) return { original: ref, targetNodeId: own.node.id, confidence: 0.9, resolvedBy: 'instance-method' }; + const indexed = memberOn(owners, method, ref, context, true, type); + if (indexed) { + return indexed.node.id === ref.fromNodeId ? null + : { original: ref, targetNodeId: indexed.node.id, confidence: 0.9, resolvedBy: 'instance-method', edgeKind: 'references' }; + } } return extensionFor(type, owners, method, ref, context, isStdMethod); } @@ -1270,30 +1324,129 @@ const VB_READ_TYPE_KINDS: ReadonlySet = new Set([...VB_TYPE_KINDS, 'enum */ const VB_READ_KINDS: ReadonlySet = new Set([...VB_VALUE_KINDS, 'enum_member', 'method', ...VB_TYPE_LIKE_KINDS]); -/** `Name.Member`, as the extractor sends a VB.NET value read through a name (extractVbMemberRead). */ -const VB_MEMBER_READ = /^([A-Za-z_]\w*)\.(\[?[A-Za-z_]\w*\]?)$/; +/** What a read through a value names: a field, property, constant or event of its type, or a method it runs. */ +const VB_INSTANCE_READ_KINDS: ReadonlySet = new Set([...VB_VALUE_KINDS, 'method']); + +/** Members that belong to a type, not an instance, besides those declared `Shared`: a constant, an `Enum` case, a nested type. */ +const VB_SHARED_READ_KINDS: ReadonlySet = new Set(['constant', 'enum_member', ...VB_TYPE_LIKE_KINDS]); + +/** + * Whether a member belongs to its type rather than to an instance: `Shared`, + * an `Enum` case, a nested type, or a `Const` — Shared without saying so, + * which a VB.NET field's node doesn't record, so its declaration is read. + */ +function isSharedMember(n: Node, context: ResolutionContext): boolean { + if (n.isStatic || VB_SHARED_READ_KINDS.has(n.kind)) return true; + if (n.kind !== 'field') return false; + const code = codeLines(n.filePath, context).slice(n.startLine - 1, n.startLine + 2).join(' '); + return new RegExp(`\\bConst\\s+(?:[^=]*,\\s*)?${escapeRegex(n.name)}(?![\\w$%&!#@])`, 'i').test(code); +} -/** Whether a reference is a VB.NET value read through a name, which matchVbMemberRead alone resolves. */ +/** + * A member read (or a `With` block's call) as the extractor sends it + * (extractVbMemberRead): the receiver — a name, `Me` / `MyClass` / `MyBase`, + * or `{T}` for a value of a type the code writes — then each member read + * through it, the last the one used: `AppSession.SessionId`, `x.Normal`, + * `Me._h.Title`, `{BoolParam}.Switch`. + */ +const VB_MEMBER_PATH = /^(\{[^{}]+\}|\[?[A-Za-z_]\w*\]?)((?:\.\[?[A-Za-z_]\w*\]?)*)\.(\[?[A-Za-z_]\w*\]?)$/; + +/** Whether a reference is a VB.NET member read through a receiver, which matchVbMemberRead alone resolves. */ export function isVbMemberRead(ref: UnresolvedRef): boolean { - return ref.language === 'vbnet' && ref.referenceKind === 'references' && VB_MEMBER_READ.test(ref.referenceName); + return ref.language === 'vbnet' && ref.referenceKind === 'references' && VB_MEMBER_PATH.test(ref.referenceName); } /** - * The project types `name` means where a value is read through it - * (`AppSession` in `AppSession.SessionId`): a class, module, structure, - * interface or enum. Null when the name holds a value there — a local, a - * parameter, a member of a type around the read or of a module — or names - * no project type, or two. A member typed as the type of its own name - * (`Public Property Settings As Settings`) reaches that type's members - * either way, as VB.NET's "Color Color" rule has it. + * Whether a reference is a VB.NET call through a receiver path, which only a + * `With` block sends (`.Run()` in `With Me._h`, `With DirectCast(o, T)`) and + * matchVbPathCall alone resolves. A call through a name (`x.Run`) is the + * name matcher's, which types it with matchVbTypedCall. */ -function typesReadThrough(name: string, ref: UnresolvedRef, context: ResolutionContext): Node[] | null { +export function isVbPathCall(ref: UnresolvedRef): boolean { + if (ref.language !== 'vbnet' || ref.referenceKind !== 'calls') return false; + const m = VB_MEMBER_PATH.exec(ref.referenceName); + return m !== null && (m[2] !== '' || m[1]!.startsWith('{') || /^(?:Me|MyClass|MyBase)$/i.test(m[1]!)); +} + +/** What a receiver path reaches: the project type whose members are read through it, and how. */ +interface VbReceiver { + /** The parts of the project type the receiver names or holds a value of; none for an outside type. */ + owners: Node[]; + /** The type a value is declared as, with the type arguments it gives; absent through a type's name. */ + typed?: VbType; + /** The receiver names a type (`AppSession`, `Outer.Mode`), whose own members are read, not a value. */ + throughType: boolean; + /** The name is a value whose type has the same name (`theme As Theme`): VB.NET's "Color Color" rule. */ + colorColor?: boolean; +} + +/** `Name` for an escaped `[Name]`. */ +function unescaped(name: string): string { + return name.replace(/^\[(.*)\]$/, '$1'); +} + +/** A receiver holding a value of type `t`; null when that type isn't known, is `Object` (late-bound), or names two types. */ +function valueReceiver(t: VbType | null | undefined, context: ResolutionContext): VbReceiver | null { + if (!t || typeKey(t) === 'object') return null; + const owners = ownersOf(t, context); + return owners ? { owners, typed: t, throughType: false } : null; +} + +/** + * What a receiver path's first link is where a member is read through it: + * `Me` / `MyClass` the type around the read, `MyBase` the class that type + * inherits, `{T}` a value of `T`. A name holds a value of its declared type + * when it is a local, a parameter, or a member of a type around the read or + * of a Module; any other name means the class, module, structure, interface + * or enum it names there. A value whose type has its name (`Public Property + * Settings As Settings`, `theme As Theme`) may mean either, by VB.NET's + * "Color Color" rule: the member read through it decides (matchVbMemberRead). + */ +function receiverAt(head: string, ref: UnresolvedRef, context: ResolutionContext): VbReceiver | null { + if (head.startsWith('{')) { + const owner = context.getNodeById?.(ref.fromNodeId) ?? null; + return valueReceiver(resolveTypeParameter(sited(readType(head.slice(1, -1), 0), ref.filePath, ref.line), owner, context), context); + } + if (/^(?:Me|MyClass|MyBase)$/i.test(head)) { + const own = typesAround(ref.filePath, ref.line, context)[0]; + if (!own) return null; + if (/^MyBase$/i.test(head)) return valueReceiver(supertypesOf(own, context).find((s) => !s.implemented), context); + return { owners: [own], typed: { name: own.name, array: false }, throughType: false }; + } + const name = unescaped(head); const bound = receiverType(name, ref, context, 0); const written: VbType | null = bound === undefined ? { name, array: false, file: ref.filePath, line: ref.line } : bound && !bound.array && bound.name.toLowerCase() === name.toLowerCase() ? bound : null; - if (!written) return null; + if (!written) return valueReceiver(bound, context); const found = typesNamedAt(written, context, VB_READ_TYPE_KINDS); - return found.ambiguous || found.owners.length === 0 ? null : found.owners; + return found.ambiguous || found.owners.length === 0 ? null + : { owners: found.owners, throughType: true, ...(bound ? { colorColor: true } : {}) }; +} + +/** + * What `name`, read through `at`, is as a receiver in turn: a value of the + * type a field, property or function declares, or a type nested in a type + * named for it (`Outer.Mode`). Null where the member, or its type, is not + * known here. + */ +function memberAt(at: VbReceiver, name: string, ref: UnresolvedRef, context: ResolutionContext): VbReceiver | null { + if (at.owners.length === 0) return null; + const fits = (n: Node) => VB_INSTANCE_READ_KINDS.has(n.kind) || (at.throughType && VB_READ_TYPE_KINDS.has(n.kind)); + const found = memberOn(at.owners, name, ref, context, true, at.typed, fits) ?? + memberOn(at.owners, `[${name}]`, ref, context, true, at.typed, fits); + if (!found) return null; + if (VB_READ_TYPE_KINDS.has(found.node.kind)) return { owners: [found.node], throughType: true }; + return valueReceiver(valueMemberType(found.node, context, found.args), context); +} + +/** What the receiver path `head.links…` reaches (see receiverAt and memberAt), or null where a link has no type here. */ +function pathReceiver(head: string, links: string[], ref: UnresolvedRef, context: ResolutionContext): VbReceiver | null { + let at = receiverAt(head, ref, context); + for (const link of links) { + if (!at) return null; + at = memberAt(at, unescaped(link), ref, context); + } + return at; } /** @@ -1330,43 +1483,92 @@ function namesWithoutRunning(ref: UnresolvedRef, context: ResolutionContext): bo } /** - * Resolve a VB.NET value read or write through a name (#2305) — - * `AppSession.SessionId`, `AppSession.CurrentUser = "demo"`, `Logger.Level`, - * `Mode.Fast` — to the member that the type the name means declares or - * inherits, and to the type. A method named this way is called (no type is - * linked, as for a call written with parentheses), unless `AddressOf` or - * `NameOf` only names it. Null when the name holds a value there (an - * instance's members are not read through its type), names no project type, - * or names one without that member: `Color.Red` is not a project `Color`'s. + * Resolve a VB.NET member read or write to the member the receiver's type + * declares or inherits. Through a type's name (#2305) — `AppSession.SessionId`, + * `AppSession.CurrentUser = "demo"`, `Logger.Level`, `Mode.Fast` — the read + * links the type as well, and a `Shared` member before a same-named instance + * one. Through a value — `x.Normal = 3` on a parameter `x As Holder`, + * `Me._h.Title`, a `With` block's `.Value`, an initializer's `.Switch` — it + * links the member of the type the value is declared as, whatever that + * type's name; never a member of the type the receiver's own name would + * mean. A value named like its type (`theme As Theme`) reads an instance + * member as a value does and a Shared one as the type does, by VB.NET's + * "Color Color" rule. A method named either way is called, as without + * parentheses VB.NET runs it, unless `AddressOf` or `NameOf` only names it. + * Null when a link of the path is not typed here (an outside type: + * `Color.Red`, `str.Length`), is late-bound (`Object`), or names two of the + * project's types. */ export function matchVbMemberRead(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null { - const m = VB_MEMBER_READ.exec(ref.referenceName); + const m = VB_MEMBER_PATH.exec(ref.referenceName); if (!m) return null; - const owners = typesReadThrough(m[1]!, ref, context); - if (!owners) return null; + const links = m[2] ? m[2].slice(1).split('.') : []; + const at = pathReceiver(m[1]!, links, ref, context); + if (!at || at.owners.length === 0) return null; + // `MySettings.Default` reads the property declared `[Default]`, and back. + const name = unescaped(m[3]!); + const calls = (member: Node) => member.kind === 'method' && !namesWithoutRunning(ref, context); + const throughValue = (member: Node): ResolvedRef => ({ + original: ref, + targetNodeId: member.id, + confidence: 0.9, + resolvedBy: 'instance-method', + ...(calls(member) ? { edgeKind: 'calls' as const } : {}), + }); + if (!at.throughType) { + // The member the name means: the nearest the type declares or inherits. + // The read's own member (`Return Me.Count` in `Count`) runs itself. + const fits = (n: Node) => VB_INSTANCE_READ_KINDS.has(n.kind); + const member = (memberOn(at.owners, name, ref, context, true, at.typed, fits) ?? + memberOn(at.owners, `[${name}]`, ref, context, true, at.typed, fits))?.node; + return member && member.id !== ref.fromNodeId ? throughValue(member) : null; + } // Not the member the read is written in: staxrip's `Overrides ReadOnly // Property Package` returns the class's `Shared ReadOnly Property Package`. const fits = (n: Node) => VB_READ_KINDS.has(n.kind) && n.id !== ref.fromNodeId; - // `MySettings.Default` reads the property declared `[Default]`, and back. - const name = m[2]!.replace(/^\[(.*)\]$/, '$1'); - let member = (memberOn(owners, name, ref, context, true, undefined, fits) ?? - memberOn(owners, `[${name}]`, ref, context, true, undefined, fits))?.node; + let member = (memberOn(at.owners, name, ref, context, true, undefined, fits) ?? + memberOn(at.owners, `[${name}]`, ref, context, true, undefined, fits))?.node; if (!member) return null; // Of a `Shared` member and an instance one of the same name, a type's name reads the `Shared` one. if (!member.isStatic) { const found = member; member = context.getNodesByQualifiedName(found.qualifiedName).find((n) => n.isStatic && n.filePath === found.filePath && fits(n)) ?? found; } + // "Color Color": a value named like its type (`theme As Theme`) reads an + // instance member through itself, and only a Shared one through the type. + if (at.colorColor && !isSharedMember(member, context)) return throughValue(member); if (member.kind === 'method') { return { original: ref, targetNodeId: member.id, confidence: 0.85, resolvedBy: 'qualified-name', - ...(namesWithoutRunning(ref, context) ? {} : { edgeKind: 'calls' as const }), + ...(calls(member) ? { edgeKind: 'calls' as const } : {}), }; } - return readThrough(member, owners, ref, context, { confidence: 0.9 }); + // A type named through another (`Outer.Mode.Fast`) is linked by the read + // that names it (`Outer.Mode`), so only a type named itself is linked here. + return links.length === 0 ? readThrough(member, at.owners, ref, context, { confidence: 0.9 }) + : { original: ref, targetNodeId: member.id, confidence: 0.9, resolvedBy: 'qualified-name' }; +} + +/** + * Resolve a VB.NET call through a receiver path, which a `With` block sends + * for its `.Run()` (`With Me._h`, `With user.Settings`, `With + * DirectCast(o, T)`), as matchVbTypedCall resolves one through a typed name: + * the method the path's type has or inherits, a read of a field or property + * it indexes, or an extension method for the type. Null — never a guess by + * the method's name — when a link of the path is not typed here. + */ +export function matchVbPathCall( + ref: UnresolvedRef, + context: ResolutionContext, + isStdMethod: (name: string) => boolean, +): ResolvedRef | null { + const m = VB_MEMBER_PATH.exec(ref.referenceName); + if (!m) return null; + const at = pathReceiver(m[1]!, m[2] ? m[2].slice(1).split('.') : [], ref, context); + return at?.typed && !at.throughType ? callOnValue(at.typed, at.owners, unescaped(m[3]!), ref, context, isStdMethod) : null; } const VB_TYPE_IMPORTS = new WeakMap>>(); @@ -1445,7 +1647,7 @@ export function isVbMemberInScope(n: Node, ref: UnresolvedRef, context: Resoluti * sync never reads a changed file's old declarations. */ export function clearVbnetReceiverMemos(context: ResolutionContext): void { - for (const memo of [VB_CODE_LINES, VB_WORD_LINES, VB_BINDINGS, VB_FILE_TYPES, VB_MEMBERS, VB_MODULES, VB_SUPERS, VB_ANCESTRIES, + for (const memo of [VB_CODE_LINES, VB_WORD_LINES, VB_BINDINGS, VB_FILE_TYPES, VB_FILE_QNS, VB_MEMBERS, VB_MODULES, VB_SUPERS, VB_ANCESTRIES, VB_PROJECTS, VB_PROJECT_INFO, VB_FILE_IMPORTS, VB_ALIASES, VB_BASE_NAMES, VB_TYPE_PARAMS, VB_EXTENSIONS, VB_TYPE_IMPORTS, VB_SCOPES] as Array>) { memo.delete(context); From 05712869072d23ec71d23e2801bb68c1778e63d8 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 14:41:06 +0000 Subject: [PATCH 06/23] fix(js,ts): link calls through an import whose name contains $ (#2378) The ES import regex in extractJSImports captured default and namespace bindings with \w+, which stops at a `$`. So `import items$ from './store'`, `import $ from './dom'` and `import * as ns$ from './ns'` failed the whole statement and produced no import mapping, and `items$.getState().inc()` never reached the store action. The `as` split of named imports, the `a: b` split of a CommonJS destructuring and the re-export checks had the same \w-only shape. Some bound a cut-off name instead (`{ a as b$ }` bound `b`, `{ default as items$ }` bound `items`), and `export { a$ } from` was dropped from barrel chasing. Capture every binding with the ASCII identifier class [A-Za-z_$][\w$]*, keeping the `type`-modifier lookahead: `import type from './x'` still binds `type`, and `import type $T` / `import type from$` now bind. A default binding is never followed by `{`, so the `${` of a code generator's template literal (`import ${x} from '${src}'`, as in qwik's optimizer) is not taken for a binding. importShadowedAt and hasParameterBinding bounded the name with \b, which never fires beside a `$`, so a local `const items$ = ...` or an `items$` parameter did not shadow the imported store. Named `$` imports already got those wrong edges on main, and the mapping fix would have extended them to default and namespace imports. Bound the name with (? --- CHANGELOG.md | 1 + __tests__/import-type-modifier.test.ts | 90 +++++++++++++++++++++++++- src/resolution/import-resolver.ts | 16 +++-- src/resolution/name-matcher.ts | 7 +- 4 files changed, 104 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fd0b0a6cc..3055b1a6e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In Dart, what a top-level variable's or a field's initializer calls, creates and reads is now linked. In Riverpod apps, where most wiring lives in provider closures like `final repoProvider = Provider((ref) => Repository(ref.watch(dioProvider)));`, `callers`, impact and `codegraph_explore` now follow a provider to the code it builds instead of stopping at the provider. A `final` or `const` initializer belongs to its constant, and a `var`'s or a field's to its file or class. A call through a type's static constant, like `FutureProvider.autoDispose(…)`, now links to that constant instead of an unrelated method that shares its name. Re-index Dart projects after upgrading. - In Dart, a call further down a chain, like Riverpod's `FutureProvider.autoDispose.family(…)` or `events.map(mapper).transform(…)` on a stream, now links to the method of the type the chain before it produces, worked out from what each step is declared to return, and to nothing when that type can't be worked out. Before, it linked to whichever project method shared its name, so `X.autoDispose.family(…)` reached the same provider builder whatever `X` was, and a stream's `transform` reached an unrelated `transform` method. `super.` calls now reach the superclass's method, `context.read().add(…)` reaches the bloc's own `add`, and the members of an extension marked `@internal` are found too. Re-index Dart projects after upgrading. (#750) - In VB.NET, reading or setting a field or property through a variable, parameter, field, `Me` or `MyBase`, like `x.Normal = 3`, `Me._h.Title`, `.Value` inside a `With` block or `.Switch` in `New BoolParam With {…}`, now counts as a use of that member, and so do calls inside a `With` block, functions called without parentheses and reads through a class whose name starts in lower case. Before, `codegraph callers` on an instance field or property missed most of its uses. Only a member that the value's declared type has or inherits is linked, nothing when that type comes from outside your project, and a value named after its class, like `theme As Theme`, counts as a use of the class only when it reads a `Shared` member. Re-index VB.NET projects after upgrading. +- In JavaScript and TypeScript, an import whose name contains a `$`, like `import items$ from './store'`, `import * as api$ from './api'` or `import { load as load$ } from './data'`, now links the calls made through it, such as `items$.getState().inc()`, to the code it imports, and so does a `$` name in a `require(…)` destructuring or an `export { … } from` barrel. Before, such an import was skipped or bound under a cut-off name (`load` for `load$`), so those calls reached nothing and the functions they call could look unused. A local variable or parameter that reuses an imported `$` name, like `const items$ = …` inside a function, is no longer mistaken for the import. Re-index JavaScript and TypeScript projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/import-type-modifier.test.ts b/__tests__/import-type-modifier.test.ts index a74b430703..16b5c895bc 100644 --- a/__tests__/import-type-modifier.test.ts +++ b/__tests__/import-type-modifier.test.ts @@ -6,13 +6,17 @@ * `type.innerType()` (a parameter named `type`) was taken for a call on an * import. An inline `{ util, type objectUtil }` named its binding * `type objectUtil`. + * + * A binding is any JS identifier, `$` included. The import regexes matched + * names with `\w`, which stops at a `$`: `import items$ from './store'` and + * `import * as ns$` yielded no binding at all, and `{ a as b$ }` bound `b`. */ import { describe, it, expect, afterAll } from 'vitest'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; import { CodeGraph } from '../src'; -import { extractImportMappings } from '../src/resolution/import-resolver'; +import { extractImportMappings, extractReExports } from '../src/resolution/import-resolver'; const bindings = (source: string) => extractImportMappings('src/a.ts', source, 'typescript').map((m) => `${m.localName}<${m.exportedName}${m.isNamespace ? ' ns' : ''}`); @@ -34,6 +38,90 @@ describe('import mappings and TypeScript type modifiers', () => { }); }); +describe('import bindings whose names contain `$`', () => { + it('default, namespace and mixed imports bind the whole name', () => { + expect(bindings(`import items$ from './store';\n`)).toEqual(['items$ { + expect(bindings(`import { a$ as b$, a as $b, default as items$ } from './ab';\n`)).toEqual(['b$ { + expect(bindings("const code = `import ${name} from '${src}'`;\n")).toEqual([]); + expect(bindings("const code = `import type ${name} from '${src}'`;\n")).toEqual([]); + }); + + it('a CommonJS destructuring binds the whole name', () => { + expect(bindings(`const { a$: b$, a: $c, d$ } = require('./r');\n`)).toEqual(['b$ { + expect(extractReExports(`export { a$, $b as c$, default as $store } from './x';\n`, 'typescript')).toEqual([ + { kind: 'named', exportedName: 'a$', originalName: 'a$', source: './x' }, + { kind: 'named', exportedName: 'c$', originalName: '$b', source: './x' }, + { kind: 'named', exportedName: '$store', originalName: 'default', source: './x' }, + ]); + }); +}); + +describe('a `$` binding imported from another file', () => { + const roots: string[] = []; + afterAll(() => { + for (const r of roots.splice(0)) fs.rmSync(r, { recursive: true, force: true }); + }); + + it('`items$.getState().inc()` reaches the store action unless a local or parameter shadows `items$`', async () => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-import-dollar-')); + roots.push(root); + const files: Record = { + 'package.json': JSON.stringify({ name: 'shop', dependencies: { zustand: '*' } }), + 'src/store.ts': `import { create } from 'zustand'; + +const items$ = create((set) => ({ inc: () => set({}) })); +export default items$; +`, + 'src/util.ts': `export function helper() { return 1; } +`, + 'src/decoy.ts': `export function helper() { return 2; } +`, + 'src/use.ts': `import items$ from './store'; +import * as util$ from './util'; + +export function clickInc() { items$.getState().inc(); } +export function shadowed() { const items$ = other(); items$.getState().inc(); } +export function param(items$: Store) { items$.getState().inc(); } +export function run() { return util$.helper(); } +`, + }; + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + const cg = await CodeGraph.init(root, { index: true }); + try { + const callers = (file: string, name: string) => { + const target = cg.getNodesInFile(file).find((n) => n.kind === 'function' && n.name === name); + expect(target, `${file}: ${name}`).toBeDefined(); + return cg.getCallers(target!.id).filter((c) => c.edge.kind === 'calls').map((c) => c.node.name).sort(); + }; + expect(callers('src/store.ts', 'inc')).toEqual(['clickInc']); + expect(callers('src/util.ts', 'helper')).toEqual(['run']); + expect(callers('src/decoy.ts', 'helper')).toEqual([]); + } finally { + cg.close(); + } + }); +}); + describe('a name imported from a package names nothing in the project', () => { const roots: string[] = []; afterAll(() => { diff --git a/src/resolution/import-resolver.ts b/src/resolution/import-resolver.ts index 30bd4137b6..07236bfc92 100644 --- a/src/resolution/import-resolver.ts +++ b/src/resolution/import-resolver.ts @@ -964,7 +964,11 @@ function extractJSImports(content: string): ImportMapping[] { // type-only form, not a default import named `type` — which every such // line used to add, making `type.innerType()` a call on an import. // (`import type from './x'` still binds `type`: backtracking gives it back.) - const importRegex = /import\s+(?:type\s+(?=[{*]|(?!from\b)\w))?(?:(\w+)\s*,?\s*)?(?:\{([^}]+)\})?\s*(?:(\*)\s+as\s+(\w+))?\s*from\s*['"]([^'"]+)['"]/g; + // A binding is any JS identifier, `$` included: `\w` stops at the `$` of + // `import $store from './store'`, failing the whole statement. A default + // binding is never followed by `{`, so the `${` of a code generator's + // `` `import ${name} from '${src}'` `` is no binding. + const importRegex = /import\s+(?:type\s+(?=[{*]|(?!from(?![\w$]))[A-Za-z_$]))?(?:([A-Za-z_$][\w$]*)(?![\w${])\s*,?\s*)?(?:\{([^}]+)\})?\s*(?:(\*)\s+as\s+([A-Za-z_$][\w$]*))?\s*from\s*['"]([^'"]+)['"]/g; let match; while ((match = importRegex.exec(content)) !== null) { @@ -984,9 +988,9 @@ function extractJSImports(content: string): ImportMapping[] { // Named imports if (namedImports) { // `{ util, type objectUtil }`: an inline `type` modifier is not part of the name. - const names = namedImports.split(',').map((s) => s.trim().replace(/^type\s+(?=\w)/, '')); + const names = namedImports.split(',').map((s) => s.trim().replace(/^type\s+(?=[A-Za-z_$])/, '')); for (const name of names) { - const aliasMatch = name.match(/(\w+)\s+as\s+(\w+)/); + const aliasMatch = name.match(/([A-Za-z_$][\w$]*)\s+as\s+([A-Za-z_$][\w$]*)/); if (aliasMatch) { mappings.push({ localName: aliasMatch[2]!, @@ -1038,7 +1042,7 @@ function extractJSImports(content: string): ImportMapping[] { if (destructured) { const names = destructured.split(',').map((s) => s.trim()); for (const name of names) { - const aliasMatch = name.match(/(\w+)\s*:\s*(\w+)/); + const aliasMatch = name.match(/([A-Za-z_$][\w$]*)\s*:\s*([A-Za-z_$][\w$]*)/); if (aliasMatch) { mappings.push({ localName: aliasMatch[2]!, @@ -1373,7 +1377,7 @@ export function extractReExports(content: string, language: Language): ReExport[ for (const raw of inner.split(',')) { const item = raw.trim(); if (!item) continue; - const aliasMatch = item.match(/^(\w+)\s+as\s+(\w+)$/); + const aliasMatch = item.match(/^([A-Za-z_$][\w$]*)\s+as\s+([A-Za-z_$][\w$]*)$/); if (aliasMatch) { out.push({ kind: 'named', @@ -1381,7 +1385,7 @@ export function extractReExports(content: string, language: Language): ReExport[ originalName: aliasMatch[1]!, source, }); - } else if (/^\w+$/.test(item)) { + } else if (/^[A-Za-z_$][\w$]*$/.test(item)) { out.push({ kind: 'named', exportedName: item, diff --git a/src/resolution/name-matcher.ts b/src/resolution/name-matcher.ts index 7569c6c109..b4c13838a6 100644 --- a/src/resolution/name-matcher.ts +++ b/src/resolution/name-matcher.ts @@ -11171,7 +11171,8 @@ function importShadowedAt(name: string, ref: UnresolvedRef, context: ResolutionC return stack; }; const scope = stackAt(code.length); - const declarations = new RegExp(`\\b(?:const|let|var|function|class)\\s+(?:${escaped}\\b|\\{[^}]*\\b${escaped}\\b)`, 'g'); + // Not `\b`: there is no word boundary beside the `$` of `items$` or `$store`. + const declarations = new RegExp(`\\b(?:const|let|var|function|class)\\s+(?:${escaped}(?![\\w$])|\\{[^}]*(? stackAt(m.index!).every((p, i) => scope[i] === p)); } @@ -11179,8 +11180,8 @@ function importShadowedAt(name: string, ref: UnresolvedRef, context: ResolutionC * parentheses must not make the outer shadow invisible. Conservative when a * parameter's type mentions the same name: leave that call unresolved. */ function hasParameterBinding(code: string, escapedName: string): boolean { - const name = new RegExp(`\\b${escapedName}\\b`); - if (new RegExp(`\\b${escapedName}\\s*=>`).test(code)) return true; + const name = new RegExp(`(?`).test(code)) return true; for (let i = 0; i < code.length; i++) { if (code[i] !== '(' || /\b(?:if|while|for|switch|with)\s*$/.test(code.slice(0, i))) continue; let depth = 1, j = i + 1; From 4d6168a701f1710a9059bdaf544f65bca8ae7957 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 14:45:17 +0000 Subject: [PATCH 07/23] fix(dart): a bare call to a parameter or local links nothing (#2379) A receiver-less Dart call, or a function passed by name, whose name a parameter, local, loop or catch variable, or pattern variable around it binds now links nothing, instead of a same-named top-level symbol in another file or a member the class inherits; a local function declared there still links. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/dart-local-call-scope.test.ts | 248 +++++++++ src/resolution/dart-local-scope.ts | 666 ++++++++++++++++++++++++ src/resolution/index.ts | 13 +- 4 files changed, 925 insertions(+), 3 deletions(-) create mode 100644 __tests__/dart-local-call-scope.test.ts create mode 100644 src/resolution/dart-local-scope.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 3055b1a6e3..49ffc639ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In Dart, a call further down a chain, like Riverpod's `FutureProvider.autoDispose.family(…)` or `events.map(mapper).transform(…)` on a stream, now links to the method of the type the chain before it produces, worked out from what each step is declared to return, and to nothing when that type can't be worked out. Before, it linked to whichever project method shared its name, so `X.autoDispose.family(…)` reached the same provider builder whatever `X` was, and a stream's `transform` reached an unrelated `transform` method. `super.` calls now reach the superclass's method, `context.read().add(…)` reaches the bloc's own `add`, and the members of an extension marked `@internal` are found too. Re-index Dart projects after upgrading. (#750) - In VB.NET, reading or setting a field or property through a variable, parameter, field, `Me` or `MyBase`, like `x.Normal = 3`, `Me._h.Title`, `.Value` inside a `With` block or `.Switch` in `New BoolParam With {…}`, now counts as a use of that member, and so do calls inside a `With` block, functions called without parentheses and reads through a class whose name starts in lower case. Before, `codegraph callers` on an instance field or property missed most of its uses. Only a member that the value's declared type has or inherits is linked, nothing when that type comes from outside your project, and a value named after its class, like `theme As Theme`, counts as a use of the class only when it reads a `Shared` member. Re-index VB.NET projects after upgrading. - In JavaScript and TypeScript, an import whose name contains a `$`, like `import items$ from './store'`, `import * as api$ from './api'` or `import { load as load$ } from './data'`, now links the calls made through it, such as `items$.getState().inc()`, to the code it imports, and so does a `$` name in a `require(…)` destructuring or an `export { … } from` barrel. Before, such an import was skipped or bound under a cut-off name (`load` for `load$`), so those calls reached nothing and the functions they call could look unused. A local variable or parameter that reuses an imported `$` name, like `const items$ = …` inside a function, is no longer mistaken for the import. Re-index JavaScript and TypeScript projects after upgrading. +- In Dart, calling a parameter or a local variable, like `create(ref, arg)` inside `overrideWith(… create)`, a closure's parameter, a loop variable or a test's mock `listener(0, 1)`, no longer links the call to an unrelated function or constant of the same name in another file, or to a method the class inherits: a Bloc event handler's `emit(…)` is the handler's own `emit` parameter, not `Bloc.emit`. So `codegraph callers` and impact no longer list code that never calls them, while calls the parameter or variable doesn't cover, and calls to a local function, link as before. Re-index Dart projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/dart-local-call-scope.test.ts b/__tests__/dart-local-call-scope.test.ts new file mode 100644 index 0000000000..7dec2813ef --- /dev/null +++ b/__tests__/dart-local-call-scope.test.ts @@ -0,0 +1,248 @@ +/** + * A bare Dart call to a name a parameter or local around it binds calls that + * parameter or local — never a same-named symbol elsewhere. + * + * riverpod's `overrideWith(CreatedT Function(Ref ref, ArgT arg) create)` calls + * its parameter (`create(ref, arg)`), as do its tests' provider factories and + * an analyzer cache's `upsert(key, create)`. All of them were linked to a docs + * example's top-level `final create = Mutation<…>()` that none of them import. + * Tests' mocks (`final listener = Listener(); listener(0, 1)`) went to + * other test files' `listener` functions, and bloc's event handlers' `emit` + * parameter (`on((event, emit) => emit(…))`) to `Bloc.emit`, which a + * handler never calls. None of those bindings is a node, so such a call links + * nothing. A call the binding does not cover still links. + * + * Runs against the native kernel (when built) and the wasm extractor, which + * must agree. + */ +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; +import type { Node } from '../src/types'; + +const FILES: Record = { + 'pubspec.yaml': 'name: app\nenvironment:\n sdk: ">=3.0.0 <4.0.0"\n', + // The docs example nobody imports: the only top-level `create`. + 'doc/mutation.dart': `class Mutation { + Object call(String key) => key; +} + +final create = Mutation(); +final createTodo = create('create_todo'); +`, + 'lib/family.dart': `class Ref {} + +class Override { + Override(Object Function(Ref ref) build); +} + +mixin FunctionalFamilyOverride { + ArgT get argument => throw 0; + + Override overrideWith(CreatedT Function(Ref ref, ArgT arg) create) { + return Override((ref) => create(ref, argument) as Object); + } +} + +class Cache { + final _values = {}; + + T upsert(Object key, T Function() create) { + final existing = _values[key]; + if (existing != null) return existing; + final created = create(); + _values[key] = created; + return created; + } +} + +class Holder { + void create() {} + + void run(void Function() create) { + this.create(); + create(); + } +} + +enum Kind { set, list } + +R pick({required R Function() set, required R Function() list}) => set(); + +class Box {} + +Box? find() => null; + +void check() { + final Box? box = find(); + print(box); + Box(); +} +`, + 'test/matrix.dart': `typedef Factory = Object Function(Object Function(Object ref, Object? arg) create, {String? name}); + +final factories = [ + (create, {name}) => create(Object(), name), +]; + +final generic = (T Function() create) => create(); +`, + // Another test's function of the same name as the mock below. + 'test/other_test.dart': `void listener() {} + +void fn() {} +`, + 'test/listener_test.dart': `class Listener { + void call(T? previous, T next) {} +} + +void main() { + final listener = Listener(); + listener(0, 1); + + void Function() build = () {}; + build(); + + for (final fn in []) { + fn(); + } + + final (create, _) = (() => 0, 1); + create(); +} +`, + 'lib/bloc.dart': `abstract class Emitter { + void call(S state); +} + +class Bloc { + void emit(S state) {} + + void on(void Function(E event, Emitter emit) handler) {} +} + +class CounterBloc extends Bloc { + CounterBloc() { + on((event, emit) => emit(1)); + } + + void onReset(String event, Emitter emit) { + emit(0); + } + + void bump() => emit(2); +} +`, + 'lib/util.dart': `void notify(int value) {} +`, + // Calls a closure parameter or a loop variable does not cover, and a local + // function nearer than the parameter it shadows. + 'lib/wire.dart': `import 'util.dart'; + +void wire(List values) { + values.forEach((notify) => print(notify)); + notify(1); + for (final notify in values) { + print(notify); + } + notify(2); +} + +int outer(int Function() make) { + int helper() { + int make() => 2; + return make(); + } + + return helper() + make(); +} +`, +}; + +describe('Dart calls to a parameter or local', () => { + let root = ''; + let cg: CodeGraph | undefined; + let kernel: string | undefined; + + beforeEach(() => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-local-calls-')); + for (const [rel, content] of Object.entries(FILES)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + kernel = process.env.CODEGRAPH_KERNEL; + }); + + afterEach(() => { + cg?.close(); + cg = undefined; + fs.rmSync(root, { recursive: true, force: true }); + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; + }); + + it.each(['default', 'wasm'])('link nothing, and leave the calls they do not cover alone (%s)', async (backend) => { + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; + cg = await CodeGraph.init(root, { index: true }); + const graph = cg; + const node = (file: string, qualifiedName: string): Node => { + const found = graph.getNodesInFile(file).find((n) => n.qualifiedName === qualifiedName); + expect(found, `${file} ${qualifiedName}`).toBeDefined(); + return found!; + }; + /** `qualifiedName:line` of each call (or construction) out of a node. */ + const calls = (from: Node): string[] => + graph + .getOutgoingEdgesFrom([from.id]) + .filter((e) => e.kind === 'calls' || e.kind === 'instantiates') + .map((e) => `${graph.getNode(e.target)!.qualifiedName}:${e.line}`) + .sort(); + /** The line of `file` that holds `text`. */ + const lineOf = (file: string, text: string): number => FILES[file]!.split('\n').findIndex((l) => l.includes(text)) + 1; + + // Only the docs example's own file calls into it (a call through its + // `create` constant constructs the `Mutation` the constant holds). + const docs = graph.getNodesInFile('doc/mutation.dart').map((n) => n.id); + expect([...new Set(graph.getIncomingEdgesTo(docs, ['calls', 'instantiates']).map((e) => graph.getNode(e.source)!.filePath))]) + .toEqual(['doc/mutation.dart']); + + // A parameter: a method's, a function-typed one inside a closure, closures' in initializers. + expect(calls(node('lib/family.dart', 'FunctionalFamilyOverride::overrideWith'))) + .toEqual([`Override:${lineOf('lib/family.dart', 'create(ref, argument)')}`]); + expect(calls(node('lib/family.dart', 'Cache::upsert'))).toEqual([]); + // (a parameter may be named `set`, which is no enum's member here) + expect(calls(node('lib/family.dart', 'pick'))).toEqual([]); + expect(calls(node('test/matrix.dart', 'factories'))).toEqual([]); + expect(calls(node('test/matrix.dart', 'generic'))).toEqual([]); + + // A parameter shadows a method of the class, which `this.` still reaches. + expect(calls(node('lib/family.dart', 'Holder::run'))) + .toEqual([`Holder::create:${lineOf('lib/family.dart', 'this.create();')}`]); + + // A local: a mock, a function-typed variable, a loop variable, a destructured one. + expect(calls(node('test/listener_test.dart', 'main'))) + .toEqual([`Listener:${lineOf('test/listener_test.dart', 'Listener()')}`]); + const otherTest = graph.getNodesInFile('test/other_test.dart').map((n) => n.id); + expect(graph.getIncomingEdgesTo(otherTest, ['calls'])).toEqual([]); + + // A handler's `Emitter` parameter is not `Bloc.emit`; a bare call of the inherited method is. + expect(calls(node('lib/bloc.dart', 'CounterBloc'))).toEqual([`Bloc::on:${lineOf('lib/bloc.dart', 'on')}`]); + expect(calls(node('lib/bloc.dart', 'CounterBloc::onReset'))).toEqual([]); + expect(calls(node('lib/bloc.dart', 'CounterBloc::bump'))).toEqual([`Bloc::emit:${lineOf('lib/bloc.dart', 'emit(2)')}`]); + + // A sibling closure's parameter and a finished loop's variable cover nothing after them. + expect(calls(node('lib/wire.dart', 'wire'))) + .toEqual([`notify:${lineOf('lib/wire.dart', 'notify(1)')}`, `notify:${lineOf('lib/wire.dart', 'notify(2)')}`]); + + // A local function is nearer than the parameter it shadows, inside its block only. + expect(calls(node('lib/wire.dart', 'helper'))).toEqual([`make:${lineOf('lib/wire.dart', 'return make()')}`]); + expect(calls(node('lib/wire.dart', 'outer'))).not.toContain(`make:${lineOf('lib/wire.dart', 'helper() + make()')}`); + + // A nullable typed local's type is not a binding: `Box()` still constructs `Box`. + expect(calls(node('lib/family.dart', 'check'))) + .toEqual([`Box:${lineOf('lib/family.dart', ' Box();')}`, `find:${lineOf('lib/family.dart', '= find()')}`]); + }); +}); diff --git a/src/resolution/dart-local-scope.ts b/src/resolution/dart-local-scope.ts new file mode 100644 index 0000000000..8fdea685e6 --- /dev/null +++ b/src/resolution/dart-local-scope.ts @@ -0,0 +1,666 @@ +/** + * A name a Dart function, closure or block around a call declares — a + * parameter, a local variable, a loop or `catch` variable, a pattern + * variable — is what a bare call of that name means there. + * + * riverpod's `overrideWith(CreatedT Function(Ref ref, ArgT arg) create)` calls + * its parameter, `create(ref, arg)`, and so do its tests' provider factories + * (`(create, {name, dependencies}) => …`). The index holds no node for any of + * those, so the name matcher handed 48 such calls to the one top-level + * `create` it knew: a docs example's `final create = Mutation<…>()` that none + * of the callers import. A parameter hides a member as well: a bloc event + * handler's `emit(…)` calls its `Emitter` parameter, never `Bloc.emit`. The + * same holds for a function passed by name. Read from the source of the + * call's file: + * + * - a parameter list that a body follows (`{ … }` or `=> …`), the body being + * its scope: a function's, a method's, a closure's, a `catch` clause's, a + * constructor's (its initializer list too); + * - the variables a `for` head declares, for the loop; + * - a local a block declares (`final x = …`, `Foo? x;`, `var (a, b) = …`, a + * pattern's `final x`), from there to the block's end. + * + * Fields and top-level variables are not locals. The nearest binding around + * the call decides: a local function declared there is a node, and the call + * keeps the one it resolved to. + */ +import type { ResolutionContext, ResolvedRef, UnresolvedRef } from './types'; + +/** Where a name is bound: offsets into the file's source, inclusive. */ +interface Scope { + start: number; + end: number; + /** A local function's name, which a call can reach. */ + fn?: boolean; +} + +interface DartFileScopes { + lineStarts: number[]; + /** Name → the scopes it is bound in. */ + names: Map; +} + +const memos = new WeakMap>(); + +/** Drop the memos (see ReferenceResolver.clearCaches). */ +export function clearDartLocalScopeMemos(context: ResolutionContext): void { + memos.delete(context); +} + +/** + * The resolved reference, or null when it is a receiver-less Dart call (or a + * function passed by name) whose name a parameter or local around it binds. + */ +export function gateDartLocal(resolved: ResolvedRef | null, ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null { + if (!resolved || ref.language !== 'dart') return resolved; + if (ref.referenceKind !== 'calls' && ref.referenceKind !== 'function_ref') return resolved; + const name = ref.referenceName; + if (!/^[A-Za-z_$][\w$]*$/.test(name)) return resolved; + const file = fileScopes(ref.filePath, context); + const bound = file?.names.get(name); + if (!file || !bound) return resolved; + const lines = context.getFileLines?.(ref.filePath) ?? context.readFile(ref.filePath)?.split('\n'); + const line = lines?.[ref.line - 1]; + if (line === undefined) return resolved; + const column = nameColumn(line, name, ref.column); + // `this.create()`, `x.create()`, `..create()` — the dot maybe ending the + // line before: a member, whatever the locals are. + const before = line.slice(0, column); + if (column < 0 || /\.\s*$/.test(before) || + (before.trim() === '' && /\.\s*$/.test((lines![ref.line - 2] ?? '').replace(/\/\/.*$/, '')))) return resolved; + const at = (file.lineStarts[ref.line - 1] ?? 0) + column; + // Scopes nest, so the binding that starts last is the nearest one. + let nearest: Scope | null = null; + for (const scope of bound) { + if (at >= scope.start && at <= scope.end && (!nearest || scope.start > nearest.start)) nearest = scope; + } + return !nearest || nearest.fn ? resolved : null; +} + +/** + * Where on its line a reference's name starts. A Dart ref's column sits just + * past the name (a function value's at it); a column counted in bytes misses + * on a line with non-ASCII text before it, so the nearest whole-word + * occurrence is taken then. + */ +function nameColumn(line: string, name: string, column: number): number { + const isWord = (at: number): boolean => + line.startsWith(name, at) && !/[\w$]/.test(line[at - 1] ?? '') && !/[\w$]/.test(line[at + name.length] ?? ''); + if (column >= 0 && isWord(column)) return column; + if (column >= name.length && isWord(column - name.length)) return column - name.length; + let best = -1; + for (let at = line.indexOf(name); at >= 0; at = line.indexOf(name, at + 1)) { + if (isWord(at) && (best < 0 || Math.abs(at - column) < Math.abs(best - column))) best = at; + } + return best; +} + +function fileScopes(filePath: string, context: ResolutionContext): DartFileScopes | null { + let memo = memos.get(context); + if (!memo) { + memo = new Map(); + memos.set(context, memo); + } + const hit = memo.get(filePath); + if (hit !== undefined) return hit; + const source = context.readFile(filePath); + const scopes = source === null ? null : readScopes(source); + memo.set(filePath, scopes); + return scopes; +} + +/** Every parameter, loop variable and local a Dart file binds, with its scope. */ +function readScopes(source: string): DartFileScopes { + const lineStarts = [0]; + for (let i = source.indexOf('\n'); i >= 0; i = source.indexOf('\n', i + 1)) lineStarts.push(i + 1); + const code = blankTypeArguments(blankDartLiterals(source)); + const brackets = matchBrackets(code); + const names = new Map(); + const bind = (name: string, start: number, end: number, fn = false): void => { + if (name === '_' || DART_RESERVED.has(name)) return; + const scope: Scope = fn ? { start, end, fn } : { start, end }; + const list = names.get(name); + if (list) list.push(scope); + else names.set(name, [scope]); + }; + const parameterLists = bindParameters(code, brackets, bind); + bindLocals(code, brackets, parameterLists, bind); + return { lineStarts, names }; +} + +type Bind = (name: string, start: number, end: number, fn?: boolean) => void; + +/** + * Each parameter list a body follows, the body being where its names are + * bound — and a `for` head's variables, for the loop. A group a control-flow + * keyword heads (`if (create) {`) holds an expression, and a call's arguments + * (`: super(x) {`, `: _f = make(x) {` in an initializer list) bind nothing. + * A function declared in a block binds its own name there, to the block's end. + * Returns the offsets of the groups read as parameter lists. + */ +function bindParameters(code: string, b: Brackets, bind: Bind): Set { + const lists = new Set(); + for (let k = 0; k < b.at.length; k++) { + const open = b.partner[k]!; + if (code[b.at[k]!] !== ')' || open < 0) continue; + const from = b.at[open]!; + const head = tokenBefore(code, from); + let i = skipSpace(code, b.at[k]! + 1); + const modifier = /^(?:async\s*\*?|sync\s*\*)/.exec(code.slice(i, i + 8)); + if (modifier) i = skipSpace(code, i + modifier[0].length); + const list = code.slice(from + 1, b.at[k]!); + const block = code[i] === '{' && b.at[k + 1] === i && b.partner[k + 1]! >= 0 ? b.at[b.partner[k + 1]!]! : -1; + if (head.word === 'for') { + const end = block >= 0 ? block : endOfStatement(code, b, i, false); + for (const name of forHeadNames(list)) bind(name, from, end); + lists.add(from); + continue; + } + if (head.word !== null && CONTROL_HEADS.has(head.word)) continue; + let scope: Scope | null = null; + if (block >= 0) scope = { start: i, end: block }; + else if (code.startsWith('=>', i)) scope = { start: i, end: endOfStatement(code, b, i + 2, true) }; + else if (code[i] === ':' && isConstructorHead(code, head)) scope = { start: i, end: endOfConstructor(code, b, i + 1) }; + if (!scope || isCallArguments(code, head)) continue; + lists.add(from); + for (const name of parameterNames(list)) bind(name, scope.start, scope.end); + // `int make() => 2;` in a block: a local function, a node of its own. + const around = head.word !== null && !DART_KEYWORDS.has(head.word) ? enclosingBlock(code, b, head.at) : -1; + if (around >= 0) bind(head.word!, head.at, blockEnd(code, b, around), true); + } + return lists; +} + +/** + * Whether a group is a call's arguments rather than a declaration's + * parameters: a call in a constructor's initializer list (`: _value = + * compute(x) {`, `: super.named(x) {`, `: assert(x) {`). + */ +function isCallArguments(code: string, head: { word: string | null; at: number }): boolean { + if (head.word === null) return false; + if (head.word === 'super' || head.word === 'this' || head.word === 'assert') return true; + const before = tokenBefore(code, head.at); + if (before.word === null && /^[=:,]$/.test(code[before.at] ?? '')) return true; + // `super.named(x)` / `this.named(x)`, never a named constructor `Foo.named(x)`. + if (before.word === null && code[before.at] === '.') { + const owner = tokenBefore(code, before.at); + return owner.word === 'super' || owner.word === 'this'; + } + return false; +} + +/** + * Whether a group followed by `:` is a constructor's parameter list — + * `Foo(this.x) :`, `const Foo.named(int x) :` at the start of a member — and + * not a call in a conditional (`c ? f(x) : y`) or a `case Foo(x):`. + */ +function isConstructorHead(code: string, head: { word: string | null; at: number }): boolean { + if (head.word === null || DART_KEYWORDS.has(head.word)) return false; + let type = head.word; + let before = tokenBefore(code, head.at); + if (before.word === null && code[before.at] === '.') { + const owner = tokenBefore(code, before.at); + if (owner.word === null) return false; + type = owner.word; + before = tokenBefore(code, owner.at); + } + if (!/^_*[A-Z$]/.test(type)) return false; + if (before.word !== null) return before.word === 'const' || before.word === 'external'; + return before.at < 0 || /^[;{}]$/.test(code[before.at] ?? ''); +} + +/** + * The end of a constructor's initializer list and body, from just past its + * `:` — the body being the first `{` that does not start a value (`: _m = {}`). + */ +function endOfConstructor(code: string, b: Brackets, from: number): number { + let k = firstBracketFrom(b, from); + let pos = from; + for (;;) { + const next = k < b.at.length ? b.at[k]! : code.length; + const semicolon = code.indexOf(';', pos); + if (semicolon >= 0 && semicolon < next) return semicolon; + if (k >= b.at.length) return code.length; + const ch = code[next]; + if (ch === ')' || ch === ']' || ch === '}') return next; + const close = b.partner[k]!; + if (close < 0) return code.length; + if (ch === '{') { + const prior = tokenBefore(code, next); + if (prior.word !== null || /[)\]'"]/.test(code[prior.at] ?? '')) return b.at[close]!; + } + pos = b.at[close]! + 1; + k = close + 1; + } +} + +/** + * The names a parameter list declares: `(Ref ref, {required this.create, + * int count = 0})`, `([String? label])`, old-style `void cb(int x)` (`cb`), + * untyped closure parameters `(create, {name})`, and a switch arm's pattern + * `Foo(:final value) =>`. + */ +function parameterNames(list: string): string[] { + const names: string[] = []; + for (const raw of splitParameters(list)) { + let item = raw.replace(/@[\w$.]+(?:\s*\([^()]*\))?/g, ' '); + const eq = item.indexOf('='); + if (eq >= 0) item = item.slice(0, eq); + item = item.trimEnd(); + // `void cb(int x)`: the name is before its own parameter list. + if (item.endsWith(')')) { + let depth = 0; + let at = item.length - 1; + for (; at >= 0; at--) { + if (item[at] === ')') depth++; + else if (item[at] === '(' && --depth === 0) break; + } + item = item.slice(0, Math.max(0, at)).trimEnd(); + } + const name = /([A-Za-z_$][\w$]*)$/.exec(item)?.[1]; + if (name) names.push(name); + } + return names; +} + +/** A parameter list's items, the optional group's (`{…}` / `[…]`, always last) included. */ +function splitParameters(list: string): string[] { + const items: string[] = []; + let depth = 0; + let item = ''; + for (let i = 0; i < list.length; i++) { + const ch = list[i]!; + if (depth === 0 && (ch === '{' || ch === '[') && item.trim() === '') { + const close = list.lastIndexOf(ch === '{' ? '}' : ']'); + items.push(...splitParameters(list.slice(i + 1, close > i ? close : list.length))); + return items; + } + if (ch === '(' || ch === '[' || ch === '{') depth++; + else if (ch === ')' || ch === ']' || ch === '}') depth--; + if (ch === ',' && depth === 0) { + if (item.trim() !== '') items.push(item); + item = ''; + } else { + item += ch; + } + } + if (item.trim() !== '') items.push(item); + return items; +} + +/** The variables a `for` head declares: `final x in xs`, `var (a, b) in pairs`, `var i = 0, j = n; …`. */ +function forHeadNames(head: string): string[] { + const loop = /^([^;]*?)\bin\b/.exec(head); + if (loop) { + const decl = loop[1]!.trim(); + const pattern = /^(?:final|var)\s*(?:[\w$.]+\s*)?([([{][\s\S]*)$/.exec(decl); + if (pattern) return patternBinders(pattern[1]!); + const declared = /^(?:(?:final|var|const)\s+(?:[\w$.]+\s*\??\s+)?|[\w$.]+\s*\??\s+)([A-Za-z_$][\w$]*)$/.exec(decl); + return declared ? [declared[1]!] : []; + } + const init = head.split(';')[0] ?? ''; + if (!/^\s*(?:(?:final|var|const|late)\b|[\w$.]+\s*\??\s+[A-Za-z_$][\w$]*\s*=)/.test(init)) return []; + return [...init.matchAll(/(?:^|,|\s)([A-Za-z_$][\w$]*)\s*=(?![=>])/g)].map((m) => m[1]!); +} + +/** The names a destructuring pattern binds: `(a, b)`, `[x, ...rest]`, `Point(:x, y: final py)`, `{'k': v}`. */ +function patternBinders(pattern: string): string[] { + const names: string[] = []; + for (const m of pattern.matchAll(/(?? x = …`, `void Function() x + * = …`, `final (a, b) = …`, and a pattern's `final x` / `var x` (`case + * Foo(:final x)`, `if (v case final x?)`). A declaration directly in a class + * body is a field, and one at the top of the file a library variable. + */ +function bindLocals(code: string, b: Brackets, parameterLists: Set, bind: Bind): void { + // `direct`: a statement's own declaration, whose block is the bracket right + // around it; a pattern's variable is in the block around its `case` or `if`. + const bindInBlock = (name: string, at: number, direct: boolean): void => { + let k = innermostBracket(code, b, at); + while (!direct && k >= 0 && code[b.at[k]!] !== '{') { + // A parameter list's `final x` is the parameter, bound where the list is read. + if (parameterLists.has(b.at[k]!)) return; + k = b.parent[k]!; + } + if (k >= 0 && code[b.at[k]!] === '{' && !isTypeBody(code, b.at[k]!)) bind(name, at, blockEnd(code, b, k)); + }; + for (const m of code.matchAll(/(?])|;))/g)) { + if (isDeclarationType(code, b, tokenBefore(code, m.index))) bindInBlock(m[1]!, m.index, true); + } + // A pattern variable: `case Foo(:final value)`, `if (x case final y?)` — + // not the type of `final Foo? x = …`. + for (const m of code.matchAll(/(?|\bwhen\b|&&|\|\|))/g)) { + bindInBlock(m[1]!, m.index, false); + } + // A destructuring declaration: `final (a, b) = …`, `var Point(:x, :y) = …`. + for (const m of code.matchAll(/(?])/.test(code.slice(close + 1, close + 4))) continue; + for (const name of patternBinders(code.slice(open + 1, close))) bindInBlock(name, m.index, true); + } +} + +/** + * Whether the token before a name followed by `=` / `;` makes it a + * declaration: `final` / `var` / `const`, a type (`Foo`, `Foo?`, `List` + * — type arguments are blanked — or a function type ending `Function(…)`). + */ +function isDeclarationType(code: string, b: Brackets, before: { word: string | null; at: number }): boolean { + if (before.word !== null) return DECLARATION_KEYWORDS.has(before.word) || !DART_KEYWORDS.has(before.word); + const ch = code[before.at]; + if (ch === '?') return /[\w$)]/.test(code[before.at - 1] ?? ''); + if (ch === ')') { + const k = bracketIndexAt(b, before.at); + const open = k >= 0 ? b.partner[k]! : -1; + return open >= 0 && tokenBefore(code, b.at[open]!).word === 'Function'; + } + return false; +} + +/** Whether the `{` at `brace` opens a class, mixin, enum or extension body. */ +function isTypeBody(code: string, brace: number): boolean { + const from = Math.max(code.lastIndexOf(';', brace - 1), code.lastIndexOf('{', brace - 1), code.lastIndexOf('}', brace - 1)); + return TYPE_BODY_HEAD.test(code.slice(from + 1, brace)); +} + +const TYPE_BODY_HEAD = /^\s*(?:@[\w$.]+(?:\s*\((?:[^()]|\([^()]*\))*\))?\s*)*(?:(?:abstract|base|final|sealed|interface|mixin|augment)\s+)*(?:class|mixin|enum|extension)\b/; + +/** The index of the `{` right around offset `at` when it holds statements (no class or extension body), or -1. */ +function enclosingBlock(code: string, b: Brackets, at: number): number { + const k = innermostBracket(code, b, at); + return k >= 0 && code[b.at[k]!] === '{' && !isTypeBody(code, b.at[k]!) ? k : -1; +} + +/** Where the bracket at index `k` closes: the end of the file when it never does. */ +function blockEnd(code: string, b: Brackets, k: number): number { + return b.partner[k]! >= 0 ? b.at[b.partner[k]!]! : code.length; +} + +/** + * Where the expression or statement starting at `from` ends: the first `;` + * (and, for an expression, `,`) outside the brackets it opens, or the close + * of the bracket around it — the end of a `=> …` body in an argument list, + * a switch arm or a declaration. + */ +function endOfStatement(code: string, b: Brackets, from: number, expression: boolean): number { + let k = firstBracketFrom(b, from); + let pos = from; + for (;;) { + const next = k < b.at.length ? b.at[k]! : code.length; + for (let i = pos; i < next; i++) { + if (code[i] === ';' || (expression && code[i] === ',')) return i; + } + if (k >= b.at.length) return code.length; + const ch = code[next]; + if (ch === ')' || ch === ']' || ch === '}') return next; + const close = b.partner[k]!; + if (close < 0) return code.length; + pos = b.at[close]! + 1; + k = close + 1; + } +} + +/** The word right before offset `at` (skipping blanks), or else the offset of the character there (-1 at the start). */ +function tokenBefore(code: string, at: number): { word: string | null; at: number } { + let i = at - 1; + while (i >= 0 && /\s/.test(code[i]!)) i--; + let start = i; + while (start >= 0 && /[\w$]/.test(code[start]!)) start--; + if (start === i) return { word: null, at: i }; + return { word: code.slice(start + 1, i + 1), at: start + 1 }; +} + +function skipSpace(code: string, at: number): number { + while (at < code.length && /\s/.test(code[at]!)) at++; + return at; +} + +/** Keywords that head a parenthesised expression, not a parameter list. */ +const CONTROL_HEADS: ReadonlySet = new Set(['if', 'while', 'switch']); + +/** Keywords a declaration's name can follow. */ +const DECLARATION_KEYWORDS: ReadonlySet = new Set(['final', 'var', 'const']); + +/** Dart's reserved words: never a name a declaration binds. */ +const DART_RESERVED: ReadonlySet = new Set([ + 'assert', 'break', 'case', 'catch', 'class', 'const', 'continue', 'default', 'do', 'else', 'enum', 'extends', + 'false', 'final', 'finally', 'for', 'if', 'in', 'is', 'new', 'null', 'rethrow', 'return', 'super', 'switch', + 'this', 'throw', 'true', 'try', 'var', 'void', 'while', 'with', +]); + +/** + * The reserved words and the built-in and contextual ones that never name a + * declaration's type or a function there. Several are fine parameter names — + * json_generator's `R Function(DartType item) set` — so only DART_RESERVED + * keeps a name from binding. + */ +const DART_KEYWORDS: ReadonlySet = new Set([ + ...DART_RESERVED, + 'abstract', 'as', 'async', 'await', 'base', 'covariant', 'deferred', 'export', 'extension', 'external', 'factory', + 'get', 'hide', 'implements', 'import', 'interface', 'late', 'library', 'mixin', 'of', 'on', 'operator', 'part', + 'required', 'sealed', 'set', 'show', 'static', 'sync', 'typedef', 'when', 'yield', +]); + +// ---------------------------------------------------------------- brackets + +interface Brackets { + /** The offset of every bracket character, in order. */ + at: number[]; + /** For each bracket, the index of its partner, or -1. */ + partner: number[]; + /** For each bracket, the index of the open bracket around it, or -1. */ + parent: number[]; +} + +/** Pairs `()`, `[]` and `{}`; a stray close is left unpaired, and so are the opens a close skips past. */ +function matchBrackets(code: string): Brackets { + const at: number[] = []; + const partner: number[] = []; + const parent: number[] = []; + const stack: number[] = []; + for (let i = 0; i < code.length; i++) { + const ch = code[i]; + if (ch === '(' || ch === '[' || ch === '{') { + at.push(i); + partner.push(-1); + parent.push(stack.length > 0 ? stack[stack.length - 1]! : -1); + stack.push(at.length - 1); + } else if (ch === ')' || ch === ']' || ch === '}') { + const want = ch === ')' ? '(' : ch === ']' ? '[' : '{'; + let s = stack.length - 1; + while (s >= 0 && code[at[stack[s]!]!] !== want) s--; + at.push(i); + partner.push(-1); + if (s < 0) { + parent.push(stack.length > 0 ? stack[stack.length - 1]! : -1); + continue; + } + const open = stack[s]!; + stack.length = s; + partner[open] = at.length - 1; + partner[at.length - 1] = open; + parent.push(parent[open]!); + } + } + return { at, partner, parent }; +} + +/** The index of the first bracket at or after offset `from`. */ +function firstBracketFrom(b: Brackets, from: number): number { + let lo = 0; + let hi = b.at.length; + while (lo < hi) { + const mid = (lo + hi) >> 1; + if (b.at[mid]! < from) lo = mid + 1; + else hi = mid; + } + return lo; +} + +/** The index of the bracket at offset `at`, or -1. */ +function bracketIndexAt(b: Brackets, at: number): number { + const k = firstBracketFrom(b, at); + return b.at[k] === at ? k : -1; +} + +/** The index of the innermost open bracket around offset `at`, or -1. */ +function innermostBracket(code: string, b: Brackets, at: number): number { + const k = firstBracketFrom(b, at) - 1; + if (k < 0) return -1; + const ch = code[b.at[k]!]; + return ch === '(' || ch === '[' || ch === '{' ? k : b.parent[k]!; +} + +// ---------------------------------------------------------------- lexing + +/** + * The source with comments and the text of string literals blanked to + * spaces (offsets and newlines kept). Code inside a `${…}` interpolation + * stays, minus the braces that delimit it; block comments nest, and raw + * strings (`r'…'`) have no escapes or interpolation. + */ +function blankDartLiterals(source: string): string { + const out = source.split(''); + const n = source.length; + const blank = (from: number, to: number): void => { + for (let k = from; k < to && k < n; k++) if (source[k] !== '\n' && source[k] !== '\r') out[k] = ' '; + }; + // The strings an interpolation was opened from, innermost last, with the brace depth inside it. + const suspended: Array<{ quote: string; braces: number }> = []; + let quote: string | null = null; + let raw = false; + let i = 0; + while (i < n) { + if (quote !== null) { + if (source.startsWith(quote, i)) { + i += quote.length; + quote = null; + continue; + } + const ch = source[i]!; + if (!raw && ch === '\\') { + blank(i, i + 2); + i += 2; + continue; + } + if (!raw && ch === '$' && source[i + 1] === '{') { + blank(i, i + 2); + suspended.push({ quote, braces: 0 }); + quote = null; + i += 2; + continue; + } + // A single-quoted string ends at the line's end however it was left. + if (quote.length === 1 && ch === '\n') { + quote = null; + i++; + continue; + } + blank(i, i + 1); + i++; + continue; + } + const ch = source[i]!; + if (ch === '/' && source[i + 1] === '/') { + const end = source.indexOf('\n', i); + blank(i, end < 0 ? n : end); + i = end < 0 ? n : end; + continue; + } + if (ch === '/' && source[i + 1] === '*') { + let depth = 1; + let j = i + 2; + while (j < n && depth > 0) { + if (source[j] === '/' && source[j + 1] === '*') { + depth++; + j += 2; + } else if (source[j] === '*' && source[j + 1] === '/') { + depth--; + j += 2; + } else { + j++; + } + } + blank(i, j); + i = j; + continue; + } + if (suspended.length > 0 && (ch === '{' || ch === '}')) { + const top = suspended[suspended.length - 1]!; + if (ch === '{') top.braces++; + else if (top.braces > 0) top.braces--; + else { + blank(i, i + 1); + suspended.pop(); + quote = top.quote; + raw = false; + } + i++; + continue; + } + if (ch === '"' || ch === "'") { + raw = source[i - 1] === 'r' && !/[\w$]/.test(source[i - 2] ?? ''); + quote = source[i + 1] === ch && source[i + 2] === ch ? ch.repeat(3) : ch; + i += quote.length; + continue; + } + i++; + } + return out.join(''); +} + +/** + * The code with type-argument lists blanked — `Map`, `(x) =>`, + * `[]` — so their commas never end an argument and their angle brackets + * never read as comparisons. A `<` opens one when it follows a name with no + * space (`List`), or when what it closes is followed by `(`, `[`, `{` or + * `.` (a generic function or a typed literal), and everything inside is type + * syntax. + */ +function blankTypeArguments(code: string): string { + if (!code.includes('<')) return code; + const out = code.split(''); + let i = code.indexOf('<'); + while (i >= 0) { + const end = typeArgumentsEnd(code, i); + if (end > i) { + const glued = /[\w$]/.test(code[i - 1] ?? ''); + const next = code[skipSpace(code, end + 1)] ?? ''; + if (glued || next === '(' || next === '[' || next === '{' || next === '.') { + for (let k = i; k <= end; k++) if (out[k] !== '\n' && out[k] !== '\r') out[k] = ' '; + i = code.indexOf('<', end + 1); + continue; + } + } + i = code.indexOf('<', i + 1); + } + return out.join(''); +} + +/** The offset of the `>` closing a type-argument list opened at `open`, or -1 if what follows is not one. */ +function typeArgumentsEnd(code: string, open: number): number { + let angles = 0; + let parens = 0; + for (let i = open; i < code.length && i < open + 400; i++) { + const ch = code[i]!; + if (ch === '<') angles++; + else if (ch === '>') { + if (code[i - 1] === '=') return -1; + if (--angles === 0) return parens === 0 ? i : -1; + } else if (ch === '(' || ch === '{') parens++; + else if (ch === ')' || ch === '}') { + if (--parens < 0) return -1; + } else if (!/[\w$\s.,?]/.test(ch)) return -1; + } + return -1; +} diff --git a/src/resolution/index.ts b/src/resolution/index.ts index 0b952a6410..8964590a79 100644 --- a/src/resolution/index.ts +++ b/src/resolution/index.ts @@ -27,6 +27,7 @@ import { isCppConstructorRef, matchCppConstructor } from './cpp-constructor'; import { gateSwiftTypeTarget, clearSwiftTypeVisibility, swiftExtendedConformances } from './swift-type-visibility'; import { clearVbnetReceiverMemos, isVbMemberRead, isVbPathCall, matchVbMemberRead, matchVbPathCall } from './vbnet-receivers'; import { gateTypeParameter, clearTypeParameterMemos } from './type-parameters'; +import { gateDartLocal, clearDartLocalScopeMemos } from './dart-local-scope'; import { resolveViaImport, resolvePhpImportedStaticCall, resolvePhpQualifiedClassRef, resolveJvmImport, extractImportMappings, extractReExports, loadCppIncludeDirs, isPhpIncludePathRef, isCobolCopybookRef, isNixPathImportRef, isJsPathImportRef, isBoundToOutOfRepoImport, clearImportResolverMemos, resolveImportPath, isExternalImport } from './import-resolver'; import { ResolverPool, minRefsForPool, shouldEngageAdaptively } from './resolver-pool'; import { resolveAliasBinding } from './alias-binding'; @@ -471,6 +472,7 @@ export class ReferenceResolver { clearSwiftTypeVisibility(this.context); clearVbnetReceiverMemos(this.context); clearTypeParameterMemos(this.context); + clearDartLocalScopeMemos(this.context); } } @@ -1096,9 +1098,14 @@ export class ReferenceResolver { // A Swift type reference never lands on an `extension X {}` node, nor on a // nested type it cannot name bare (see ./swift-type-visibility). // A name a declaration around the reference declares as a type parameter - // (`def f[A]`, `class Foo`) is that parameter (see ./type-parameters). - const candidate = gateTypeParameter( - gateSwiftTypeTarget(this.gateTargetKind(this.resolveOneInner(ref), ref), ref, this.context), + // (`def f[A]`, `class Foo`) is that parameter (see ./type-parameters), + // and a Dart call to a parameter or local calls that (./dart-local-scope). + const candidate = gateDartLocal( + gateTypeParameter( + gateSwiftTypeTarget(this.gateTargetKind(this.resolveOneInner(ref), ref), ref, this.context), + ref, + this.context, + ), ref, this.context, ); From 652c36b72ae621f29d1cf3f59cee784fe9a21165 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 14:48:06 +0000 Subject: [PATCH 08/23] fix(dart): index const constructors and redirecting factories; a call through a type stays on that type (#2380) * fix(dart): index const constructors and redirecting factories; a call through a type stays on that type Both Dart extractors (the TS walker and the native kernel) skipped `const` constructors and redirecting factories (`const Foo.bar(...)`, `const factory Foo.bar() = _Bar;`), which parse as signature kinds of their own. A call such as flutter_bloc's `BlocProvider.value(...)` then found no method on BlocProvider, and the resolver guessed another type's `value`: on felangel/bloc, 89 calls linked to `RepositoryProvider::value`. Extraction (TS + kernel, at parity): - Named const constructors and redirecting factories are methods named by the constructor, returning their class, with a parameters-only signature; the unnamed ones stay unindexed. The name is read only from before the parameter list, so a redirect target (`= _Impl.named`) never names it. - A redirecting factory references the class it redirects to, not the target constructor's name or an import prefix. - A constructor called with type arguments keeps its type: `BlocProvider.value(...)` is `BlocProvider.value`, as a statement and as an expression (`constructor_invocation`, which produced no call at all before). Resolver: - A Dart call through a type's name reaches only that type's own constructor, static member or static constant, or nothing: no guess by name, no inherited lookup, no same-file look-alike, no instance member of the same name. SDK calls like `Uri.parse` no longer land on a project `parse` past an `extension on Uri`. - A named constructor is never reached by a bare name, the last link of a chain, a function value or an annotation (riverpod's 210 `@internal` annotations). Validated on felangel/bloc @b9be1e2 and rrousselGit/riverpod @4ba1be2 with the kernel loaded: bloc 18,338 -> 18,495 edges, riverpod 85,606 -> 85,854, every removed edge triaged. Afterwards every edge into a named constructor is written `Owner.ctor`. Co-Authored-By: Claude Opus 5.5 * fix(dart): read a type's static members one way for calls and chains - A call through a type's name now finds its member with dartStaticMember, the lookup a chain's static link uses since #2376, so both pick the same member: the call site's own file first, then the nearest copy. - isDartStaticMember's constructor test is isDartConstructor, anchored at the declaration: an instance getter declared just above a same-named factory (`Object? get error` over `const factory AsyncValue.error(...)`) read the factory from the next lines and counted as static. - clearNameMatcherMemos drops DART_CONSTRUCTORS with the other source-derived Dart memos. Co-Authored-By: Claude Opus 5.5 --------- Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/dart-const-constructors.test.ts | 277 ++++++++++++++++++ .../kernel-parity/TortureConstCtors.dart | 86 ++++++ __tests__/kernel-dart-parity.test.ts | 11 +- codegraph-kernel/src/dart.rs | 119 ++++++-- docs/design/dart-kernel-port-checklist.md | 50 +++- src/extraction/languages/dart.ts | 68 ++++- src/extraction/tree-sitter.ts | 12 + src/resolution/name-matcher.ts | 107 +++++-- 9 files changed, 660 insertions(+), 71 deletions(-) create mode 100644 __tests__/dart-const-constructors.test.ts create mode 100644 __tests__/fixtures/kernel-parity/TortureConstCtors.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 49ffc639ab..0e6a11232f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In VB.NET, reading or setting a field or property through a variable, parameter, field, `Me` or `MyBase`, like `x.Normal = 3`, `Me._h.Title`, `.Value` inside a `With` block or `.Switch` in `New BoolParam With {…}`, now counts as a use of that member, and so do calls inside a `With` block, functions called without parentheses and reads through a class whose name starts in lower case. Before, `codegraph callers` on an instance field or property missed most of its uses. Only a member that the value's declared type has or inherits is linked, nothing when that type comes from outside your project, and a value named after its class, like `theme As Theme`, counts as a use of the class only when it reads a `Shared` member. Re-index VB.NET projects after upgrading. - In JavaScript and TypeScript, an import whose name contains a `$`, like `import items$ from './store'`, `import * as api$ from './api'` or `import { load as load$ } from './data'`, now links the calls made through it, such as `items$.getState().inc()`, to the code it imports, and so does a `$` name in a `require(…)` destructuring or an `export { … } from` barrel. Before, such an import was skipped or bound under a cut-off name (`load` for `load$`), so those calls reached nothing and the functions they call could look unused. A local variable or parameter that reuses an imported `$` name, like `const items$ = …` inside a function, is no longer mistaken for the import. Re-index JavaScript and TypeScript projects after upgrading. - In Dart, calling a parameter or a local variable, like `create(ref, arg)` inside `overrideWith(… create)`, a closure's parameter, a loop variable or a test's mock `listener(0, 1)`, no longer links the call to an unrelated function or constant of the same name in another file, or to a method the class inherits: a Bloc event handler's `emit(…)` is the handler's own `emit` parameter, not `Bloc.emit`. So `codegraph callers` and impact no longer list code that never calls them, while calls the parameter or variable doesn't cover, and calls to a local function, link as before. Re-index Dart projects after upgrading. +- In Dart, `const` constructors and redirecting factories, like flutter_bloc's `const BlocProvider.value(…)` or freezed's `const factory LoginState.loading() = _Loading;`, are now indexed, so a call such as `BlocProvider.value(…)` or `BlocProvider.value(…)` links to that constructor instead of another class's member with the same name. A call through a class name now reaches only that class's own constructors and static members, never a look-alike class, a parent class, an instance getter of the same name, or a project method that merely shares its name with an SDK call like `Uri.parse(…)`, and a constructor is no longer linked from a bare name, the end of a call chain or an annotation like `@internal`. Re-index Dart projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/dart-const-constructors.test.ts b/__tests__/dart-const-constructors.test.ts new file mode 100644 index 0000000000..438c84f3a3 --- /dev/null +++ b/__tests__/dart-const-constructors.test.ts @@ -0,0 +1,277 @@ +/** + * Dart `const` constructors and redirecting factories are methods, and a call + * through a type's name is to that type's own member or to nothing. + * + * `const Foo.bar(…)` and `const factory Foo.bar() = _Bar;` parse as signature + * kinds of their own, which neither extractor indexed. So flutter_bloc's + * `BlocProvider.value(…)` found no `value` on BlocProvider, and the resolver + * guessed the one other `value` — RepositoryProvider's non-const constructor — + * for all 89 calls in felangel/bloc. + * + * Dart inherits no static member and no constructor, so a call through a type + * the project declares never means another type's method: not a same-named + * one guessed by name, not a supertype's, not a same-file look-alike's. And + * the SDK's `Uri.parse(…)` is not a project `parse` because the project has an + * `extension on Uri`. + * + * A constructor is only ever called through its class. Written with type + * arguments — `BlocProvider.value(…)`, most of bloc's tests — + * the call still names the type, and a bare name or a chain's last link + * (`box.inner.value(1)`) never means a constructor. + * + * Runs against the native kernel (when built) and the wasm extractor, which + * must agree. + */ +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; +import type { Node } from '../src/types'; + +const FILES: Record = { + 'pubspec.yaml': 'name: app\nenvironment:\n sdk: ">=3.0.0 <4.0.0"\n', + 'lib/bloc_provider.dart': `class BlocProvider { + const BlocProvider({required T Function() create}) : _create = create, _value = null; + + const BlocProvider.value({required T value}) : this._(value: value); + + const BlocProvider._({T? value}) : _create = null, _value = value; + + final T Function()? _create; + final T? _value; + + void handle(Object value) => accept(value); +} + +void accept(Object o) {} +`, + 'lib/repository_provider.dart': `class RepositoryProvider { + RepositoryProvider({required T Function() create}); + + RepositoryProvider.value({required T value}); + + static T of(Object context) => throw 0; +} +`, + 'lib/new_car_state.dart': `class NewCarState { + const NewCarState._({this.brands = const []}); + + const NewCarState.initial() : this._(); + + const factory NewCarState.loading() = _Loading; + + const factory NewCarState() = _Loading.named; + + const factory NewCarState.fromJson(Map json) = _Loading.fromJson; + + final List brands; +} + +class _Loading extends NewCarState { + const _Loading() : super._(); + + const _Loading.named() : super._(); + + const _Loading.fromJson(Map json) : super._(); +} +`, + 'lib/profile_wizard_state.dart': `class ProfileWizardState { + ProfileWizardState.initial() : step = 0; + + final int step; + + Object fromJson(Object json) => json; +} +`, + // A look-alike declared first in the same file. + 'lib/family.dart': `class EmptyFamily extends Family { + EmptyFamily._() : super._(); +} + +class Family { + const Family._(); + + static Family make() => Family._(); +} +`, + 'lib/sub.dart': `abstract class Base { + const Base(); + + factory Base.named() => const _BaseImpl(); +} + +class _BaseImpl extends Base { + const _BaseImpl(); +} + +class Sub extends Base { + const Sub(); + + const factory Sub.named() = _SubImpl; +} + +class _SubImpl extends Sub { + const _SubImpl(); +} +`, + 'lib/analysis_options.dart': `class AnalysisOptions { + const AnalysisOptions(this.path); + + factory AnalysisOptions.parse(String path) => AnalysisOptions(path); + + final String path; +} +`, + 'lib/linter.dart': `extension on Uri { + String get canonicalizedPath => path; +} +`, + // An instance getter declared before a constructor of the same name. + 'lib/async_value.dart': `sealed class AsyncValue { + const AsyncValue._(); + + Object? get error => null; + + const factory AsyncValue.error(Object error) = AsyncError; +} + +class AsyncError extends AsyncValue { + const AsyncError(this.error) : super._(); + + @override + final Object error; +} + +Object fail(Object e) => AsyncValue.error(e); +`, + 'lib/change_notifier_provider.dart': `class ChangeNotifierProvider { + const ChangeNotifierProvider.internal(); +} +`, + // package:meta's `internal` annotation is a constant outside the project. + 'lib/scope.dart': `import 'package:meta/meta.dart'; + +@internal +Object guarded() => 0; +`, + 'lib/app.dart': `import 'bloc_provider.dart'; +import 'repository_provider.dart'; +import 'new_car_state.dart'; +import 'sub.dart'; + +Object build(Object counter) => BlocProvider.value(value: counter); +Object typed(Object counter) => BlocProvider.value(value: counter); +Object typedRepository(Object repository) => RepositoryProvider.value(value: repository); +NewCarState start() => NewCarState.initial(); +NewCarState load() => NewCarState.loading(); +Sub sub() => Sub.named(); +Object find(Object context) => BlocProvider.of(context); +Uri link() => Uri.parse('https://example.com'); +Object tail(dynamic box) => box.inner.value(1); +`, +}; + +describe('Dart const constructors and redirecting factories', () => { + let root = ''; + let cg: CodeGraph | undefined; + let kernel: string | undefined; + + beforeEach(() => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-const-ctors-')); + for (const [rel, content] of Object.entries(FILES)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + kernel = process.env.CODEGRAPH_KERNEL; + }); + + afterEach(() => { + cg?.close(); + cg = undefined; + fs.rmSync(root, { recursive: true, force: true }); + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; + }); + + it.each(['default', 'wasm'])('are indexed and called through their own type (%s)', async (backend) => { + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; + cg = await CodeGraph.init(root, { index: true }); + const graph = cg; + const find = (file: string, qualifiedName: string): Node | undefined => + graph.getNodesInFile(file).find((n) => n.qualifiedName === qualifiedName); + const node = (file: string, qualifiedName: string): Node => { + const found = find(file, qualifiedName); + expect(found, `${file} ${qualifiedName}`).toBeDefined(); + return found!; + }; + const targets = (from: Node, kind: string): string[] => + [...new Set(graph + .getOutgoingEdgesFrom([from.id]) + .filter((e) => e.kind === kind) + .map((e) => graph.getNode(e.target)!.qualifiedName))] + .sort(); + const sources = (to: Node): string[] => + [...new Set(graph + .getIncomingEdgesTo([to.id]) + .filter((e) => e.kind !== 'contains') + .map((e) => `${e.kind} ${graph.getNode(e.source)!.qualifiedName}`))] + .sort(); + + // Named `const` constructors and redirecting factories are methods named + // by the constructor, returning their class; the unnamed ones stay + // unindexed, as the unnamed generative constructor is, and a redirecting + // factory's target (`= _Loading.named`) names nothing. + const value = node('lib/bloc_provider.dart', 'BlocProvider::value'); + expect(value.kind).toBe('method'); + expect(value.returnType).toBe('BlocProvider'); + expect(value.signature).toBe('({required T value})'); + node('lib/bloc_provider.dart', 'BlocProvider::_'); + expect(find('lib/bloc_provider.dart', 'BlocProvider::BlocProvider')).toBeUndefined(); + node('lib/new_car_state.dart', 'NewCarState::initial'); + const loading = node('lib/new_car_state.dart', 'NewCarState::loading'); + expect(loading.signature).toBe('()'); + expect(find('lib/new_car_state.dart', 'NewCarState::NewCarState')).toBeUndefined(); + expect(find('lib/new_car_state.dart', 'NewCarState::named')).toBeUndefined(); + node('lib/new_car_state.dart', '_Loading::named'); + node('lib/sub.dart', 'Sub::named'); + // A redirecting factory refers to the class it constructs, and not to + // that class's constructor as if it were a type (`= _Loading.fromJson`). + expect(targets(loading, 'references')).toEqual(['_Loading']); + expect(targets(node('lib/new_car_state.dart', 'NewCarState::fromJson'), 'references')).toEqual(['_Loading']); + expect(sources(node('lib/profile_wizard_state.dart', 'ProfileWizardState::fromJson'))).toEqual([]); + + // Each call reaches the constructor of the type it names, type arguments + // or not... + expect(targets(node('lib/app.dart', 'build'), 'calls')).toEqual(['BlocProvider::value']); + expect(targets(node('lib/app.dart', 'typed'), 'calls')).toEqual(['BlocProvider::value']); + expect(targets(node('lib/app.dart', 'typedRepository'), 'calls')).toEqual(['RepositoryProvider::value']); + expect(targets(node('lib/app.dart', 'start'), 'calls')).toEqual(['NewCarState::initial']); + expect(targets(node('lib/app.dart', 'load'), 'calls')).toEqual(['NewCarState::loading']); + expect(targets(node('lib/app.dart', 'sub'), 'calls')).toEqual(['Sub::named']); + expect(targets(node('lib/family.dart', 'Family::make'), 'calls')).toEqual(['Family::_']); + // A constructor, not the instance getter that shares its name. + const errorFactory = graph.getNodesInFile('lib/async_value.dart') + .find((n) => n.qualifiedName === 'AsyncValue::error' && n.signature === '(Object error)'); + expect(errorFactory).toBeDefined(); + expect(graph.getOutgoingEdgesFrom([node('lib/async_value.dart', 'fail').id]) + .filter((e) => e.kind === 'calls').map((e) => e.target)).toEqual([errorFactory!.id]); + // ...and never another type's member of that name. + expect(sources(node('lib/repository_provider.dart', 'RepositoryProvider::value'))).toEqual(['calls typedRepository']); + expect(sources(node('lib/profile_wizard_state.dart', 'ProfileWizardState::initial'))).toEqual([]); + expect(sources(node('lib/family.dart', 'EmptyFamily::_'))).toEqual([]); + expect(sources(node('lib/sub.dart', 'Base::named'))).toEqual([]); + // A member the named type does not declare is outside the project. + expect(targets(node('lib/app.dart', 'find'), 'calls')).toEqual([]); + expect(sources(node('lib/repository_provider.dart', 'RepositoryProvider::of'))).toEqual([]); + expect(targets(node('lib/app.dart', 'link'), 'calls')).toEqual([]); + expect(sources(node('lib/analysis_options.dart', 'AnalysisOptions::parse'))).toEqual([]); + + // A constructor is only ever reached through its class: a parameter that + // shares its name, the last link of a chain, or an annotation is not it. + expect(targets(node('lib/app.dart', 'tail'), 'calls')).toEqual([]); + expect(sources(value)).toEqual(['calls build', 'calls typed']); + expect(sources(node('lib/change_notifier_provider.dart', 'ChangeNotifierProvider::internal'))).toEqual([]); + }); +}); diff --git a/__tests__/fixtures/kernel-parity/TortureConstCtors.dart b/__tests__/fixtures/kernel-parity/TortureConstCtors.dart new file mode 100644 index 0000000000..3d23bce806 --- /dev/null +++ b/__tests__/fixtures/kernel-parity/TortureConstCtors.dart @@ -0,0 +1,86 @@ +import 'package:meta/meta.dart'; +import 'package:other/other.dart' as p; + +const kDepth = 3; + +/// A provider with const constructors and redirecting factories. +class ProviderT { + /// The unnamed const constructor: no node. + const ProviderT({required this.create, this.lazy = true}) : _value = null; + + /// A named const constructor that redirects. + const ProviderT.value({required T value, int depth = kDepth}) + : this._(value: value); + + @visibleForTesting + const ProviderT._({T? value}) + : create = null, + lazy = false, + _value = value; + + const factory ProviderT.redirect({int a}) = _ImplT; + + factory ProviderT.plain() = _ImplT.named; + + const factory ProviderT.json(Map json) = _ImplT.fromJson; + + const factory ProviderT.prefixed() = p.OtherT; + + const factory ProviderT.prefixedNamed() = p.OtherT.named; + + const factory ProviderT.unnamedTarget() = _ImplT; + + const factory ProviderT() = _ImplT.named; + + final Object? create; + final bool lazy; + final T? _value; + + void handle(Object value) => accept(value); + + static ProviderT make() => ProviderT.value(value: 1); + + static Object typed(dynamic box) { + ProviderT.value(value: 2); + final made = ProviderT.value(value: 3); + accept(ProviderT.value(value: 4)); + wrap(child: ProviderT.value(value: 5)); + box.inner.value(6); + return p.OtherT.named(made); + } +} + +class _ImplT extends ProviderT { + const _ImplT({int a = 0}) : super._(); + + const _ImplT.named() : super._(); + + const _ImplT.fromJson(Map json) : super._(); +} + +class _$GeneratedT { + const _$GeneratedT.create(); +} + +enum StatusT { + ok(200), + gone.named(410); + + const StatusT(this.code); + + const StatusT.named(this.code); + + final int code; +} + +extension type const MetersT(int value) { + const MetersT.zero() : this(0); +} + +final topProvider = ProviderT.value(value: 7); + +Object build() => ProviderT.value(value: 8); + +void accept(Object o) {} + +void wrap({required Object child}) {} diff --git a/__tests__/kernel-dart-parity.test.ts b/__tests__/kernel-dart-parity.test.ts index cc8fd008e3..7943d34778 100644 --- a/__tests__/kernel-dart-parity.test.ts +++ b/__tests__/kernel-dart-parity.test.ts @@ -19,12 +19,15 @@ * and the exact duplicated-ref interleave; TortureFnrefDart.dart: fn-ref * capture channels incl. named-argument non-capture and the file/class * twins; TortureMini/TortureSigs/TortureCtors/TortureVrefDart: signatures - * verbatim, prefixed-return-type prefix bug, const factories invisible, + * verbatim, prefixed-return-type prefix bug, a const factory as a method, * value-ref matrix with `$X` vs `${X}` asymmetry; TortureReadsTypes.dart: * getter-read refs and the type positions outside signatures — #2338/#2327; * TortureInitializers.dart: initializers walked as the code their constant, * class or file runs, every member-body kind, and a local declaration's - * second variable left to its function) and their CRLF variants + * second variable left to its function; TortureConstCtors.dart: `const` + * constructors and redirecting factories as methods with the unnamed ones + * skipped, every redirect-target form, and constructors called with type + * arguments, as statements and as expressions) and their CRLF variants * (derived in-memory — #1329), plus defer and generated-file pins. * * The full-repo sweeps live in scripts/kernel-parity.mjs (shelf/bloc/flutter @@ -122,6 +125,10 @@ describe.skipIf(!kernelBuilt)('kernel Dart extraction parity', () => { // instantiations, reads, closures with block bodies and local functions, // and function values captured once, for the declaration. ['TortureInitializers.dart', 30], + // `const` constructors and redirecting factories as methods (the unnamed + // ones skipped), every redirect-target form, and constructors called + // with type arguments in statements and expressions. + ['TortureConstCtors.dart', 20], ] as const; for (const [file, minNodes] of FIXTURES) { diff --git a/codegraph-kernel/src/dart.rs b/codegraph-kernel/src/dart.rs index b423a8f6ef..458ecc5c44 100644 --- a/codegraph-kernel/src/dart.rs +++ b/codegraph-kernel/src/dart.rs @@ -18,8 +18,9 @@ //! `.`); `ConfigT.load()` double-emits (calls + a static-member references //! ref — no callee-of-call skip in the dart branch); operator methods mint //! `method ""`; the unnamed constructor is skipped -//! (isMisparsedFunction) while named ctors/factories are named by the CTOR -//! name with the class as returnType; instance fields mint NO nodes (only +//! (isMisparsedFunction) while named ctors/factories — `const` ones and +//! redirecting factories included — are named by the CTOR name with the +//! class as returnType; instance fields mint NO nodes (only //! static_final_declaration → constant, via the hook); every initializer is //! body-walked once — a constant's from the constant, a field's or a //! top-level variable's from the class or the file; prefixed return @@ -90,6 +91,23 @@ fn angle_args_re() -> &'static Regex { RE.get_or_init(|| Regex::new(r"<[^>]*>").unwrap()) } +/// The UpperCamel test of isDartTypeName (`/^[_$]*[A-Z]/`) — how Dart writes +/// a type, `_Private` and `$Generated` ones included. +fn is_upper_camel(text: &str) -> bool { + text.trim_start_matches(&['_', '$'][..]) + .chars() + .next() + .map(|c| c.is_ascii_uppercase()) + .unwrap_or(false) +} + +/// DART_BODILESS_CTORS (dart.ts) — `const Foo.bar();` and a redirecting +/// factory `const factory Foo.bar() = _Bar;`, each a signature kind of its +/// own inside a `declaration`. +fn is_bodiless_ctor(kind: &str) -> bool { + matches!(kind, "constant_constructor_signature" | "redirecting_factory_constructor_signature") +} + struct Scope { row: u32, kind: &'static str, @@ -385,7 +403,9 @@ impl<'t> Walker<'t> { /// dartConstructorSignature (dart.ts:25-35). fn constructor_signature(&self, node: Node<'t>) -> Option> { - if matches!(node.kind(), "factory_constructor_signature" | "constructor_signature") { + if matches!(node.kind(), "factory_constructor_signature" | "constructor_signature") + || is_bodiless_ctor(node.kind()) + { return Some(node); } if node.kind() == "method_signature" { @@ -415,9 +435,12 @@ impl<'t> Walker<'t> { /// dartCtorInfo (dart.ts:61-70). fn ctor_info(&self, node: Node<'t>) -> Option<(String, String)> { let ctor = self.constructor_signature(node)?; + // The names before the parameters: a redirecting factory names its + // target after them (`factory Foo() = _Impl.named;`). let mut cursor = ctor.walk(); let ids: Vec> = ctor .named_children(&mut cursor) + .take_while(|c| c.kind() != "formal_parameter_list") .filter(|c| c.kind() == "identifier") .collect(); let class_name = self.enclosing_type_name(node)?; @@ -448,11 +471,13 @@ impl<'t> Walker<'t> { Some(last.to_string()) } - /// isMisparsedFunction (dart.ts:177-188) — skip the UNNAMED constructor. - fn is_unnamed_ctor(&self, node: Node<'t>) -> bool { + /// isMisparsedFunction (dart.ts:177-188) — skip the UNNAMED constructor, + /// and a `const` ctor / redirecting factory that names no enclosing type + /// (error recovery's). + fn is_misparsed_function(&self, node: Node<'t>) -> bool { match self.ctor_info(node) { Some((class_name, ctor_name)) => ctor_name == class_name, - None => false, + None => is_bodiless_ctor(node.kind()), } } @@ -463,10 +488,15 @@ impl<'t> Walker<'t> { let params = sig .named_children(&mut c1) .find(|c| c.kind() == "formal_parameter_list"); + // A constructor has no return type: the type a redirecting factory + // names is its target (`= _Impl`). let mut c2 = sig.walk(); - let ret = sig - .named_children(&mut c2) - .find(|c| matches!(c.kind(), "type_identifier" | "void_type")); + let ret = if is_bodiless_ctor(sig.kind()) { + None + } else { + sig.named_children(&mut c2) + .find(|c| matches!(c.kind(), "type_identifier" | "void_type")) + }; if params.is_none() && ret.is_none() { return None; } @@ -704,7 +734,10 @@ impl<'t> Walker<'t> { self.extract_class(node); return; } - "method_signature" | "constructor_signature" => { + "method_signature" + | "constructor_signature" + | "constant_constructor_signature" + | "redirecting_factory_constructor_signature" => { self.extract_method(node); return; } @@ -753,7 +786,7 @@ impl<'t> Walker<'t> { } // isMisparsedFunction: the unnamed constructor is skipped — node // suppressed, body still walked (attributed to the current stack top). - if self.is_unnamed_ctor(node) { + if self.is_misparsed_function(node) { if let Some(body) = self.resolve_body(node) { self.visit_body(body); } @@ -800,7 +833,7 @@ impl<'t> Walker<'t> { } let name = self.extract_name(node); // isMisparsedFunction — the unnamed ctor: body-only walk. - if self.is_unnamed_ctor(node) { + if self.is_misparsed_function(node) { if let Some(body) = self.resolve_body(node) { self.visit_body(body); } @@ -1035,6 +1068,11 @@ impl<'t> Walker<'t> { if ap.kind() == "identifier" { return Some(format!("{}.{}", self.text(ap), self.text(method_id))); } + // A constructor called with type arguments names + // its type all the same (`BlocProvider.value`). + if let Some(type_name) = self.type_arguments_receiver(ap) { + return Some(format!("{}.{}", type_name, self.text(method_id))); + } // Chained static-factory: the receiver is itself // a call — re-encode `().` when // the chain starts capitalized (#750). @@ -1091,6 +1129,21 @@ impl<'t> Walker<'t> { }; } + // `=> BlocProvider.value(…)` — a constructor called + // with type arguments, as most expressions parse it. The type is the + // LAST type_identifier: an import prefix (`p.X.named`) is one too. + if node.kind() == "constructor_invocation" { + let mut c1 = node.walk(); + let type_id = node.named_children(&mut c1).filter(|c| c.kind() == "type_identifier").last(); + let mut c2 = node.walk(); + let name_id = node.named_children(&mut c2).find(|c| c.kind() == "identifier"); + return match (type_id, name_id) { + (Some(t), Some(n)) => Some(format!("{}.{}", self.text(t), self.text(n))), + (Some(t), None) => Some(self.text(t).to_string()), + _ => None, + }; + } + None } @@ -1119,6 +1172,9 @@ impl<'t> Walker<'t> { if ap.kind() == "identifier" { return Some(format!("{}.{}", self.text(ap), self.text(method_id))); } + if let Some(type_name) = self.type_arguments_receiver(ap) { + return Some(format!("{}.{}", type_name, self.text(method_id))); + } } return Some(self.text(method_id).to_string()); } @@ -1126,6 +1182,23 @@ impl<'t> Walker<'t> { None } + /// dartTypeArgumentsReceiver (dart.ts) — `BlocProvider` in + /// `BlocProvider.value(…)`, when `selector` is the `<…>` + /// between the type and `.value`. Only a constructor is called that way. + fn type_arguments_receiver(&self, selector: Node<'t>) -> Option<&'t str> { + if selector.kind() != "selector" || selector.named_child_count() != 1 { + return None; + } + if selector.named_child(0)?.kind() != "type_arguments" { + return None; + } + let type_node = selector.prev_named_sibling()?; + if type_node.kind() != "identifier" { + return None; + } + Some(self.text(type_node)) + } + // --- extractStaticMemberRef — the dart branch (:4759-4767) ------------ fn extract_static_member_ref(&mut self, node: Node<'t>) { @@ -1326,6 +1399,20 @@ impl<'t> Walker<'t> { } else { node }; + // A redirecting factory names the class it constructs after `=`, then + // perhaps that class's constructor (`= _$QuestionImpl.fromJson`, two + // type_identifiers). Neither the constructor nor an import prefix is + // a type, and Dart writes types UpperCamel. + if sig.kind() == "redirecting_factory_constructor_signature" { + let mut cursor = sig.walk(); + let kids: Vec> = sig.named_children(&mut cursor).collect(); + for child in kids { + if child.kind() != "type_identifier" || is_upper_camel(self.text(child)) { + self.type_refs_from_subtree(child, row); + } + } + return; + } self.type_refs_from_subtree(sig, row); } @@ -1354,13 +1441,7 @@ impl<'t> Walker<'t> { /// constructor call names. fn is_type_name_dart(&self, node: Node<'t>) -> bool { let text = self.text(node); - let upper = text - .trim_start_matches(&['_', '$'][..]) - .chars() - .next() - .map(|c| c.is_ascii_uppercase()) - .unwrap_or(false); - if !upper || is_builtin_type(text) { + if !is_upper_camel(text) || is_builtin_type(text) { return false; } if node.next_sibling().map(|s| s.kind() == ".").unwrap_or(false) { diff --git a/docs/design/dart-kernel-port-checklist.md b/docs/design/dart-kernel-port-checklist.md index 6048396c4d..e2575d6ef3 100644 --- a/docs/design/dart-kernel-port-checklist.md +++ b/docs/design/dart-kernel-port-checklist.md @@ -190,7 +190,9 @@ change dart's grammar, which is exactly the hazard this vendor kills. Types: functionTypes=[`function_signature`] (:119); classTypes= [`class_definition`] (:120); methodTypes=[`method_signature`, -`constructor_signature`] (:126); interfaceTypes=[] ; structTypes=[]; +`constructor_signature`, `constant_constructor_signature`, +`redirecting_factory_constructor_signature`] (:126 — the last two since +2026-10-06); interfaceTypes=[] ; structTypes=[]; enumTypes=[`enum_declaration`] (:129); enumMemberTypes=[`enum_constant`] (:130); typeAliasTypes=[`type_alias`] (:131); importTypes=[`import_or_export`] (:132); **callTypes=[] (:133 — extractCall NEVER runs for dart; all call refs @@ -237,9 +239,14 @@ Grammar-shape facts the config leans on (all probed, `mini-cst.txt` / initializers]`) — reached by the walker via plain recursion into `declaration`. `const` constructors are `declaration > constant_constructor_signature` and redirecting factories are - `declaration > redirecting_factory_constructor_signature` — **NEITHER is - in methodTypes → const ctors and `const factory X.r() = Impl;` are - INVISIBLE (no node, no refs)**. Fields are `declaration > + `declaration > redirecting_factory_constructor_signature` — both carry + NO fields (children: `const_builtin`? `"factory"`? identifier [`.` + identifier] formal_parameter_list, then for a redirect `=` and the + target: `type_identifier` [type_arguments] [`.` name], where the target + constructor's name is a `type_identifier` without type arguments and an + `identifier` after them). Until 2026-10-06 neither was in methodTypes + (no node, no refs); now both mint methods exactly like the bare + `constructor_signature` (§isMisparsedFunction, §resolveName). Fields are `declaration > (static)? (final|const|type|var) > initialized_identifier_list | static_final_declaration_list` (§Constants). - **Statements/expressions:** calls have NO call node — a postfix chain is @@ -349,7 +356,12 @@ Hooks PRESENT (port each exactly — anchors into languages/dart.ts): extension_declaration/enum_declaration and reads ITS name field) and `reduce` ≠ `Action` → treated as the method it is (pinned: `extract-probe4.txt` — method `reduce`, position starting AT `reduce`, - sig/ret undefined, decorates override intact). + sig/ret undefined, decorates override intact). dartCtorInfo reads only the + identifiers BEFORE the formal_parameter_list, so a redirecting factory's + target (`factory Foo() = _Impl.named;`) never names it. A + `constant_constructor_signature` / `redirecting_factory_constructor_signature` + that dartCtorInfo rejects (names no enclosing type — error recovery) is + skipped too: it can be nothing else. - **getSignature (:189-208)** — method_signature unwraps to function/getter/setter signature (NOT ctor/factory/operator); params = find namedChild `formal_parameter_list`; retType = find namedChild @@ -365,7 +377,9 @@ Hooks PRESENT (port each exactly — anchors into languages/dart.ts): formal_parameter_list on method_signature); **bodiless named ctor (declaration > constructor_signature) → `"()"`-style params-only sig** (node IS the ctor signature; its formal_parameter_list is found by type) — - pin BOTH ctor sig shapes; operators → undefined. + pin BOTH ctor sig shapes; operators → undefined. `const` ctors and + redirecting factories → params only too: no retType is looked up for them + (a redirect's `= _Impl` type_identifier is its target, not a return type). - **getVisibility (:209-222)** — method_signature → unwrap to function/getter/setter signature → its first `identifier` child; other nodes → childForFieldName('name'). Name starts `_` → 'private', else @@ -386,9 +400,9 @@ Hooks PRESENT (port each exactly — anchors into languages/dart.ts): children for type `'static'` → true; else false. `static WidgetT make()` → true ✓ (the `static` keyword is an anon child of method_signature); bare constructor_signature → false. Top-level functions → false. -- **resolveName (:244-260)** — dartCtorInfo: named ctor/factory → the ctor - name (`named`, `create`, `_`); unnamed ctor or non-ctor → undefined (falls - to extractName §below). +- **resolveName (:244-260)** — dartCtorInfo: named ctor/factory (`const` + and redirecting ones included) → the ctor name (`named`, `create`, `_`); + unnamed ctor or non-ctor → undefined (falls to extractName §below). - **extractImport (:261-304)** — importText = trimmed full node slice; moduleName = the URI string content: `library_import > import_specification > configurable_uri > uri > string_literal` (else the @@ -442,7 +456,7 @@ Registration: `EXTRACTORS.dart` (languages/index.ts:56), `FN_REF_SPECS.dart` | `import_or_export` | importTypes:1209 → extractImport:3170 | §Extractor config | | `new_expression` | INSTANTIATION_KINDS:1255 (`new_expression` ∈ :354-361) | extractInstantiation:4610 → ctor field lookups null → namedChild(0) = type_identifier → `instantiates` ref from stack top; `<`-strip + last-`.`-segment apply (`new p.Foo()` → `Foo`). findAnonymousClassBody → always null for dart. Children still recursed | | `function_body` (sibling of a consumed signature) | **no branch** | recursed → THE DOUBLE-WALK (§below) | -| `declaration` (fields, bodiless ctors) | no branch | recursed → constructor_signature hits methodTypes; each field `initialized_identifier` hits the hook (body-walked for the class); constant_constructor_signature, redirecting_factory_constructor_signature, initializers, annotations-in-place: nothing | +| `declaration` (fields, bodiless ctors) | no branch | recursed → constructor_signature, constant_constructor_signature and redirecting_factory_constructor_signature hit methodTypes; each field `initialized_identifier` hits the hook (body-walked for the class); initializers, annotations-in-place: nothing | | `getter_signature` / `setter_signature` BARE (top level) | no branch | **top-level getters/setters are INVISIBLE** (no node; their sibling function_body is visitNode-recursed where calls don't extract) — in classes they're method_signature-wrapped → methods | | `const_object_expression`, `selector`, `cascade_section`, `assignment_expression`, `local_variable_declaration`, patterns, `extension_type_declaration`, `part_directive`, `library_name`, lambdas | no branch | recursed; calls only extract in the BODY walker (`extractBareCall` is not consulted by visitNode!) — §Calls for the consequences | | `property_signature`/`method_signature` TS branch (:1282) | **shadowed** | method_signature is consumed at :1027 first; property_signature isn't a dart kind — branch unreachable | @@ -643,8 +657,9 @@ chain → FIRST value child only); `static final sharedInst = WidgetT(0)` → constant under the class, sig `= WidgetT`; multi-declarations → one node each with own columns. **NO nodes ever**: instance fields (typed/untyped/ late/var), `static var`, top-level var/typed vars, top-level getters/ -setters, const constructors, redirecting factories, extension_type -containers, `part`/`part of`/`library`/deferred imports. **Initializers +setters, extension_type containers, `part`/`part of`/`library`/deferred +imports. (Named `const` constructors and redirecting factories mint +methods since 2026-10-06; the unnamed ones still mint nothing.) **Initializers are code:** every initializer is walked with the body walker — a constant's for the constant (riverpod's `final repoProvider = Provider((ref) => Repository(ref.watch(dioProvider)));` → calls @@ -682,7 +697,9 @@ extract-mini.txt): | `w?.render()` | conditional_assignable_selector | `w.render` — **`?.` is encoded exactly like `.`** | | `y2..add(1)..add(2)` (cascades) | cascade_section (argument_part NOT inside a selector) | **NOTHING — cascade calls are completely invisible** | | `new WidgetT(2)` | new_expression → INSTANTIATION branch :5145 FIRST | `instantiates WidgetT` (extractBareCall's new_expression arm :363-367 is DEAD — the else-if never reaches it); args still recursed | -| `pad(const EdgeInsetsT.all(8.0))` | const_object_expression :369-376 | `EdgeInsetsT.all` at the CONST node position (typeId + '.' + nameId; type-only form → `EdgeInsetsT`); children recursed after | +| `pad(const EdgeInsetsT.all(8.0))` | const_object_expression :369-376 | `EdgeInsetsT.all` at the CONST node position (typeId + '.' + nameId; type-only form → `EdgeInsetsT`); children recursed after. The FIRST type_identifier: `const p.X.named()` → `p.named` (prefix bug, preserved) | +| `BlocProviderT.value(…);` as a statement | args selector; prev = `.value` selector; accessorPrev = a selector holding only `type_arguments`, whose prev is the identifier | `BlocProviderT.value` (dartTypeArgumentsReceiver, since 2026-10-06 — bare `value` before); the `.value().tail` re-encode reads it the same way | +| `=> BlocProviderT.value(…)`, and as an initializer, argument or `return` value | `constructor_invocation` (type_identifier [`.` type_identifier] type_arguments `.` identifier arguments) | `BlocProviderT.value` at the node position — the LAST type_identifier, so `p.X.named()` → `X.named` (since 2026-10-06; nothing before) | | `generic(5)` | args selector (type args ride argument_part) | bare `generic` | | `await fetch()` | recursion through unary/await_expression | `fetch` at the selector | | `throw StateError('bad')` | recursion | `StateError` | @@ -746,7 +763,12 @@ BUILTIN_TYPES (:5768-5782), at each leaf's position. Consequences (pinned): = constructor_signature → param types emit (`Widget.named(WidgetT w)` → references WidgetT); `this.`-params (constructor_param) hold no type_identifier → nothing. Bodiless declaration-wrapped ctors: extractMethod - runs on the bare constructor_signature → sig = node → same. + runs on the bare constructor_signature → sig = node → same; so do `const` + ctors. A redirecting factory walks its named children one by one and + skips a DIRECT type_identifier that is not UpperCamel (`/^[_$]*[A-Z]/`): + after `=` those are an import prefix (`= p.Impl`) or the target + constructor's name (`= _$QuestionImpl.fromJson`, where `fromJson` is a + type_identifier) — `references _$QuestionImpl` only. - Getters: references from the getter's TYPE (suppressed if builtin — `int get area` → nothing; `WidgetT get w` → references WidgetT). - extractVariableTypeAnnotation (:6074) needs a `type_annotation` child — diff --git a/src/extraction/languages/dart.ts b/src/extraction/languages/dart.ts index ad5b8c4bd0..fdac302a78 100644 --- a/src/extraction/languages/dart.ts +++ b/src/extraction/languages/dart.ts @@ -100,6 +100,16 @@ function dartInnerSignature(node: SyntaxNode): SyntaxNode { return node; } +/** + * The constructors that never have a body — `const Foo.bar();` and a + * redirecting factory `const factory Foo.bar() = _Bar;` — each parse as a + * signature kind of its own, inside a `declaration`. + */ +const DART_BODILESS_CTORS: ReadonlySet = new Set([ + 'constant_constructor_signature', + 'redirecting_factory_constructor_signature', +]); + /** * The factory/named-constructor signature inside a node, if any. A constructor * parses as `method_signature > {factory_,}constructor_signature` (e.g. @@ -107,7 +117,10 @@ function dartInnerSignature(node: SyntaxNode): SyntaxNode { * and — for a named ctor — the constructor-name identifier. */ function dartConstructorSignature(node: SyntaxNode): SyntaxNode | undefined { - if (node.type === 'factory_constructor_signature' || node.type === 'constructor_signature') { + if ( + node.type === 'factory_constructor_signature' || node.type === 'constructor_signature' || + DART_BODILESS_CTORS.has(node.type) + ) { return node; } if (node.type === 'method_signature') { @@ -146,7 +159,13 @@ function dartEnclosingTypeName(node: SyntaxNode): string | undefined { function dartCtorInfo(node: SyntaxNode): { className: string; ctorName: string } | undefined { const ctor = dartConstructorSignature(node); if (!ctor) return undefined; - const ids = ctor.namedChildren.filter((c: SyntaxNode) => c.type === 'identifier'); + // The names before the parameters: a redirecting factory names its target + // after them (`factory Foo() = _Impl.named;`). + const ids: SyntaxNode[] = []; + for (const c of ctor.namedChildren) { + if (c.type === 'formal_parameter_list') break; + if (c.type === 'identifier') ids.push(c); + } const className = dartEnclosingTypeName(node); if (!className || !ids[0]) return undefined; if (ids[0].text !== className) return undefined; // misparsed method, not a ctor @@ -176,6 +195,19 @@ function extractDartReturnType(node: SyntaxNode, source: string): string | undef return last; } +/** + * The type a call written with type arguments goes through — `BlocProvider` + * in `BlocProvider.value(…)`, when `selector` is the `<…>` + * between the type and `.value`. Only a constructor is called that way. + */ +function dartTypeArgumentsReceiver(selector: SyntaxNode | null): string | undefined { + if (selector?.type !== 'selector' || selector.namedChildCount !== 1 || selector.namedChild(0)?.type !== 'type_arguments') { + return undefined; + } + const type = selector.previousNamedSibling; + return type?.type === 'identifier' ? type.text : undefined; +} + /** * The callee name of the Dart call whose `argument_part` selector is `argPart` * — mirrors the main extractBareCall accessor logic so a chained receiver @@ -194,6 +226,8 @@ function dartCalleeOfArgPart(argPart: SyntaxNode): string | undefined { if (methodId) { const accessorPrev = prev.previousNamedSibling; if (accessorPrev?.type === 'identifier') return accessorPrev.text + '.' + methodId.text; + const typeName = dartTypeArgumentsReceiver(accessorPrev); + if (typeName) return typeName + '.' + methodId.text; return methodId.text; } } @@ -208,7 +242,11 @@ export const dartExtractor: LanguageExtractor = { // constructor `Foo._()` parses as a bare `constructor_signature`, so include // it too — resolveName names it by the ctor name and getReturnType gives it // the class as its return type, so `Foo._().bar()` chains resolve (#750). - methodTypes: ['method_signature', 'constructor_signature'], + // `const` constructors and redirecting factories have signature kinds of + // their own: flutter_bloc's `const BlocProvider.value(…)` is one, and + // without its node a `BlocProvider.value(…)` call went to another class's + // `value`. + methodTypes: ['method_signature', 'constructor_signature', ...DART_BODILESS_CTORS], interfaceTypes: [], structTypes: [], enumTypes: ['enum_declaration'], @@ -314,7 +352,10 @@ export const dartExtractor: LanguageExtractor = { // tree-sitter misparsed as a ctor (`@override (T) m()`) is NOT skipped here. // (isMisparsedFunction skips node creation but still visits the body.) const ctor = dartCtorInfo(node); - return ctor != null && ctor.ctorName === ctor.className; + // A `const` constructor or redirecting factory is nothing else, so one + // that names no enclosing type is error recovery's, and skipped. + if (!ctor) return DART_BODILESS_CTORS.has(node.type); + return ctor.ctorName === ctor.className; }, getSignature: (node, source) => { // For function_signature: extract params + return type @@ -327,7 +368,9 @@ export const dartExtractor: LanguageExtractor = { if (inner) sig = inner; } const params = sig.namedChildren.find((c: SyntaxNode) => c.type === 'formal_parameter_list'); - const retType = sig.namedChildren.find((c: SyntaxNode) => + // A constructor has no return type: the type a redirecting factory names + // is its target (`= _Impl`). + const retType = DART_BODILESS_CTORS.has(sig.type) ? undefined : sig.namedChildren.find((c: SyntaxNode) => c.type === 'type_identifier' || c.type === 'void_type' ); if (!params && !retType) return undefined; @@ -467,6 +510,10 @@ export const dartExtractor: LanguageExtractor = { if (accessorPrev?.type === 'identifier') { return accessorPrev.text + '.' + methodId.text; } + // A constructor called with type arguments names its type all the + // same: `BlocProvider.value(…)` → `BlocProvider.value`. + const typeName = dartTypeArgumentsReceiver(accessorPrev); + if (typeName) return typeName + '.' + methodId.text; // Chained static-factory / fluent call: the receiver is itself a call // (`Foo.create().bar()`), so accessorPrev is that call's argument_part // selector. Encode `().` so resolution can infer @@ -512,6 +559,17 @@ export const dartExtractor: LanguageExtractor = { return undefined; } + // `=> BlocProvider.value(…)` — a constructor called with type + // arguments, as most expressions parse it. The type is the last + // `type_identifier`: an import prefix (`p.X.named`) is one too. + if (node.type === 'constructor_invocation') { + const typeId = node.namedChildren.filter((c: SyntaxNode) => c.type === 'type_identifier').pop(); + const nameId = node.namedChildren.find((c: SyntaxNode) => c.type === 'identifier'); + if (typeId && nameId) return typeId.text + '.' + nameId.text; + if (typeId) return typeId.text; + return undefined; + } + return undefined; }, extractMemberRead: dartMemberRead, diff --git a/src/extraction/tree-sitter.ts b/src/extraction/tree-sitter.ts index 893fd07aab..8019b3af14 100644 --- a/src/extraction/tree-sitter.ts +++ b/src/extraction/tree-sitter.ts @@ -7280,6 +7280,18 @@ export class TreeSitterExtractor { c.type === 'factory_constructor_signature' ) ?? node; } + // A redirecting factory names the class it constructs after `=`, then + // perhaps that class's constructor (`= _$QuestionImpl.fromJson`, which + // parses as two type_identifiers). Neither the constructor nor an import + // prefix is a type, and Dart writes types UpperCamel. + if (sig.type === 'redirecting_factory_constructor_signature') { + for (const child of sig.namedChildren) { + if (child.type !== 'type_identifier' || /^[_$]*[A-Z]/.test(child.text)) { + this.extractTypeRefsFromSubtree(child, nodeId); + } + } + return; + } this.extractTypeRefsFromSubtree(sig, nodeId); return; } diff --git a/src/resolution/name-matcher.ts b/src/resolution/name-matcher.ts index b4c13838a6..5668a53482 100644 --- a/src/resolution/name-matcher.ts +++ b/src/resolution/name-matcher.ts @@ -1106,7 +1106,9 @@ export function matchFunctionRef( // defines inside `test_custom_auth`. Those still count against a lone // cross-file guess below — a name several functions use for themselves is // as likely a local's. - let candidates = named.filter((n) => isLexicallyReachable(n, ref, context)); + let candidates = named.filter((n) => isLexicallyReachable(n, ref, context) && + // A Dart constructor is torn off through its class, never by a bare name. + !isDartConstructor(n, context)); if (candidates.length === 0) return null; // A Python name the function around it binds — a parameter, an assignment — // is that local's value: httpx's `auth_flow(self, request)` handing `request` @@ -2866,6 +2868,32 @@ function isDartMethodInScope(method: Node, ref: UnresolvedRef, context: Resoluti return dartMemberDepth(method, ref, context) < Infinity; } +const DART_CONSTRUCTORS = new WeakMap>(); + +/** + * Whether a Dart method is a named constructor — `Foo.named(…)`, `factory + * Foo.of(…)`, `const Foo.value(…)`, `const factory Foo.x() = _X;` — read from + * its declaration. Dart reaches one only through its class (`Foo.value(…)`, + * the tear-off `Foo.value`), never by a bare name: a parameter `value` passed + * on is not `const BlocProvider.value(…)`. + */ +function isDartConstructor(n: Node, context: ResolutionContext): boolean { + if (n.language !== 'dart' || n.kind !== 'method') return false; + let memo = DART_CONSTRUCTORS.get(context); + if (!memo) DART_CONSTRUCTORS.set(context, (memo = new Map())); + const hit = memo.get(n.id); + if (hit !== undefined) return hit; + const cut = n.qualifiedName.lastIndexOf('::'); + const owner = cut > 0 ? n.qualifiedName.slice(0, cut).split('::').pop()! : ''; + const lines = context.getFileLines?.(n.filePath) ?? context.readFile(n.filePath)?.split(/\r?\n/) ?? []; + const head = (lines[n.startLine - 1] ?? '').slice(n.startColumn); + const escape = (name: string): string => name.replace(/\$/g, '\\$'); + const constructor = owner !== '' && + new RegExp(String.raw`^(?:(?:const|factory|external)\s+)*${escape(owner)}\s*\.\s*${escape(n.name)}(?![\w$])`).test(head); + memo.set(n.id, constructor); + return constructor; +} + /** * How many supertype steps separate the class a Dart call is written in from * `method`'s owner: 0 for its own member, Infinity when the owner is not in @@ -3461,25 +3489,21 @@ function dartStaticMember(typeName: string, name: string, ref: UnresolvedRef, co const found = context.getNodesByName(name).filter((m) => m.language === 'dart' && (m.kind === 'method' || m.kind === 'function' || m.kind === 'constant' || m.kind === 'enum_member') && owners.some((o) => o.filePath === m.filePath && m.qualifiedName === `${o.qualifiedName}::${name}`) && - !isDartSetter(m, context) && isDartStaticMember(m, typeName, context)); + !isDartSetter(m, context) && isDartStaticMember(m, context)); if (found.length <= 1) return found[0] ?? null; return found.find((m) => m.filePath === ref.filePath) ?? found.reduce((a, b) => (computePathProximity(ref.filePath, b.filePath) > computePathProximity(ref.filePath, a.filePath) ? b : a)); } /** - * Whether a member of the Dart type `owner` is reached through the type - * itself: a static member, constant or enum value, or a named constructor or - * factory (`factory ProviderContainer.test(…)`) — not an instance member - * sharing a constructor's name (`AsyncValue`'s `error` getter beside its - * `AsyncValue.error(…)` factory). + * Whether a member of a Dart type is reached through the type itself: a + * static member, constant or enum value, or a named constructor or factory + * (`factory ProviderContainer.test(…)`) — not an instance member sharing a + * constructor's name (`AsyncValue`'s `error` getter beside its + * `AsyncValue.error(…)` factory, even declared on the line above it). */ -function isDartStaticMember(m: Node, owner: string, context: ResolutionContext): boolean { - if (m.isStatic || m.kind === 'constant' || m.kind === 'enum_member') return true; - const lines = context.getFileLines?.(m.filePath) ?? context.readFile(m.filePath)?.split(/\r?\n/) ?? []; - const head = `${(lines[m.startLine - 1] ?? '').slice(m.startColumn)} ${lines[m.startLine] ?? ''} ${lines[m.startLine + 1] ?? ''}`; - const esc = (s: string): string => s.replace(/\$/g, '\\$'); - return new RegExp(`(?:^|[^\\w$.])${esc(owner)}\\s*\\.\\s*${esc(m.name)}\\s*[(<]`).test(head); +function isDartStaticMember(m: Node, context: ResolutionContext): boolean { + return m.isStatic === true || m.kind === 'constant' || m.kind === 'enum_member' || isDartConstructor(m, context); } /** @@ -3969,6 +3993,31 @@ function dartExtensionMemberOf(typeName: string, name: string, ref: UnresolvedRe return found?.viaExtension ? found.node : null; } +/** + * A Dart call through a type's name — `BlocProvider.value(…)`, riverpod's + * `FutureProvider.autoDispose(…)` — is to one of that type's own constructors + * or static members, or to nothing the project declares. Dart inherits none + * of them, so a guess past the type is always wrong: flutter_bloc's + * `BlocProvider.value(…)` went to `RepositoryProvider`'s `value` 89 times, + * riverpod's `Family2Family._()` to the `EmptyFamily2Family._` declared above + * it, and the SDK's `Uri.parse(…)`, past bloc_lint's `extension on Uri`, to a + * project `parse`. A static constant's callee is the value it holds (`static + * const autoDispose = AutoDisposeFutureProviderBuilder();`). The member is + * found as a chain's static link finds it (dartStaticMember). Undefined when + * the receiver names no Dart type of the project. + */ +function matchDartTypeMemberCall( + typeName: string, + member: string, + ref: UnresolvedRef, + context: ResolutionContext, +): ResolvedRef | null | undefined { + if (!context.getNodesByName(typeName).some((n) => n.language === 'dart' && DART_TYPE_KINDS.has(n.kind))) return undefined; + const own = dartStaticMember(typeName, member, ref, context); + return own && own.kind !== 'enum_member' + ? { original: ref, targetNodeId: own.id, confidence: 0.85, resolvedBy: 'qualified-name' } : null; +} + /** * How a bare Rust or Go name is written at its call: `path` after `::` (left * to the path strategies), `chained` after a `.` — with the receiver it is @@ -6683,6 +6732,11 @@ export function matchByExactName( !isKotlinNumberBitwise(n, ref) && !(solidityBare && !isSolidityMemberInScope(n, ref, context)) && !(dartBare && isDartMember(n) && !isDartMethodInScope(n, ref, context)) && + // A Dart constructor is reached through its class (`Foo.named(…)`, + // `@Foo.named(…)`), never by its name alone: not a bare call, not the + // last link of a chain, not an annotation (riverpod's 210 `@internal` + // annotations went to its providers' `internal` constructors). + !(ref.language === 'dart' && isDartConstructor(n, context)) && !(phpSelf && (n.kind !== 'method' || !isPhpMethodInScope(n, ref, phpSelf, context))) && !(pythonShape && !fitsPythonCallShape(n, pythonShape, ref, context)) && !(rustBare && !isRustNameInScope(n, ref, context)) && @@ -8387,6 +8441,7 @@ export function clearNameMatcherMemos(context: ResolutionContext): void { DART_LINEAGES.delete(context); DART_EXTENSION_OWNERS.delete(context); DART_GETTERS.delete(context); + DART_CONSTRUCTORS.delete(context); DART_SETTERS.delete(context); DART_CODE.delete(context); DART_RETURN_TYPES.delete(context); @@ -9514,6 +9569,13 @@ export function matchMethodCall( // receiver type we can try to infer from its local declaration. const inferableReceiver = dotMatch || luaColonMatch || rDollarMatch; + // A Dart call through a type's name is to that type's own member, or to + // nothing in the project. + if (ref.language === 'dart' && dotMatch) { + const typeMember = nmTimedT('mc-darttype', ref, () => matchDartTypeMemberCall(objectOrClass!, methodName!, ref, context)); + if (typeMember !== undefined) return typeMember; + } + // Infer the receiver's type from its local declaration/initializer in the // enclosing scope, then resolve the method on that type (#1108). C++ keeps its // dedicated inferrer (header scan + `auto`); every other language uses the @@ -9739,24 +9801,6 @@ export function matchMethodCall( if (classNode.language !== ref.language) continue; const nodesInFile = context.getNodesInFile(classNode.filePath); - // Dart: a call through a type's static constant invokes the value the - // constant holds. riverpod's `FutureProvider.autoDispose(…)` calls - // `static const autoDispose = AutoDisposeFutureProviderBuilder();`, - // which the lookups below gave to another builder's `autoDispose` - // method. A Dart type can't also declare a method of that name, and its - // static members are not inherited, so its own constant is the callee. - if (ref.language === 'dart') { - const holder = nodesInFile.find((n) => - n.kind === 'constant' && n.name === methodName && n.qualifiedName === `${classNode.qualifiedName}::${methodName}`); - if (holder) { - return { - original: ref, - targetNodeId: holder.id, - confidence: 0.85, - resolvedBy: 'qualified-name', - }; - } - } const methodNode = nodesInFile.find( (n) => n.kind === 'method' && @@ -11480,6 +11524,7 @@ export function matchFuzzy( !(pythonShape && !fitsPythonCallShape(n, pythonShape, ref, context)) && !(javaBare && n.kind === 'method' && !isJavaMethodInScope(n, ref, context)) && !(dartBare && isDartMember(n) && !isDartMethodInScope(n, ref, context)) && + !(ref.language === 'dart' && isDartConstructor(n, context)) && !(kotlinCall && !isKotlinTopLevelVisible(n, ref, context)) && !(kotlinBare && !isKotlinMemberReachable(n, ref, context)) && !isKotlinNumberBitwise(n, ref) && From 3f96f80fcb702a96c893ffefcfa3007a64d061e4 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 14:57:23 +0000 Subject: [PATCH 09/23] fix(dart): link generic calls the parser reads as two comparisons (#2375) tree-sitter-dart parses a generic call with arguments as two comparisons about as often as it parses it as a call, depending on the code around it: `ref.read(p)` comes out as `relational_expression(relational_expression(ref.read < Repo) > (p))`. Generic constructors (`Provider((ref) => 0)`), named arguments (which then parse as a `record_literal`) and calls after `await` or a prefix operator are hit too. Neither extractor recorded a call for that shape, only a member read of `ref.read` that linked nothing, so providers, repository reads and bloc lookups written with a type argument had no callers. Across felangel/bloc, rrousselGit/riverpod and flutter/samples there are 2,853 such calls, against 2,836 generic calls with arguments that parse as calls. - Both extractors (the TS walker and the native kernel) recover the call at its `<` when the type argument names a type and the code is laid out as a call: `<` against the callee and `(` against the `>`. A comparison such as `a < b` is left alone. The recovered call gets what a parsed one does: the call at the `<`, a reference to the type argument, and no member read of the callee or of a prefixed type argument. - A call chained on a recovered call keeps its bare name. The `BlocProvider.of().increment` encoding a parsed chain gets resolves through what `of` returns, which for a generic factory is its type parameter, so it would drop the edge the bare name finds. - When the grammar ends an arrow function in front of a generic call (`(ref) => ref.watch(p)` as `((ref) => ref).watch(p)`), the receiver is read from the end of the arrow's body, so the call is `ref.watch` rather than a bare `watch`. Validated with the kernel loaded: bloc +85, riverpod +1,580 and flutter/samples +54 edges, none lost; kernel/wasm parity has 0 diffs on all three repos. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/dart-generic-calls.test.ts | 219 +++++++++++++ .../kernel-parity/TortureGenericCalls.dart | 62 ++++ __tests__/kernel-dart-parity.test.ts | 8 +- codegraph-kernel/src/dart.rs | 290 ++++++++++++++---- docs/design/dart-kernel-port-checklist.md | 41 +++ src/extraction/languages/dart.ts | 235 ++++++++++---- src/extraction/tree-sitter-types.ts | 5 +- src/extraction/tree-sitter.ts | 30 +- 9 files changed, 764 insertions(+), 127 deletions(-) create mode 100644 __tests__/dart-generic-calls.test.ts create mode 100644 __tests__/fixtures/kernel-parity/TortureGenericCalls.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e6a11232f..16d4ed8d34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In JavaScript and TypeScript, an import whose name contains a `$`, like `import items$ from './store'`, `import * as api$ from './api'` or `import { load as load$ } from './data'`, now links the calls made through it, such as `items$.getState().inc()`, to the code it imports, and so does a `$` name in a `require(…)` destructuring or an `export { … } from` barrel. Before, such an import was skipped or bound under a cut-off name (`load` for `load$`), so those calls reached nothing and the functions they call could look unused. A local variable or parameter that reuses an imported `$` name, like `const items$ = …` inside a function, is no longer mistaken for the import. Re-index JavaScript and TypeScript projects after upgrading. - In Dart, calling a parameter or a local variable, like `create(ref, arg)` inside `overrideWith(… create)`, a closure's parameter, a loop variable or a test's mock `listener(0, 1)`, no longer links the call to an unrelated function or constant of the same name in another file, or to a method the class inherits: a Bloc event handler's `emit(…)` is the handler's own `emit` parameter, not `Bloc.emit`. So `codegraph callers` and impact no longer list code that never calls them, while calls the parameter or variable doesn't cover, and calls to a local function, link as before. Re-index Dart projects after upgrading. - In Dart, `const` constructors and redirecting factories, like flutter_bloc's `const BlocProvider.value(…)` or freezed's `const factory LoginState.loading() = _Loading;`, are now indexed, so a call such as `BlocProvider.value(…)` or `BlocProvider.value(…)` links to that constructor instead of another class's member with the same name. A call through a class name now reaches only that class's own constructors and static members, never a look-alike class, a parent class, an instance getter of the same name, or a project method that merely shares its name with an SDK call like `Uri.parse(…)`, and a constructor is no longer linked from a bare name, the end of a call chain or an annotation like `@internal`. Re-index Dart projects after upgrading. +- In Dart, a call that passes a type argument and arguments, like `ref.read(repoProvider)`, `ref.watch(counterProvider)`, `Provider((ref) => …)`, `BlocProvider.of(context)` or `RepositoryProvider(create: …)`, now links to the method or class it calls, and the type it passes counts as used there. Depending on the code around it, the parser often read such a call as two comparisons, so it linked nothing, and Riverpod providers, repository reads and bloc lookups were missing from `callers`, impact and `codegraph_explore`. A real comparison like `a < b` is still left alone. Re-index Dart projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/dart-generic-calls.test.ts b/__tests__/dart-generic-calls.test.ts new file mode 100644 index 0000000000..d106b07748 --- /dev/null +++ b/__tests__/dart-generic-calls.test.ts @@ -0,0 +1,219 @@ +/** + * Dart generic calls that tree-sitter-dart parses as two comparisons. + * + * `ref.read(repoProvider)` comes out of the grammar as + * `(ref.read < Repo) > (repoProvider)`, a relational expression inside + * another, about as often as it comes out as a call: which one depends on the + * code around it. `Provider((ref) => 0)`, `int g(Ref ref) => + * ref.read(1);`, `RepositoryProvider(create: …)` (named arguments + * parse as a record) and `await users.fetch(1)` all can. Neither + * extractor recorded a call for that shape, only a member read of `ref.read` + * that links nothing, so providers, repository reads and bloc lookups written + * with a type argument had no callers. `context.read()`, with + * empty arguments, parses as a call and always worked. + * + * The nest is the call when its type argument names a type and it is laid + * out as a call is, `<` against the callee and `(` against the `>`; a + * comparison is written `a < b`. + * + * Runs against the native kernel (when built) and the wasm extractor, which + * must agree. + */ +import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; +import { extractFromSource } from '../src/extraction'; +import { initGrammars, loadGrammarsForLanguages } from '../src/extraction/grammars'; +import type { Node } from '../src/types'; + +const BACKENDS = ['default', 'wasm'] as const; + +let kernel: string | undefined; + +function useBackend(backend: (typeof BACKENDS)[number]): void { + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; +} + +beforeEach(() => { + kernel = process.env.CODEGRAPH_KERNEL; +}); + +afterEach(() => { + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; +}); + +describe('Dart generic calls parsed as comparisons: extraction', () => { + beforeAll(async () => { + await initGrammars(); + await loadGrammarsForLanguages(['dart']); + }); + + const SOURCE = [ + 'int g(Ref ref) => ref.read(1);', + '', + 'void f(Ref ref) {', + ' final a = ref.watch(p);', + ' ref.read(repoProvider);', + ' print(ref.watch(p) + 1);', + ' final b = a < B > (c);', + ' final d = a(c);', + '}', + '', + ].join('\n'); + + it.each(BACKENDS)('records the call a parsed one gets, at its `<` (%s)', (backend) => { + useBackend(backend); + const result = extractFromSource('lib/providers.dart', SOURCE, 'dart'); + const names = new Map(result.nodes.map((n) => [n.id, n.name])); + const refs = result.unresolvedReferences + .filter((r) => r.referenceKind === 'calls' || r.referenceKind === 'references') + .map((r) => `${names.get(r.fromNodeId)} ${r.referenceKind} ${r.referenceName} ${r.line}:${r.column}`) + .sort(); + + expect(refs).toEqual([ + 'f calls print 6:7', + // Line 6 parses as a call: what the recovered calls must look like. + 'f calls ref.read 5:10', + 'f calls ref.watch 4:21', + 'f calls ref.watch 6:17', + 'f references Ref 3:7', + // The type argument is referenced as a parsed one is; `int` is built in. + 'f references Repo 5:11', + 'g calls ref.read 1:26', + 'g references Ref 1:6', + ]); + // No member read of `ref.read` / `ref.watch`, and the comparisons on + // lines 7 and 8 stay comparisons. + }); +}); + +describe('Dart generic calls parsed as comparisons: graph', () => { + const FILES: Record = { + 'pubspec.yaml': 'name: app\nenvironment:\n sdk: ">=3.0.0 <4.0.0"\n', + 'lib/riverpod.dart': `class Ref { + T watch(Object provider) => throw 0; + T read(Object provider) => throw 0; +} + +class Provider { + Provider(T Function(Ref ref) create); +} +`, + 'lib/data.dart': `class User {} + +class Repo { + Repo(); +} + +class UserRepository { + Future fetch(int id) => throw 0; +} +`, + 'lib/bloc.dart': `class BuildContext {} + +class BlocProvider { + static T of(BuildContext context) => throw 0; +} + +class CounterCubit { + void increment() {} +} + +class RepositoryProvider { + RepositoryProvider({required T Function(BuildContext context) create}); +} +`, + // Every call below parses as two comparisons. + 'lib/app.dart': `import 'bloc.dart'; +import 'data.dart'; +import 'riverpod.dart'; + +final seedProvider = Provider((ref) => 0); +final repoProvider = Provider((ref) => Repo()); +final countProvider = Provider((Ref ref) => ref.watch(seedProvider)); + +int g(Ref ref) => ref.read(countProvider); + +Repo readRepo(Ref ref) { + final repo = ref.read(repoProvider); + return repo; +} + +Future loadUser(UserRepository users) async { + final user = await users.fetch(1); + return user; +} + +void tap(BuildContext context) { + BlocProvider.of(context).increment(); +} + +Object provide() => RepositoryProvider(create: (_) => Repo()); + +bool compare(int a, int b, int c) { + final spaced = a < b > (c); + final lower = a(c); + return spaced && lower; +} +`, + }; + + let root = ''; + let cg: CodeGraph | undefined; + + beforeEach(() => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-generic-calls-')); + for (const [rel, content] of Object.entries(FILES)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + }); + + afterEach(() => { + cg?.close(); + cg = undefined; + fs.rmSync(root, { recursive: true, force: true }); + }); + + it.each(BACKENDS)('link the calls, constructions and type arguments (%s)', async (backend) => { + useBackend(backend); + cg = await CodeGraph.init(root, { index: true }); + const graph = cg; + const node = (qualifiedName: string): Node => { + const found = graph.getNodesInFile('lib/app.dart').find((n) => n.qualifiedName === qualifiedName); + expect(found, qualifiedName).toBeDefined(); + return found!; + }; + const targets = (from: string, kind: string): string[] => + [...new Set(graph + .getOutgoingEdgesFrom([node(from).id]) + .filter((e) => e.kind === kind) + .map((e) => graph.getNode(e.target)!.qualifiedName))] + .sort(); + + // The issue's shapes: a typed receiver's method, through `=>` and a block. + expect(targets('g', 'calls')).toEqual(['Ref::read']); + expect(targets('readRepo', 'calls')).toEqual(['Ref::read']); + expect(targets('readRepo', 'references')).toContain('Repo'); + + // Riverpod providers built with a type argument construct their provider, + // and a typed closure parameter still types the call written in it. + expect(targets('seedProvider', 'instantiates')).toEqual(['Provider']); + expect(targets('repoProvider', 'instantiates')).toEqual(['Provider', 'Repo']); + expect(targets('countProvider', 'instantiates')).toEqual(['Provider']); + expect(targets('countProvider', 'calls')).toEqual(['Ref::watch']); + + // After `await`, with named arguments, and through a static method. + expect(targets('loadUser', 'calls')).toEqual(['UserRepository::fetch']); + expect(targets('provide', 'instantiates')).toEqual(['Repo', 'RepositoryProvider']); + expect(targets('tap', 'calls')).toEqual(['BlocProvider::of', 'CounterCubit::increment']); + expect(targets('tap', 'references')).toContain('CounterCubit'); + + // Comparisons are not calls. + expect(targets('compare', 'calls')).toEqual([]); + }); +}); diff --git a/__tests__/fixtures/kernel-parity/TortureGenericCalls.dart b/__tests__/fixtures/kernel-parity/TortureGenericCalls.dart new file mode 100644 index 0000000000..7c09f1b981 --- /dev/null +++ b/__tests__/fixtures/kernel-parity/TortureGenericCalls.dart @@ -0,0 +1,62 @@ +// Generic calls tree-sitter-dart parses as two comparisons — `ref.read(p)` +// comes out as `(ref.read < Repo) > (p)` — recovered as calls, and the +// comparisons that look like them. +import 'package:app/app.dart' as p; + +// Initializers: a constant's, a top-level variable's, a field's. +final counterProvider = Provider((ref) => ref.watch(seedProvider)); +final repoProvider = Provider((ref) { + final dio = ref.read(dioProvider); + return Repo(dio); +}); +var cache = Cache(capacity: 10); +final routes = [MaterialPageRoute(builder: (_) => const Home())]; + +int g(Ref ref) => ref.read(1); + +class Screen { + final notifier = ValueNotifier(0); + static final route = MaterialPageRoute(builder: (_) => const Screen()); + static var shared = Notifier(repoProvider); + + const Screen(); + + Future load(Ref ref, BuildContext context) async { + ref.read(repoProvider); + final user = await ref.read(userRepoProvider).fetch(id); + final map = ref.read>(mapProvider); + final prefixed = ref.read(repoProvider); + final generic = ref.read>(boxProvider); + BlocProvider.of(context).increment(); + final state = BlocProvider.of(context).state; + final neg = -ref.read(countProvider); + final not = !ref.read(flagProvider); + final nested = Wrapper(Inner(seed)); + final bare = build(seed); + final dyn = await box.openBox('box'); + final chained = Factory.create(seed).build(); + final lower = repo.items.where(isDone).toList(); + final self = this.read(repoProvider); + final cascade = Builder(seed)..name = 'x'; + final templ = '${ref.read(repoProvider)}'; + final sum = ref.watch(countProvider) + 1; + return show(context: context, builder: (_) => const Screen()); + } + + void outer(Ref ref) { + int inner() => ref.watch(innerProvider); + final cb = () => navigator.push(any()); + inner(); + } + + bool compare(int a, int b, int c, int d) { + // Comparisons, not calls. + final spaced = a < B > (c); + final lower = a(c); + final left = a (c); + final right = a (c); + final expr = a < b + 1 > (c); + final record = a<(B, C)>(d); + return a < b && c > d; + } +} diff --git a/__tests__/kernel-dart-parity.test.ts b/__tests__/kernel-dart-parity.test.ts index 7943d34778..c6b2487750 100644 --- a/__tests__/kernel-dart-parity.test.ts +++ b/__tests__/kernel-dart-parity.test.ts @@ -27,7 +27,9 @@ * second variable left to its function; TortureConstCtors.dart: `const` * constructors and redirecting factories as methods with the unnamed ones * skipped, every redirect-target form, and constructors called with type - * arguments, as statements and as expressions) and their CRLF variants + * arguments, as statements and as expressions; TortureGenericCalls.dart: + * generic calls parsed as two comparisons, recovered as calls) and their CRLF + * variants * (derived in-memory — #1329), plus defer and generated-file pins. * * The full-repo sweeps live in scripts/kernel-parity.mjs (shelf/bloc/flutter @@ -129,6 +131,10 @@ describe.skipIf(!kernelBuilt)('kernel Dart extraction parity', () => { // ones skipped), every redirect-target form, and constructors called // with type arguments in statements and expressions. ['TortureConstCtors.dart', 20], + // Generic calls the grammar parses as two comparisons (`ref.read(p)` + // as `(ref.read < Repo) > (p)`): every callee, type-argument and argument + // shape, in bodies and initializers, and the comparisons that look alike. + ['TortureGenericCalls.dart', 10], ] as const; for (const [file, minNodes] of FIXTURES) { diff --git a/codegraph-kernel/src/dart.rs b/codegraph-kernel/src/dart.rs index 458ecc5c44..116414fc65 100644 --- a/codegraph-kernel/src/dart.rs +++ b/codegraph-kernel/src/dart.rs @@ -108,6 +108,18 @@ fn is_bodiless_ctor(kind: &str) -> bool { matches!(kind, "constant_constructor_signature" | "redirecting_factory_constructor_signature") } +/// DART_LOWERCASE_TYPES (dart.ts) — Dart's lowercase built-in types, which a +/// type argument can name: ``, ``. +fn is_lowercase_type(name: &str) -> bool { + matches!(name, "int" | "double" | "num" | "bool" | "dynamic" | "void") +} + +/// DART_PREFIXED (dart.ts) — what a callee can sit under in front of a +/// generic call: `await`, `-`, `!`. +fn is_prefixed(kind: &str) -> bool { + matches!(kind, "unary_expression" | "await_expression") +} + struct Scope { row: u32, kind: &'static str, @@ -1048,61 +1060,15 @@ impl<'t> Walker<'t> { return None; } let prev = node.prev_named_sibling()?; - if prev.kind() == "identifier" { - return Some(self.text(prev).to_string()); - } - if prev.kind() == "selector" { - let mut pc = prev.walk(); - let accessor = prev.named_children(&mut pc).find(|c| { - matches!( - c.kind(), - "unconditional_assignable_selector" | "conditional_assignable_selector" - ) - }); - if let Some(accessor) = accessor { - let mut ac = accessor.walk(); - let method_id = accessor.named_children(&mut ac).find(|c| c.kind() == "identifier"); - if let Some(method_id) = method_id { - let accessor_prev = prev.prev_named_sibling(); - if let Some(ap) = accessor_prev { - if ap.kind() == "identifier" { - return Some(format!("{}.{}", self.text(ap), self.text(method_id))); - } - // A constructor called with type arguments names - // its type all the same (`BlocProvider.value`). - if let Some(type_name) = self.type_arguments_receiver(ap) { - return Some(format!("{}.{}", type_name, self.text(method_id))); - } - // Chained static-factory: the receiver is itself - // a call — re-encode `().` when - // the chain starts capitalized (#750). - if ap.kind() == "selector" { - let mut apc = ap.walk(); - if ap.named_children(&mut apc).any(|c| c.kind() == "argument_part") { - if let Some(inner) = self.callee_of_arg_part(ap) { - if starts_upper_re().is_match(&inner) { - return Some(format!("{}().{}", inner, self.text(method_id))); - } - } - } - } - } - return Some(self.text(method_id).to_string()); - } - } - } - // super.method() / this.method(): prev is a bare accessor. - if matches!( - prev.kind(), - "unconditional_assignable_selector" | "conditional_assignable_selector" - ) { - let mut pc = prev.walk(); - let id = prev.named_children(&mut pc).find(|c| c.kind() == "identifier"); - if let Some(id) = id { - return Some(self.text(id).to_string()); - } - } - return None; + return self.callee_name(prev); + } + + // A generic call the grammar read as two comparisons + // (`ref.read(p)`), named at its `<`, where a parsed call's + // argument part starts. + if node.kind() == "relational_operator" { + let (callee, _) = self.misparsed_generic_call(node)?; + return self.callee_name(callee); } // new_expression arm — DEAD in practice (the INSTANTIATION branch @@ -1147,6 +1113,189 @@ impl<'t> Walker<'t> { None } + /// dartReceiverOf (dart.ts) — the receiver of the member access + /// `selector`: the node in front of it, or the end of an arrow function's + /// body when the grammar ended the arrow in front of a generic call + /// (`(ref) => ref.watch(p)` → `((ref) => ref).watch(p)`). + fn receiver_of(&self, selector: Node<'t>) -> Option> { + let prev = selector.prev_named_sibling(); + let body = prev + .filter(|p| p.kind() == "function_expression") + .and_then(|p| p.named_child(p.named_child_count().checked_sub(1)?)); + match body { + Some(body) if body.kind() == "function_expression_body" => { + body.named_child(body.named_child_count().checked_sub(1)?) + } + _ => prev, + } + } + + /// dartCallee (dart.ts) — the callee name of the call whose argument part + /// follows `prev`. + fn callee_name(&self, prev: Node<'t>) -> Option { + if prev.kind() == "identifier" { + return Some(self.text(prev).to_string()); + } + if prev.kind() == "selector" { + let mut pc = prev.walk(); + let accessor = prev.named_children(&mut pc).find(|c| { + matches!( + c.kind(), + "unconditional_assignable_selector" | "conditional_assignable_selector" + ) + }); + if let Some(accessor) = accessor { + let mut ac = accessor.walk(); + let method_id = accessor.named_children(&mut ac).find(|c| c.kind() == "identifier"); + if let Some(method_id) = method_id { + let accessor_prev = self.receiver_of(prev); + if let Some(ap) = accessor_prev { + if ap.kind() == "identifier" { + return Some(format!("{}.{}", self.text(ap), self.text(method_id))); + } + // A constructor called with type arguments names + // its type all the same (`BlocProvider.value`). + if let Some(type_name) = self.type_arguments_receiver(ap) { + return Some(format!("{}.{}", type_name, self.text(method_id))); + } + // Chained static-factory: the receiver is itself + // a call — re-encode `().` when + // the chain starts capitalized (#750). + if ap.kind() == "selector" { + let mut apc = ap.walk(); + if ap.named_children(&mut apc).any(|c| c.kind() == "argument_part") { + if let Some(inner) = self.callee_of_arg_part(ap) { + if starts_upper_re().is_match(&inner) { + return Some(format!("{}().{}", inner, self.text(method_id))); + } + } + } + } + } + return Some(self.text(method_id).to_string()); + } + } + } + // super.method() / this.method(): prev is a bare accessor. + if matches!( + prev.kind(), + "unconditional_assignable_selector" | "conditional_assignable_selector" + ) { + let mut pc = prev.walk(); + let id = prev.named_children(&mut pc).find(|c| c.kind() == "identifier"); + if let Some(id) = id { + return Some(self.text(id).to_string()); + } + } + None + } + + /// dartMisparsedGenericCall (dart.ts) — a generic call tree-sitter-dart + /// parsed as two comparisons, `(ref.read < Repo) > (p)`, found from its + /// `<`: the node its callee ends with (under any `await` or prefix + /// operator) and the identifier naming its type argument. Recovered when + /// the type argument names a type and the code is laid out as a call — + /// `<` against the callee, `(` against the `>`. A call chained on it keeps + /// its bare name (the `X().m` encoding resolves through a generic + /// factory's type parameter and finds nothing). + fn misparsed_generic_call(&self, lt: Node<'t>) -> Option<(Node<'t>, Node<'t>)> { + if lt.kind() != "relational_operator" || lt.child(0)?.kind() != "<" { + return None; + } + let inner = lt.parent()?; + let outer = inner.parent()?; + if inner.kind() != "relational_expression" || outer.kind() != "relational_expression" { + return None; + } + let left = outer.named_child(0)?; + if left.start_byte() != inner.start_byte() || left.end_byte() != inner.end_byte() { + return None; + } + let gt = outer.named_child(1)?; + if gt.kind() != "relational_operator" || gt.child(0)?.kind() != ">" { + return None; + } + let args = outer.named_child(2)?; + if !matches!(args.kind(), "parenthesized_expression" | "record_literal") || args.start_byte() != gt.end_byte() { + return None; + } + let before = lt.prev_named_sibling()?; + if before.end_byte() != lt.start_byte() { + return None; + } + // The type argument: `T`, `p.T`, `T<…>` or `p.T<…>`, and nothing else. + let head = lt.next_named_sibling()?; + if head.kind() != "identifier" { + return None; + } + let mut type_name = head; + let mut rest = head.next_named_sibling(); + if let Some(sel) = rest { + let accessor = sel.named_child(0).filter(|a| a.kind() == "unconditional_assignable_selector"); + if sel.kind() == "selector" { + if let Some(accessor) = accessor { + let mut ac = accessor.walk(); + let name = accessor.named_children(&mut ac).find(|c| c.kind() == "identifier"); + type_name = name?; + rest = sel.next_named_sibling(); + } + } + } + if let Some(sel) = rest { + let only_type_args = sel.named_child_count() == 1 + && sel.named_child(0).map(|t| t.kind() == "type_arguments").unwrap_or(false); + if sel.kind() == "selector" && only_type_args { + rest = sel.next_named_sibling(); + } + } + if rest.is_some() { + return None; + } + let name = self.text(type_name); + if !is_upper_camel(name) && !is_lowercase_type(name) { + return None; + } + // `await repo.load(id)` and `-x.size(y)` put the callee + // under the prefix. + let mut callee = before; + while is_prefixed(callee.kind()) { + let count = callee.named_child_count(); + callee = callee.named_child(count.checked_sub(1)?)?; + } + Some((callee, type_name)) + } + + /// dartInMisparsedGenericCall (dart.ts) — whether a member access + /// (`.member` on `receiver`, followed by `next` under `parent`) belongs to + /// a misparsed generic call: its callee is called, and a prefixed type + /// argument (`p.Repo`) names a type. + fn in_misparsed_generic_call( + &self, + receiver: Node<'t>, + next: Option>, + parent: Option>, + ) -> bool { + let mut after = next; + let mut up = parent; + while after.is_none() { + let Some(u) = up.filter(|u| is_prefixed(u.kind())) else { break }; + after = u.next_named_sibling(); + up = if after.is_some() { None } else { u.parent() }; + } + if let Some(a) = after { + if a.kind() == "relational_operator" && self.misparsed_generic_call(a).is_some() { + return true; + } + } + if parent.map(|p| p.kind()) != Some("relational_expression") { + return false; + } + receiver + .prev_named_sibling() + .map(|b| b.kind() == "relational_operator" && self.misparsed_generic_call(b).is_some()) + .unwrap_or(false) + } + /// dartCalleeOfArgPart (dart.ts:100-116). fn callee_of_arg_part(&self, arg_part: Node<'t>) -> Option { let prev = arg_part.prev_named_sibling()?; @@ -1213,8 +1362,15 @@ impl<'t> Walker<'t> { if node.named_children(&mut cursor).any(|c| c.kind() == "argument_part") { return; } - let Some(prev) = node.prev_named_sibling() else { return }; + let Some(prev) = self.receiver_of(node) else { return }; if prev.kind() == "identifier" && cap_ident_re().is_match(self.text(prev)) { + // `Map` in `x.read>(y)` parsed as comparisons is a type + // argument, which the body walker references as a type. + if let Some(before) = prev.prev_named_sibling() { + if before.kind() == "relational_operator" && self.misparsed_generic_call(before).is_some() { + return; + } + } let name = self.text(prev).to_string(); // NO callee-of-call skip — `ConfigT.load()` double-emits // (references + calls). Position = the IDENTIFIER (receiver). @@ -1510,7 +1666,8 @@ impl<'t> Walker<'t> { if receiver.kind() != "identifier" { return; } - if let Some(next) = node.next_named_sibling() { + let next = node.next_named_sibling(); + if let Some(next) = next { if next.kind() == "selector" { let mut nc = next.walk(); if next.named_children(&mut nc).any(|c| c.kind() == "argument_part") { @@ -1518,6 +1675,11 @@ impl<'t> Walker<'t> { } } } + // The callee of a generic call the grammar read as comparisons + // (`ref.read(p)`) is called; a prefixed type argument names a type. + if self.in_misparsed_generic_call(receiver, next, node.parent()) { + return; + } let name = format!("{}.{}", self.text(receiver), self.text(member)); let reader = self.top_row(); self.push_ref_at(reader, &name, "references", member); @@ -1544,12 +1706,18 @@ impl<'t> Walker<'t> { self.extract_static_member_ref(node); - // A getter read `x.area` (#2338); a type the body names (#2327). + // A getter read `x.area` (#2338); a type the body names (#2327) — the + // type argument of a generic call parsed as comparisons included. self.extract_member_read(node); - if kind == "type_identifier" && self.is_type_name_dart(node) { - let name = self.text(node).to_string(); + let type_node = match kind { + "type_identifier" => Some(node), + "relational_operator" => self.misparsed_generic_call(node).map(|(_, type_name)| type_name), + _ => None, + }; + if let Some(type_node) = type_node.filter(|t| self.is_type_name_dart(*t)) { + let name = self.text(type_node).to_string(); let owner = self.top_row(); - self.push_ref_at(owner, &name, "references", node); + self.push_ref_at(owner, &name, "references", type_node); } if kind == "function_signature" { diff --git a/docs/design/dart-kernel-port-checklist.md b/docs/design/dart-kernel-port-checklist.md index e2575d6ef3..7f243c1ab2 100644 --- a/docs/design/dart-kernel-port-checklist.md +++ b/docs/design/dart-kernel-port-checklist.md @@ -701,6 +701,7 @@ extract-mini.txt): | `BlocProviderT.value(…);` as a statement | args selector; prev = `.value` selector; accessorPrev = a selector holding only `type_arguments`, whose prev is the identifier | `BlocProviderT.value` (dartTypeArgumentsReceiver, since 2026-10-06 — bare `value` before); the `.value().tail` re-encode reads it the same way | | `=> BlocProviderT.value(…)`, and as an initializer, argument or `return` value | `constructor_invocation` (type_identifier [`.` type_identifier] type_arguments `.` identifier arguments) | `BlocProviderT.value` at the node position — the LAST type_identifier, so `p.X.named()` → `X.named` (since 2026-10-06; nothing before) | | `generic(5)` | args selector (type args ride argument_part) | bare `generic` | +| `ref.read(p)`, `Provider((ref) => 0)`, `X(name: v)` parsed as two comparisons, `(ref.read < Repo) > (p)` (§Misparsed generic calls) | the `<` relational_operator (dartMisparsedGenericCall) | the parsed call's ref — `ref.read` / `Provider` / `X`, at the `<` | | `await fetch()` | recursion through unary/await_expression | `fetch` at the selector | | `throw StateError('bad')` | recursion | `StateError` | | `'sum ${a + compute()}'` | template_substitution recursion | `compute` (interpolation calls EMIT); `$name` → identifier_dollar_escaped → nothing | @@ -712,6 +713,46 @@ extractCall (:3684), LITERAL_RECEIVER_TYPES (:373-388), SKIP_RECEIVERS, the parenthesized-conversion regex (:4530), template-strip — ALL UNREACHABLE for dart (callTypes empty). Do not port them. +#### Misparsed generic calls (dartMisparsedGenericCall / misparsed_generic_call) + +tree-sitter-dart parses a generic call with arguments as two comparisons about +as often as it parses it as a call — the GLR tie goes either way with the code +around it: `final a = ref.watch(p);`, `ref.read(p);`, `int g(Ref +ref) => ref.read(1);` and `Provider((ref) => 0)` come out as +`relational_expression(relational_expression( < ) > )`, +while `print(ref.watch(p) + 1)`, `obj.a.b(p)` and +`ref.read(a, b)` parse as calls (2,853 nests vs 2,836 parsed generic +calls with arguments across bloc, riverpod and flutter/samples). The args are +a `parenthesized_expression`, or a `record_literal` when named +(`DropdownButton(items: …)`); the type part is `identifier`, a `.Name` +selector (`p.Repo`) and/or a type_arguments-only selector (`Map`); the +callee part sits under `unary_expression` / `await_expression` for `await` and +prefix operators. Recovered at the `<` when the type names a type (`/^[_$]*[A-Z]/` +or `int double num bool dynamic void`), `<` touches the callee and `(` touches +the `>`; `a < B > (c)`, `a(c)` and `a (c)` stay comparisons. The +recovered form emits what the parsed call does: + +- `calls` at the `<` (the parsed call's argument_part starts there); +- `references ` for the type argument, via isDartTypeName (§Type refs); + the static-member path skips `Map` in `>` so it is not doubled; +- no member read of the callee (`ref.read`, also under `await`) or of a + prefixed type (`p.Repo`). + +A call chained on a recovered one keeps its bare name (`increment` in +`BlocProvider.of(context).increment()`), unlike the parsed +chain's `BlocProvider.of().increment`: that encoding resolves through `of`'s +return type, which for generic factories is the type parameter, so it would +lose the edge the bare name finds. + +The grammar can also end an arrow function in front of a generic call: +`(ref) => ref.watch(p)` → `((ref) => ref).watch(p)`, in the +relational and the selector form alike. dartReceiverOf / receiver_of read a +receiver in that place from the end of the arrow's body (Dart writes a member +access on an arrow itself in parentheses), for callee names and static-member +refs: `ref.watch`, `BlocProvider.of`. dartCalleeOfArgPart / callee_of_arg_part +do not, so `() => BlocProvider.of(context).increment()` keeps +`increment` bare, for the reason above. + ### Static-member / value-read refs — dart branch (:4759-4767), STATIC_MEMBER_LANGS:346 Called from the body walker only (:5218). The DART-SPECIFIC branch (the diff --git a/src/extraction/languages/dart.ts b/src/extraction/languages/dart.ts index fdac302a78..788d3392ab 100644 --- a/src/extraction/languages/dart.ts +++ b/src/extraction/languages/dart.ts @@ -63,14 +63,130 @@ function isDartFieldOrTopLevelEntry(node: SyntaxNode): boolean { return owner?.type === 'declaration' && owner.parent !== null && DART_MEMBER_BODIES.has(owner.parent.type); } +/** + * The receiver of the member access `selector`: the node in front of it, or + * the end of an arrow function's body when the grammar ended the arrow in + * front of a generic call — `(ref) => ref.watch(p)` comes out as + * `((ref) => ref).watch(p)`. Dart writes a member access on the arrow + * itself in parentheses, so a receiver in that place is never the arrow. It + * names the call (`ref.watch`) and a static member's class; a call chained on + * that call keeps its bare name (see dartMisparsedGenericCall). + */ +export function dartReceiverOf(selector: SyntaxNode): SyntaxNode | null { + const prev = selector.previousNamedSibling; + const body = prev?.type === 'function_expression' ? prev.lastNamedChild : null; + return body?.type === 'function_expression_body' ? body.lastNamedChild : prev; +} + +/** Dart's lowercase built-in types, which a type argument can name: ``, ``. */ +const DART_LOWERCASE_TYPES: ReadonlySet = new Set(['int', 'double', 'num', 'bool', 'dynamic', 'void']); + +/** What a callee can sit under in front of a generic call: `await`, `-`, `!`. */ +const DART_PREFIXED: ReadonlySet = new Set(['unary_expression', 'await_expression']); + +/** A generic call tree-sitter-dart parsed as two comparisons (dartMisparsedGenericCall). */ +interface DartMisparsedCall { + /** The node the callee ends with: what a parsed call's argument part follows. */ + callee: SyntaxNode; + /** The identifier naming the type argument (`Repo` in `` and ``). */ + typeName: SyntaxNode; +} + +/** + * A generic call tree-sitter-dart parsed as two comparisons, found from its + * `<`. `ref.read(repoProvider)`, `Provider((ref) => 0)` and + * `DropdownButton(items: items)` come out as `(ref.read < Repo) > + * (repoProvider)`: a `relational_expression` inside another, with the + * arguments as a `parenthesized_expression`, or a `record_literal` when they + * are named. That happens about as often as the call parses as one, because + * the grammar breaks the tie by the code around it. Dart reads it as a call, + * and so does this when the type argument names a type (`Repo`, `p.Repo`, + * `Map`, `int`, `void`) and the code is laid out as a call: `<` against + * the callee and `(` against the `>`. A comparison is written `a < b`. + * + * A call chained on it keeps the bare name it had (`increment` in + * `BlocProvider.of(context).increment()`) rather than taking + * the `BlocProvider.of().increment` a parsed chain gets: that encoding + * resolves through what `of` returns, and a generic factory like this one + * returns its type parameter, so it would drop the edge the bare name finds. + */ +export function dartMisparsedGenericCall(lt: SyntaxNode): DartMisparsedCall | undefined { + if (lt.type !== 'relational_operator' || lt.firstChild?.type !== '<') return undefined; + const inner = lt.parent; + const outer = inner?.parent; + if (inner?.type !== 'relational_expression' || outer?.type !== 'relational_expression') return undefined; + const left = outer.namedChild(0); + if (left?.startIndex !== inner.startIndex || left.endIndex !== inner.endIndex) return undefined; + const gt = outer.namedChild(1); + if (gt?.type !== 'relational_operator' || gt.firstChild?.type !== '>') return undefined; + const args = outer.namedChild(2); + if (args?.type !== 'parenthesized_expression' && args?.type !== 'record_literal') return undefined; + if (args.startIndex !== gt.endIndex) return undefined; + const before = lt.previousNamedSibling; + if (!before || before.endIndex !== lt.startIndex) return undefined; + // The type argument: `T`, `p.T`, `T<…>` or `p.T<…>`, and nothing else. + const head = lt.nextNamedSibling; + if (head?.type !== 'identifier') return undefined; + let typeName = head; + let rest = head.nextNamedSibling; + if (rest?.type === 'selector' && rest.firstNamedChild?.type === 'unconditional_assignable_selector') { + const name = rest.firstNamedChild.namedChildren.find((c: SyntaxNode) => c.type === 'identifier'); + if (!name) return undefined; + typeName = name; + rest = rest.nextNamedSibling; + } + if (rest?.type === 'selector' && rest.namedChildCount === 1 && rest.firstNamedChild?.type === 'type_arguments') { + rest = rest.nextNamedSibling; + } + if (rest) return undefined; + if (!/^[_$]*[A-Z]/.test(typeName.text) && !DART_LOWERCASE_TYPES.has(typeName.text)) return undefined; + // `await repo.load(id)` and `-x.size(y)` put the callee under the prefix. + let callee: SyntaxNode = before; + while (DART_PREFIXED.has(callee.type)) { + const last: SyntaxNode | null = callee.lastNamedChild; + if (!last) return undefined; + callee = last; + } + return { callee, typeName }; +} + +/** + * Whether a member access — `.member` on `receiver`, followed by `next` under + * `parent` — belongs to a misparsed generic call instead of reading a member: + * its callee (`ref.read` in `ref.read(p)`, after an `await` too) is + * called, and the prefixed type argument (`p.Repo` in `x.read(y)`) + * names a type. + */ +function dartInMisparsedGenericCall( + receiver: SyntaxNode, + next: SyntaxNode | null, + parent: SyntaxNode | null, +): boolean { + let after = next; + let up = parent; + while (!after && up && DART_PREFIXED.has(up.type)) { + after = up.nextNamedSibling; + up = after ? null : up.parent; + } + if (after?.type === 'relational_operator' && dartMisparsedGenericCall(after)) return true; + if (parent?.type !== 'relational_expression') return false; + const before = receiver.previousNamedSibling; + return before?.type === 'relational_operator' && dartMisparsedGenericCall(before) !== undefined; +} + /** * A Dart member read — `x.area`, `s?.label`, `Config.instance` — as the ref * `.`, positioned on the member's name. Reading a getter runs * it, so the resolver links the read to a getter, as a call, and to nothing * else (#2338). The receiver must be a plain name, the one shape whose type the - * resolver can look up; a member that is called (`x.grow()`) is the call's. + * resolver can look up; a member that is called (`x.grow()`, or `x.grow(y)` + * parsed as comparisons) is the call's. `parent` is the node's parent when the + * walker has it: reading `.parent` walks down from the root. */ -export function dartMemberRead(node: SyntaxNode): { name: string; node: SyntaxNode } | undefined { +export function dartMemberRead( + node: SyntaxNode, + parent: SyntaxNode | null = node.parent, +): { name: string; node: SyntaxNode } | undefined { if (node.type !== 'selector') return undefined; const accessor = node.namedChildren.find((c: SyntaxNode) => c.type === 'unconditional_assignable_selector' || c.type === 'conditional_assignable_selector' @@ -83,6 +199,7 @@ export function dartMemberRead(node: SyntaxNode): { name: string; node: SyntaxNo if (next?.type === 'selector' && next.namedChildren.some((c: SyntaxNode) => c.type === 'argument_part')) { return undefined; } + if (dartInMisparsedGenericCall(receiver, next, parent)) return undefined; return { name: `${receiver.text}.${member.text}`, node: member }; } @@ -234,6 +351,63 @@ function dartCalleeOfArgPart(argPart: SyntaxNode): string | undefined { return undefined; } +/** + * The callee name of the Dart call whose argument part follows `prev`: `run` + * for `run(…)`, `obj.method` for `obj.method(…)`, `Foo.create().bar` for a + * chain off a capitalized call (#750), and a bare `method` otherwise. + */ +function dartCallee(prev: SyntaxNode): string | undefined { + // Simple function/constructor call: prev is identifier (e.g., runApp(...), MyWidget(...)) + if (prev.type === 'identifier') { + return prev.text; + } + + // Method call: prev is selector with accessor (e.g., obj.method(...), Navigator.push(...)) + if (prev.type === 'selector') { + const accessor = prev.namedChildren.find((c: SyntaxNode) => + c.type === 'unconditional_assignable_selector' || c.type === 'conditional_assignable_selector' + ); + if (accessor) { + const methodId = accessor.namedChildren.find((c: SyntaxNode) => c.type === 'identifier'); + if (methodId) { + // Include receiver for first call in chain (receiver is a direct identifier) + const accessorPrev = dartReceiverOf(prev); + if (accessorPrev?.type === 'identifier') { + return accessorPrev.text + '.' + methodId.text; + } + // A constructor called with type arguments names its type all the + // same: `BlocProvider.value(…)` → `BlocProvider.value`. + const typeName = dartTypeArgumentsReceiver(accessorPrev); + if (typeName) return typeName + '.' + methodId.text; + // Chained static-factory / fluent call: the receiver is itself a call + // (`Foo.create().bar()`), so accessorPrev is that call's argument_part + // selector. Encode `().` so resolution can infer + // bar's class from what `Foo.create` RETURNS (#645/#608 mechanism) — + // but only when the chain starts with a capitalized type (a companion + // factory / static method / constructor); an instance chain + // (`obj.foo().bar()`) keeps the bare name (its receiver's type can't + // be recovered here). + if (accessorPrev?.type === 'selector' && + accessorPrev.namedChildren.some((c: SyntaxNode) => c.type === 'argument_part')) { + const innerCallee = dartCalleeOfArgPart(accessorPrev); + if (innerCallee && /^[A-Z]/.test(innerCallee)) { + return `${innerCallee}().${methodId.text}`; + } + } + return methodId.text; + } + } + } + + // super.method() / this.method(): prev is bare unconditional_assignable_selector + if (prev.type === 'unconditional_assignable_selector' || prev.type === 'conditional_assignable_selector') { + const methodId = prev.namedChildren.find((c: SyntaxNode) => c.type === 'identifier'); + if (methodId) return methodId.text; + } + + return undefined; +} + export const dartExtractor: LanguageExtractor = { functionTypes: ['function_signature'], classTypes: ['class_definition'], @@ -490,57 +664,14 @@ export const dartExtractor: LanguageExtractor = { if (!hasArgPart) return undefined; const prev = node.previousNamedSibling; - if (!prev) return undefined; - - // Simple function/constructor call: prev is identifier (e.g., runApp(...), MyWidget(...)) - if (prev.type === 'identifier') { - return prev.text; - } - - // Method call: prev is selector with accessor (e.g., obj.method(...), Navigator.push(...)) - if (prev.type === 'selector') { - const accessor = prev.namedChildren.find((c: SyntaxNode) => - c.type === 'unconditional_assignable_selector' || c.type === 'conditional_assignable_selector' - ); - if (accessor) { - const methodId = accessor.namedChildren.find((c: SyntaxNode) => c.type === 'identifier'); - if (methodId) { - // Include receiver for first call in chain (receiver is a direct identifier) - const accessorPrev = prev.previousNamedSibling; - if (accessorPrev?.type === 'identifier') { - return accessorPrev.text + '.' + methodId.text; - } - // A constructor called with type arguments names its type all the - // same: `BlocProvider.value(…)` → `BlocProvider.value`. - const typeName = dartTypeArgumentsReceiver(accessorPrev); - if (typeName) return typeName + '.' + methodId.text; - // Chained static-factory / fluent call: the receiver is itself a call - // (`Foo.create().bar()`), so accessorPrev is that call's argument_part - // selector. Encode `().` so resolution can infer - // bar's class from what `Foo.create` RETURNS (#645/#608 mechanism) — - // but only when the chain starts with a capitalized type (a companion - // factory / static method / constructor); an instance chain - // (`obj.foo().bar()`) keeps the bare name (its receiver's type can't - // be recovered here). - if (accessorPrev?.type === 'selector' && - accessorPrev.namedChildren.some((c: SyntaxNode) => c.type === 'argument_part')) { - const innerCallee = dartCalleeOfArgPart(accessorPrev); - if (innerCallee && /^[A-Z]/.test(innerCallee)) { - return `${innerCallee}().${methodId.text}`; - } - } - return methodId.text; - } - } - } - - // super.method() / this.method(): prev is bare unconditional_assignable_selector - if (prev.type === 'unconditional_assignable_selector' || prev.type === 'conditional_assignable_selector') { - const methodId = prev.namedChildren.find((c: SyntaxNode) => c.type === 'identifier'); - if (methodId) return methodId.text; - } + return prev ? dartCallee(prev) : undefined; + } - return undefined; + // A generic call the grammar read as two comparisons (`ref.read(p)`), + // named at its `<`, where a parsed call's argument part starts. + if (node.type === 'relational_operator') { + const call = dartMisparsedGenericCall(node); + return call ? dartCallee(call.callee) : undefined; } // new MyWidget() — explicit constructor call diff --git a/src/extraction/tree-sitter-types.ts b/src/extraction/tree-sitter-types.ts index 1c2d4f374f..941e6b36c9 100644 --- a/src/extraction/tree-sitter-types.ts +++ b/src/extraction/tree-sitter-types.ts @@ -323,9 +323,10 @@ export interface LanguageExtractor { * getter `area` when `area` is one. Returns the ref name (`x.area`) and the * node to position it on, or undefined. Emitted as a `references` ref from * the function the read is in; the resolver links it only to a getter, with - * a `calls` edge (a plain field read links nothing). + * a `calls` edge (a plain field read links nothing). `parent` is the node's + * parent, handed down by the body walker. */ - extractMemberRead?: (node: SyntaxNode) => { name: string; node: SyntaxNode } | undefined; + extractMemberRead?: (node: SyntaxNode, parent?: SyntaxNode) => { name: string; node: SyntaxNode } | undefined; /** * Node types representing a file-level package/namespace declaration diff --git a/src/extraction/tree-sitter.ts b/src/extraction/tree-sitter.ts index 8019b3af14..7a4ea76add 100644 --- a/src/extraction/tree-sitter.ts +++ b/src/extraction/tree-sitter.ts @@ -23,7 +23,7 @@ import type { LanguageExtractor, ExtractorContext } from './tree-sitter-types'; import { EXTRACTORS } from './languages'; import { stripCppTemplateArgs, isCppConstructorDeclaration } from './languages/c-cpp'; import { rustImplTypeName } from './languages/rust'; -import { isDartTypeName, pushDartTypeRefs } from './languages/dart'; +import { dartMisparsedGenericCall, dartReceiverOf, isDartTypeName, pushDartTypeRefs } from './languages/dart'; import { LiquidExtractor } from './liquid-extractor'; import { RazorExtractor } from './razor-extractor'; import { SvelteExtractor } from './svelte-extractor'; @@ -5783,8 +5783,12 @@ export class TreeSitterExtractor { if (this.language === 'dart') { if (node.type !== 'selector') return; if (node.namedChildren.some((c: SyntaxNode) => c.type === 'argument_part')) return; - const prev = node.previousNamedSibling; + const prev = dartReceiverOf(node); if (prev?.type === 'identifier' && /^[A-Z][A-Za-z0-9_]*$/.test(prev.text)) { + // `Map` in `x.read>(y)` parsed as comparisons is a type + // argument, which the body walker references as a type. + const before = knownParent?.type === 'relational_expression' ? prev.previousNamedSibling : null; + if (before?.type === 'relational_operator' && dartMisparsedGenericCall(before)) return; this.pushStaticMemberRef(prev.text, ownerId, prev); } return; @@ -6600,7 +6604,7 @@ export class TreeSitterExtractor { // A member read that may run code — Dart's `x.area` calls the getter // `area` (#2338). The resolver links it to a getter, as a call, or to // nothing: a plain field read stays a reference that names no symbol. - const read = this.extractor!.extractMemberRead?.(node); + const read = this.extractor!.extractMemberRead?.(node, parent); if (read) { const readerId = this.nodeStack[this.nodeStack.length - 1]; if (readerId) { @@ -6615,18 +6619,22 @@ export class TreeSitterExtractor { } // A type a Dart body names — a local's declared type, a generic argument - // (`Future.value(null)`, `context.read()`), a cast, a - // type test — is the function's dependency, as a TS local's annotation - // is just below (#2327). - if (this.language === 'dart' && nodeType === 'type_identifier' && isDartTypeName(node)) { + // (`Future.value(null)`, `context.read()`, and + // `ref.read(p)` when the grammar read that call as comparisons), + // a cast, a type test — is the function's dependency, as a TS local's + // annotation is just below (#2327). + if (this.language === 'dart') { + const typeNode = nodeType === 'type_identifier' ? node + : nodeType === 'relational_operator' ? dartMisparsedGenericCall(node)?.typeName + : undefined; const ownerId = this.nodeStack[this.nodeStack.length - 1]; - if (ownerId) { + if (typeNode && ownerId && isDartTypeName(typeNode)) { this.unresolvedReferences.push({ fromNodeId: ownerId, - referenceName: getNodeText(node, this.source), + referenceName: getNodeText(typeNode, this.source), referenceKind: 'references', - line: node.startPosition.row + 1, - column: node.startPosition.column, + line: typeNode.startPosition.row + 1, + column: typeNode.startPosition.column, }); } } From 1b752de2c0c5101c994748e21d408102d27609b1 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 15:25:55 +0000 Subject: [PATCH 10/23] fix(dart): a member with no body keeps its dartdoc and annotations (#2382) A Dart member written without a body - a constructor like `Foo._();` or `Point.origin() : x = 0;`, a `const` constructor or redirecting factory such as flutter_bloc's `const BlocProvider.value(...)`, an abstract or `external` method - parses as a `declaration` wrapping its signature, and its `///` dartdoc and `@annotation`s are siblings of that wrapper. Both extractors looked for them before the signature, inside the wrapper, and found nothing: the docstring was lost, and `@visibleForTesting Foo._();` emitted no `decorates` reference. Extraction (TS + kernel, at parity): - A Dart-only `getDeclarationWrapper` hook returns the `declaration` when the signature is its first named child. `docstringFor` and extractDecoratorsFor's preceding-sibling scan start from it; the kernel's `declaration_wrapper` does the same for every docstring lookup and for the annotation scan. - The shared DOCSTRING_WRAPPER_TYPES / `is_wrapper` list is untouched: C/C++ share it, and their `declaration` wraps declarators. All 35 non-Dart parity fixtures extract byte-identically before and after. Validated on felangel/bloc @b9be1e2 and rrousselGit/riverpod @4ba1be2 at main 3f96f80f with the kernel loaded: bloc +32 docstrings, riverpod +126, none changed or removed, and 0 edges added or removed. The new `decorates` refs (+10 / +186) all name SDK or package:meta annotations and stay unresolved. Kernel parity sweeps show 0 diffs, and full-index kernel and wasm dumps are byte-identical on both repos. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/dart-bodiless-member-docs.test.ts | 134 ++++++++++++++++++ .../kernel-parity/TortureDeclarationDocs.dart | 112 +++++++++++++++ __tests__/kernel-dart-parity.test.ts | 10 +- codegraph-kernel/src/dart.rs | 39 ++++- docs/design/dart-kernel-port-checklist.md | 41 ++++-- src/extraction/languages/dart.ts | 9 ++ src/extraction/tree-sitter-types.ts | 8 ++ src/extraction/tree-sitter.ts | 12 +- 9 files changed, 346 insertions(+), 20 deletions(-) create mode 100644 __tests__/dart-bodiless-member-docs.test.ts create mode 100644 __tests__/fixtures/kernel-parity/TortureDeclarationDocs.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 16d4ed8d34..1ac3d601f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In Dart, calling a parameter or a local variable, like `create(ref, arg)` inside `overrideWith(… create)`, a closure's parameter, a loop variable or a test's mock `listener(0, 1)`, no longer links the call to an unrelated function or constant of the same name in another file, or to a method the class inherits: a Bloc event handler's `emit(…)` is the handler's own `emit` parameter, not `Bloc.emit`. So `codegraph callers` and impact no longer list code that never calls them, while calls the parameter or variable doesn't cover, and calls to a local function, link as before. Re-index Dart projects after upgrading. - In Dart, `const` constructors and redirecting factories, like flutter_bloc's `const BlocProvider.value(…)` or freezed's `const factory LoginState.loading() = _Loading;`, are now indexed, so a call such as `BlocProvider.value(…)` or `BlocProvider.value(…)` links to that constructor instead of another class's member with the same name. A call through a class name now reaches only that class's own constructors and static members, never a look-alike class, a parent class, an instance getter of the same name, or a project method that merely shares its name with an SDK call like `Uri.parse(…)`, and a constructor is no longer linked from a bare name, the end of a call chain or an annotation like `@internal`. Re-index Dart projects after upgrading. - In Dart, a call that passes a type argument and arguments, like `ref.read(repoProvider)`, `ref.watch(counterProvider)`, `Provider((ref) => …)`, `BlocProvider.of(context)` or `RepositoryProvider(create: …)`, now links to the method or class it calls, and the type it passes counts as used there. Depending on the code around it, the parser often read such a call as two comparisons, so it linked nothing, and Riverpod providers, repository reads and bloc lookups were missing from `callers`, impact and `codegraph_explore`. A real comparison like `a < b` is still left alone. Re-index Dart projects after upgrading. +- In Dart, a constructor or member written without a body, like flutter_bloc's `const BlocProvider.value(…)`, `Foo._();`, `Point.origin() : x = 0, y = 0;` or an abstract or `external` method, now keeps the `///` documentation and the annotations written above it, the way one with a body already did. Before, that documentation was lost, so searching for words in it didn't find the symbol, and an annotation like `@visibleForTesting` or `@protected` on it wasn't recorded. Re-index Dart projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/dart-bodiless-member-docs.test.ts b/__tests__/dart-bodiless-member-docs.test.ts new file mode 100644 index 0000000000..13b8757093 --- /dev/null +++ b/__tests__/dart-bodiless-member-docs.test.ts @@ -0,0 +1,134 @@ +/** + * A Dart member with no body — a constructor like `Foo._();` or `Foo.parts() + * : id = 0;`, an abstract `void m();`, an `external` one — parses as a + * `declaration` wrapping its signature, and the member's `///` dartdoc and + * `@annotation`s sit before that wrapper, not before the signature. + * + * Both extractors looked for them before the signature, inside the wrapper, + * where there is nothing. Such a member lost its documentation, and + * `@visibleForTesting Foo._();` emitted no `decorates` reference. + * (flutter_bloc's `const BlocProvider.value(…)`, with its long dartdoc, is one + * of these constructors.) + * + * Runs against the native kernel (when built) and the wasm extractor, which + * must agree. + */ +import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as path from 'path'; +import { extractFromSource } from '../src/extraction'; +import { initGrammars, loadGrammarsForLanguages } from '../src/extraction/grammars'; +import { tryKernelExtract, resetKernelForTests } from '../src/extraction/kernel'; +import type { ExtractionResult } from '../src/types'; + +const KERNEL_PATH = path.join( + __dirname, + '..', + 'codegraph-kernel', + 'prebuilds', + `${process.platform}-${process.arch}`, + 'codegraph-kernel.node' +); +const kernelAvailable = fs.existsSync(KERNEL_PATH) || process.env.CODEGRAPH_KERNEL_EXPECT === '1'; + +const SOURCE = `abstract class Repository { + /// Loads the user with [id]. + Future load(String id); + + @visibleForTesting + void reset(); + + /// Calls into the platform. + external int platformVersion(); +} + +class User { + /// Creates a user from its parts. + User.parts(this.name) : id = 0; + + @visibleForTesting + User.test(this.name) : id = 1; + + @Deprecated('use parts') + @internal + User.old(this.name) : id = 2; + + /// The user's name. + @deprecated + final String name; + User.afterField() : name = '', id = 3; + + final int id; +} +`; + +const ENV_KEYS = ['CODEGRAPH_KERNEL', 'CODEGRAPH_KERNEL_LANGS'] as const; + +describe('Dart members with no body keep their dartdoc and annotations', () => { + let savedEnv: Record = {}; + + beforeAll(async () => { + await initGrammars(); + await loadGrammarsForLanguages(['dart']); + }); + + beforeEach(() => { + savedEnv = Object.fromEntries(ENV_KEYS.map((k) => [k, process.env[k]])); + resetKernelForTests(); + }); + + afterEach(() => { + for (const k of ENV_KEYS) { + if (savedEnv[k] === undefined) delete process.env[k]; + else process.env[k] = savedEnv[k]; + } + resetKernelForTests(); + }); + + function extract(backend: 'kernel' | 'wasm', source: string): ExtractionResult { + if (backend === 'wasm') { + process.env.CODEGRAPH_KERNEL = '0'; + return extractFromSource('lib/user.dart', source, 'dart'); + } + delete process.env.CODEGRAPH_KERNEL; + process.env.CODEGRAPH_KERNEL_LANGS = 'all'; + const result = tryKernelExtract('lib/user.dart', source, 'dart'); + expect(result, 'kernel extraction').not.toBeNull(); + return result!; + } + + const backends = kernelAvailable ? (['kernel', 'wasm'] as const) : (['wasm'] as const); + + for (const crlf of [false, true]) { + it.each(backends)(`%s${crlf ? ' (CRLF)' : ''}`, (backend) => { + const result = extract(backend, crlf ? SOURCE.replace(/\n/g, '\r\n') : SOURCE); + const node = (qualifiedName: string) => { + const found = result.nodes.find((n) => n.qualifiedName === qualifiedName); + expect(found, qualifiedName).toBeDefined(); + return found!; + }; + const decorators = (qualifiedName: string): string[] => { + const id = node(qualifiedName).id; + return result.unresolvedReferences + .filter((r) => r.referenceKind === 'decorates' && r.fromNodeId === id) + .map((r) => r.referenceName) + .sort(); + }; + + // The dartdoc before the declaration is the member's. + expect(node('Repository::load').docstring).toBe('Loads the user with [id].'); + expect(node('Repository::platformVersion').docstring).toBe('Calls into the platform.'); + expect(node('User::parts').docstring).toBe('Creates a user from its parts.'); + + // So are the annotations, stacked ones included. + expect(decorators('Repository::reset')).toEqual(['visibleForTesting']); + expect(decorators('User::test')).toEqual(['visibleForTesting']); + expect(decorators('User::old')).toEqual(['Deprecated', 'internal']); + + // A field's dartdoc and annotations stay with the field, which mints no + // node, rather than moving on to the constructor after it. + expect(node('User::afterField').docstring).toBeUndefined(); + expect(decorators('User::afterField')).toEqual([]); + }); + } +}); diff --git a/__tests__/fixtures/kernel-parity/TortureDeclarationDocs.dart b/__tests__/fixtures/kernel-parity/TortureDeclarationDocs.dart new file mode 100644 index 0000000000..b93a0bdd5e --- /dev/null +++ b/__tests__/fixtures/kernel-parity/TortureDeclarationDocs.dart @@ -0,0 +1,112 @@ +// Members with no body are a `declaration` wrapping their signature; their +// dartdoc and annotations sit before the wrapper. + +abstract class Store { + /// Abstract method doc. + Future save(Object value); + + /// Doc above an annotation. + @protected + void flush(); + + @mustCallSuper + @Deprecated('use flush') + void sync(); + + /// Abstract getter doc (no node). + int get size; + + /// Abstract setter doc (no node). + set size(int v); + + /// Abstract operator doc (no node). + Store operator +(Store other); + + /** Block dartdoc on an external member. */ + external int nativeCount(); + + /// Static external doc. + external static Store open(); + + // Plain comment on an abstract member. + bool isEmpty(); +} + +class Point { + /// Unnamed constructor doc (no node). + Point(this.x, this.y); + + /// Named constructor doc. + /// Second line. + Point.origin() : x = 0, y = 0; + + /// Redirecting constructor doc. + Point.onX(int x) : this(x, 0); + + @visibleForTesting + Point.test(this.x, this.y); + + /// Before annotation. + @Deprecated('use origin') + /// After annotation. + Point.zero() : x = 0, y = 0; + + /* é */ @visibleForTesting Point.inline(this.x) : y = 0; + + /// Field doc. + @observable + final int x; + Point.afterField(this.x, this.y); + + @first + Point.prev(this.x, this.y); + Point.next(this.x, this.y); + + final int y; + + /// Const constructor doc. + @literal + const Point.c(this.x, this.y); + + /// Redirecting factory doc. + const factory Point.r(int x, int y) = Point; + + /// Bodied named constructor doc. + @visibleForTesting + Point.bodied(this.x, this.y) { + validate(); + } + + void validate() {} +} + +mixin Walker { + /// Mixin abstract doc. + + void walk(); +} + +extension Ext on String { + /// Extension external doc. + @pragma('vm:prefer-inline') + external String shout(); +} + +extension type Meters(double value) { + /// Extension type external doc. + external double km(); +} + +enum Mode { + on, + off; + + /// Enum const constructor doc (no node). + const Mode(); + + /// Enum external doc. + external bool get isOn; + + /// Enum external method doc. + external void toggle(); +} diff --git a/__tests__/kernel-dart-parity.test.ts b/__tests__/kernel-dart-parity.test.ts index c6b2487750..234051ed7e 100644 --- a/__tests__/kernel-dart-parity.test.ts +++ b/__tests__/kernel-dart-parity.test.ts @@ -28,8 +28,10 @@ * constructors and redirecting factories as methods with the unnamed ones * skipped, every redirect-target form, and constructors called with type * arguments, as statements and as expressions; TortureGenericCalls.dart: - * generic calls parsed as two comparisons, recovered as calls) and their CRLF - * variants + * generic calls parsed as two comparisons, recovered as calls; + * TortureDeclarationDocs.dart: the dartdoc and annotations of a + * `declaration`-wrapped member with no body, read from before the wrapper) + * and their CRLF variants * (derived in-memory — #1329), plus defer and generated-file pins. * * The full-repo sweeps live in scripts/kernel-parity.mjs (shelf/bloc/flutter @@ -135,6 +137,10 @@ describe.skipIf(!kernelBuilt)('kernel Dart extraction parity', () => { // as `(ref.read < Repo) > (p)`): every callee, type-argument and argument // shape, in bodies and initializers, and the comparisons that look alike. ['TortureGenericCalls.dart', 10], + // Members with no body (`declaration`-wrapped constructors, abstract and + // external members) take their dartdoc and annotations from before the + // wrapper; a field's stay with the field. + ['TortureDeclarationDocs.dart', 20], ] as const; for (const [file, minNodes] of FIXTURES) { diff --git a/codegraph-kernel/src/dart.rs b/codegraph-kernel/src/dart.rs index 116414fc65..002e0a2f5f 100644 --- a/codegraph-kernel/src/dart.rs +++ b/codegraph-kernel/src/dart.rs @@ -582,6 +582,29 @@ impl<'t> Walker<'t> { false } + /// getDeclarationWrapper (dart.ts) — a member with no body (`Foo._();`, + /// `const Foo.c();`, an abstract `void m();`) is a `declaration` wrapping + /// its signature, and the member's `///` dartdoc and `@annotation`s come + /// before the wrapper. A signature that opens the declaration takes both + /// from there. + fn declaration_wrapper(&self, node: Node<'t>) -> Option> { + let parent = node.parent()?; + if parent.kind() != "declaration" { + return None; + } + if parent.named_child(0)? == node { + Some(parent) + } else { + None + } + } + + /// docstringFor (tree-sitter.ts) — the preceding comment run, looked up + /// from the declaration wrapper when there is one. + fn docstring_of(&self, node: Node<'t>) -> Option { + preceding_docstring(self.declaration_wrapper(node).unwrap_or(node), self.src) + } + /// resolveBody (dart.ts:158-171). fn resolve_body(&self, node: Node<'t>) -> Option> { if matches!(node.kind(), "function_signature" | "method_signature") { @@ -804,7 +827,7 @@ impl<'t> Walker<'t> { } return; } - let docstring = preceding_docstring(node, self.src); + let docstring = self.docstring_of(node); let signature = self.signature_of(node); let visibility = self.visibility_of(node); let is_async = self.is_async_of(node); @@ -851,7 +874,7 @@ impl<'t> Walker<'t> { } return; } - let docstring = preceding_docstring(node, self.src); + let docstring = self.docstring_of(node); let signature = self.signature_of(node); let visibility = self.visibility_of(node); let is_async = self.is_async_of(node); @@ -893,7 +916,7 @@ impl<'t> Walker<'t> { // fallback finds the ON type's type_identifier — a class named after // the extended type (preserved). let name = self.extract_name(node); - let docstring = preceding_docstring(node, self.src); + let docstring = self.docstring_of(node); let visibility = self.visibility_of(node); let row = self.create_node( "class", @@ -924,7 +947,7 @@ impl<'t> Walker<'t> { None => return, }; let name = self.extract_name(node); - let docstring = preceding_docstring(node, self.src); + let docstring = self.docstring_of(node); let visibility = self.visibility_of(node); let row = self.create_node( "enum", @@ -966,7 +989,7 @@ impl<'t> Walker<'t> { if name == "" { return false; } - let docstring = preceding_docstring(node, self.src); + let docstring = self.docstring_of(node); // `value` field is null (type_alias has no fields) → no refs from // the aliased type; returns false → children re-visited. self.create_node("type_alias", &name, node, Extra { docstring, ..Default::default() }); @@ -1397,8 +1420,10 @@ impl<'t> Walker<'t> { } // Scan 2: preceding siblings, backward, stop at the first // non-annotation — stacked annotations emit in REVERSE source order. - if let Some(parent) = decl.parent() { - let decl_start = decl.start_byte(); + // A `declaration`-wrapped member's annotations precede the wrapper. + let anchor = self.declaration_wrapper(decl).unwrap_or(decl); + if let Some(parent) = anchor.parent() { + let decl_start = anchor.start_byte(); let mut decl_idx: Option = None; for i in 0..parent.named_child_count() { if let Some(sib) = parent.named_child(i) { diff --git a/docs/design/dart-kernel-port-checklist.md b/docs/design/dart-kernel-port-checklist.md index 7f243c1ab2..f9fbd71f6a 100644 --- a/docs/design/dart-kernel-port-checklist.md +++ b/docs/design/dart-kernel-port-checklist.md @@ -246,7 +246,11 @@ Grammar-shape facts the config leans on (all probed, `mini-cst.txt` / constructor's name is a `type_identifier` without type arguments and an `identifier` after them). Until 2026-10-06 neither was in methodTypes (no node, no refs); now both mint methods exactly like the bare - `constructor_signature` (§isMisparsedFunction, §resolveName). Fields are `declaration > + `constructor_signature` (§isMisparsedFunction, §resolveName). Abstract and + `external` members are `declaration > function_signature` too (an anon + `external`/`static` keyword may precede the signature). In every one of + these the member's dartdoc and annotations are siblings of the + `declaration`, not of the signature — §getDeclarationWrapper. Fields are `declaration > (static)? (final|const|type|var) > initialized_identifier_list | static_final_declaration_list` (§Constants). - **Statements/expressions:** calls have NO call node — a postfix chain is @@ -327,6 +331,16 @@ Hooks PRESENT (port each exactly — anchors into languages/dart.ts): **LIVE and load-bearing for dart**: the comment there names Dart; a method/function node's endLine extends to the sibling body's end, e.g. `named` L123-125 spans its body). +- **getDeclarationWrapper** — node's parent is a `declaration` AND node is + that declaration's FIRST named child (`firstNamedChild.equals(node)`; + kernel `named_child(0) == node` — an anon `external`/`static` keyword + before the signature doesn't count) → the `declaration`, else undefined. + Read by tree-sitter.ts's `docstringFor` (every docstring lookup, so the + kernel's `docstring_of` wraps all five `preceding_docstring` calls) and + by extractDecoratorsFor's scan #2 (§Decorators); scan #1 and + `getBodyDocstring` keep the node itself. Only Dart defines it — never add + `declaration` to DOCSTRING_WRAPPER_TYPES / docstring.rs `is_wrapper`, + which C/C++ (whose `declaration` wraps declarators) share. - **getReturnType = extractDartReturnType (:80-92)** — ctor = dartCtorInfo (§below): a validated ctor returns the CLASS name (named ctors, factories → ret = enclosing class). Else sig = dartInnerSignature (:9 — @@ -846,12 +860,19 @@ enum emits nothing). Mechanics for dart: - For a method: the previous member's function_body (or any declaration) breaks the chain correctly. The annotation-BETWEEN-doc-and-decl also breaks the DOCSTRING chain (§Docstrings). -- Bodiless ctors (declaration-wrapped): extractMethod runs on - constructor_signature whose PARENT is the `declaration` node — the - backward scan runs over declaration's children (constructor_signature is - namedChild(0) → declIdx 0 → no siblings scanned) → an annotation before - the declaration attaches to NOTHING. Annotated fields likewise emit - nothing (no extractor runs). +- Members with no body (declaration-wrapped ctors, const ctors, redirecting + factories, abstract and `external` members): the signature's PARENT is the + `declaration`, so until 2026-10-06 the backward scan ran over the + declaration's own children (the signature is namedChild(0) → declIdx 0 → + nothing scanned) and an annotation before the declaration attached to + NOTHING (`@visibleForTesting Foo._();`, `@protected void m();`). Now scan + #2 starts at getDeclarationWrapper's `declaration`: same backward walk, + same reverse order, and a field's `declaration` in between still stops + it. Annotated fields themselves emit nothing (no extractor runs). + Validation (bloc @b9be1e2 / riverpod @4ba1be2): +10 / +186 `decorates` + refs, all SDK or package:meta names (`useResult`, `override`, `internal`, + `visibleForTesting`, …), so no edges; before #2380, riverpod's 23 new + `@internal` refs on `X.internal(…)` ctors resolved to the ctor itself. ### Docstrings (tree-sitter-helpers.ts:95-127) — dartdoc is KEPT, both forms @@ -865,7 +886,11 @@ plain `//` comments all become docstrings and accumulate together** (pinned: strip + `^\/\/[/!]?\s?` + `^\s*\*\s?` gm strips fire — **all `gm` strips ride `js_multiline_strip` in docstring.rs (#1329 CRLF semantics) — call the shared code, port nothing**. DOCSTRING_WRAPPER_TYPES contains no dart kinds -→ no anchor climbing. **An `annotation` between the comment run and the +→ no anchor climbing; instead `docstringFor` starts from +getDeclarationWrapper's `declaration` for a member with no body (until +2026-10-06 those looked inside the wrapper and found nothing, e.g. +`const BlocProvider.value(…)`'s dartdoc; validation added 32 docstrings on +bloc and 126 on riverpod, none changed or removed). **An `annotation` between the comment run and the declaration BREAKS the chain** (pinned: `/// Broken by annotation.` `@deprecated` `void annotated()` → doc undefined — the dominant real-world loss since `@override` is ubiquitous). Docstrings attach to: functions, diff --git a/src/extraction/languages/dart.ts b/src/extraction/languages/dart.ts index 788d3392ab..c12a02a567 100644 --- a/src/extraction/languages/dart.ts +++ b/src/extraction/languages/dart.ts @@ -497,6 +497,15 @@ export const dartExtractor: LanguageExtractor = { } return false; }, + // A member with no body — a constructor like `Foo._();` or `const Foo.c();`, + // an abstract `void m();` — is a `declaration` wrapping its signature, and + // the member's `///` dartdoc and `@annotation`s come before the wrapper. A + // signature that opens the declaration takes both from there. + getDeclarationWrapper: (node) => { + const parent = node.parent; + if (parent?.type !== 'declaration') return undefined; + return parent.firstNamedChild?.equals(node) ? parent : undefined; + }, resolveBody: (node, bodyField) => { // Dart: function_body is a next sibling of function_signature/method_signature if (node.type === 'function_signature' || node.type === 'method_signature') { diff --git a/src/extraction/tree-sitter-types.ts b/src/extraction/tree-sitter-types.ts index 941e6b36c9..d82a66b3c3 100644 --- a/src/extraction/tree-sitter-types.ts +++ b/src/extraction/tree-sitter-types.ts @@ -166,6 +166,14 @@ export interface LanguageExtractor { * their own variants. Returns cleaned prose, or undefined when there is none. */ getBodyDocstring?: (node: SyntaxNode, source: string) => string | undefined; + /** + * The node that wraps `node` and stands in its place among the declarations + * around it, when the grammar adds one. The doc comment and annotations + * written before the declaration precede that wrapper, so both are looked up + * from it. Dart wraps a member with no body (`Foo._();`, an abstract + * `void m();`) in a `declaration` node. Returns undefined when there is none. + */ + getDeclarationWrapper?: (node: SyntaxNode) => SyntaxNode | undefined; /** Extract visibility from node */ getVisibility?: (node: SyntaxNode) => 'public' | 'private' | 'protected' | 'internal' | undefined; /** Check if node is exported */ diff --git a/src/extraction/tree-sitter.ts b/src/extraction/tree-sitter.ts index 7a4ea76add..bf8f5f35ab 100644 --- a/src/extraction/tree-sitter.ts +++ b/src/extraction/tree-sitter.ts @@ -562,7 +562,8 @@ export class TreeSitterExtractor { * same symbol, and the column holds free text (#1905). */ private docstringFor(node: SyntaxNode): string | undefined { - const preceding = getPrecedingDocstring(node, this.source); + const anchor = this.extractor?.getDeclarationWrapper?.(node) ?? node; + const preceding = getPrecedingDocstring(anchor, this.source); const body = this.extractor?.getBodyDocstring?.(node, this.source); if (preceding && body) return `${preceding}\n\n${body}`; return body || preceding; @@ -6201,9 +6202,14 @@ export class TreeSitterExtractor { // wrapper objects from `parent`/`namedChild` navigation, so // `sibling === declNode` is unreliable — `startIndex` does // the matching instead. - const parent = declNode.parent; + // + // A grammar that wraps the declaration (Dart's `declaration` + // around a member with no body) puts the annotations before the + // wrapper, so the scan starts there. + const anchor = this.extractor?.getDeclarationWrapper?.(declNode) ?? declNode; + const parent = anchor.parent; if (parent) { - const declStart = declNode.startIndex; + const declStart = anchor.startIndex; let declIdx = -1; for (let i = 0; i < parent.namedChildCount; i++) { const sibling = parent.namedChild(i); From d500e58a524ccdcab32aa8a91a70376f22f56df7 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 15:29:47 +0000 Subject: [PATCH 11/23] =?UTF-8?q?fix(dart):=20link=20a=20call=20chained=20?= =?UTF-8?q?on=20a=20generic=20lookup=20like=20BlocProvider.of(=E2=80=A6?= =?UTF-8?q?)=20(#750)=20(#2383)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a generic call parses as a call (a named argument after a positional one, as in `(context, listen: false)`, or a type argument like ``, `` or `>`), the Dart extractor records a chain on it as `BlocProvider.of().increment`. The resolver typed that receiver by what `BlocProvider.of` is declared to return: `T` for `static T of(…)`, which names no type, and nothing at all when the lookup comes from a package, as flutter_bloc and provider do in an app. So `BlocProvider.of(context, listen: false).increment()` and provider's `Provider.of(context, listen: false).add(item)` linked nothing. The declared return type is still tried first, so `Foo.create().bar()` with a concrete return type resolves as before. When it gives no edge, the chain is read at the call site the way #2376 reads a later link of a chain: the lookup's own type parameter is the type argument the call gives, and an outside `of(…)` lookup hands back its T. The edge stays on the encoded ref, as in Go's fallback (the gin runaway). The extractors are unchanged. A chain on a call parsed as two comparisons keeps its bare name (#2375), and now reaches the same method; the comments that gave the old reason are corrected. Validated before/after with the native kernel at 3f96f80f, nothing removed anywhere: felangel/bloc @b9be1e2 0 (its four such sites parse as comparisons and already linked), rrousselGit/riverpod @4ba1be2 +6 (`X.family<…>(…).call(42)` to `ClassFamily::call`), flutter/samples @63411527 +2 and brianegan/flutter_architecture_samples @d898d13 +6, all `Provider.of(context, listen: false).m()`. A bare-name fallback (as Go does) added nothing on those repos, since the lookups are outside the project, and linked 2 of the test's 8 chains wrong. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/dart-generic-factory-chain.test.ts | 228 +++++++++++++++++++ codegraph-kernel/src/dart.rs | 4 +- docs/design/dart-kernel-port-checklist.md | 10 +- src/extraction/languages/dart.ts | 9 +- src/resolution/name-matcher.ts | 15 ++ 6 files changed, 257 insertions(+), 10 deletions(-) create mode 100644 __tests__/dart-generic-factory-chain.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ac3d601f8..0980e8029f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In Dart, `const` constructors and redirecting factories, like flutter_bloc's `const BlocProvider.value(…)` or freezed's `const factory LoginState.loading() = _Loading;`, are now indexed, so a call such as `BlocProvider.value(…)` or `BlocProvider.value(…)` links to that constructor instead of another class's member with the same name. A call through a class name now reaches only that class's own constructors and static members, never a look-alike class, a parent class, an instance getter of the same name, or a project method that merely shares its name with an SDK call like `Uri.parse(…)`, and a constructor is no longer linked from a bare name, the end of a call chain or an annotation like `@internal`. Re-index Dart projects after upgrading. - In Dart, a call that passes a type argument and arguments, like `ref.read(repoProvider)`, `ref.watch(counterProvider)`, `Provider((ref) => …)`, `BlocProvider.of(context)` or `RepositoryProvider(create: …)`, now links to the method or class it calls, and the type it passes counts as used there. Depending on the code around it, the parser often read such a call as two comparisons, so it linked nothing, and Riverpod providers, repository reads and bloc lookups were missing from `callers`, impact and `codegraph_explore`. A real comparison like `a < b` is still left alone. Re-index Dart projects after upgrading. - In Dart, a constructor or member written without a body, like flutter_bloc's `const BlocProvider.value(…)`, `Foo._();`, `Point.origin() : x = 0, y = 0;` or an abstract or `external` method, now keeps the `///` documentation and the annotations written above it, the way one with a body already did. Before, that documentation was lost, so searching for words in it didn't find the symbol, and an annotation like `@visibleForTesting` or `@protected` on it wasn't recorded. Re-index Dart projects after upgrading. +- In Dart, a call on what a generic lookup returns, like flutter_bloc's `BlocProvider.of(context, listen: false).increment()` or Provider's `Provider.of(context, listen: false).add(item)`, now links to that method of the type in the angle brackets, whether the lookup is declared in your project or comes from a package. Before, such a call often linked nothing — for example whenever the lookup passed `listen: false` — so `callers` and impact missed those methods. A lookup that names no type, like `BlocProvider.of(context)`, still links nothing. Re-index Dart projects after upgrading. (#750) ## [1.6.2] - 2026-10-03 diff --git a/__tests__/dart-generic-factory-chain.test.ts b/__tests__/dart-generic-factory-chain.test.ts new file mode 100644 index 0000000000..4df0f4c032 --- /dev/null +++ b/__tests__/dart-generic-factory-chain.test.ts @@ -0,0 +1,228 @@ +/** + * A Dart call chained on a generic static factory — bloc's + * `BlocProvider.of(context, listen: false).increment()`, + * `RepositoryProvider.of(context).saveTodo(t)` — calls a + * member of the type the factory's type argument names. + * + * When the generic call parses as a call (tree-sitter-dart reads about half + * of them as two comparisons, but a named argument or a type argument like + * `` makes it a call), the extractor records the chain as + * `BlocProvider.of().increment`, and the resolver typed it by what + * `BlocProvider.of` is declared to return. That is `T` (`static T of(…)`), + * which names no type, so the call linked nothing. In an app, where + * flutter_bloc is a dependency and not in the project, nothing typed it + * either. The chain read back from the call site is typed the way a later + * link of a chain is (#750): the factory's own type parameter is the type + * argument the call gives, and an outside lookup such as `of(…)` hands + * back its T. A chain on a call read as two comparisons keeps its bare name + * (`increment`), and reaches the same method. + * + * It never falls back to a member found by its name: `StepCounter.increment`, + * next to the call site, is not what `of` returns, and a call + * with no type argument (`BlocProvider.of(context)`) links nothing. + * + * Runs against the native kernel (when built) and the wasm extractor, which + * must agree. + */ +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; + +const PUBSPEC = 'name: app\nenvironment:\n sdk: ">=3.0.0 <4.0.0"\n'; + +// A method named like each chained call, nearer the call site than the type +// that declares it: the one a guess by name would pick. +const DECOY = `class StepCounter { + void increment() {} + void decrement() {} + void saveTodo(Object todo) {} +} +`; + +/** The bloc repo itself: BlocProvider is declared in the project. */ +const LIBRARY: Record = { + 'pubspec.yaml': PUBSPEC, + 'lib/bloc_provider.dart': `class BlocProvider { + const BlocProvider(); + + static T of(Object context, {bool listen = false}) => throw 0; + + static T? maybeOf(Object context, {bool listen = false}) => null; +} +`, + 'lib/bloc.dart': `abstract class Bloc { + void add(E event) {} +} +`, + 'lib/counter/counter_cubit.dart': `class CounterCubit { + void increment() {} +} +`, + 'lib/counter/counter_bloc.dart': `import '../bloc.dart'; + +class CounterBloc extends Bloc {} +`, + 'lib/counter/step_counter.dart': DECOY, + 'lib/counter/counter_page.dart': `import '../bloc_provider.dart'; +import 'counter_cubit.dart'; +import 'counter_cubit.dart' as cubits; +import 'counter_bloc.dart'; + +class Button { + const Button({Object? onPressed}); +} + +class CounterPage { + void tap(Object context) { + BlocProvider.of(context, listen: false).increment(); + } + + void tapWrapped(Object context) { + BlocProvider.of(context, listen: false) + .increment(); + } + + void tapPrefixed(Object context) { + BlocProvider.of(context, listen: false).increment(); + } + + void tapMaybe(Object context) { + BlocProvider.maybeOf(context, listen: false)?.increment(); + } + + void tapBloc(Object context) { + BlocProvider.of(context, listen: false).add(1); + } + + void tapMissing(Object context) { + BlocProvider.of(context, listen: false).decrement(); + } + + void tapInferred(Object context) { + BlocProvider.of(context, listen: false).increment(); + } + + // Parsed as two comparisons, so increment arrives by its bare name. + void tapRecovered(Object context) { + BlocProvider.of(context).increment(); + } + + Object build(Object context) => Button( + onPressed: () => BlocProvider.of(context, listen: false).increment(), + ); +} +`, +}; + +/** An app: flutter_bloc is a dependency, outside the project. */ +const APP: Record = { + 'pubspec.yaml': PUBSPEC, + 'lib/counter/counter_cubit.dart': `class CounterCubit { + void increment() {} +} +`, + 'lib/counter/step_counter.dart': DECOY, + 'lib/todos/todos_repository.dart': `class TodosRepository { + void saveTodo(Object todo) {} +} +`, + 'lib/counter/counter_page.dart': `import 'package:flutter_bloc/flutter_bloc.dart'; +import '../todos/todos_repository.dart'; +import 'counter_cubit.dart'; + +class CounterPage { + void tap(Object context) { + BlocProvider.of(context, listen: false).increment(); + } + + void save(Object context, Object todo) { + RepositoryProvider.of(context, listen: false).saveTodo(todo); + } + + void tapInferred(Object context) { + BlocProvider.of(context, listen: false).increment(); + } + + // Parsed as two comparisons, so increment arrives by its bare name. + void tapRecovered(Object context) { + BlocProvider.of(context).increment(); + } +} +`, +}; + +describe('Dart chains on a generic static factory', () => { + let root = ''; + let cg: CodeGraph | undefined; + let kernel: string | undefined; + + const index = async (files: Record, backend: string): Promise => { + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; + cg = await CodeGraph.init(root, { index: true }); + return cg; + }; + + /** `caller -> Owner::name` for every call edge out of a file. */ + const callsFrom = (graph: CodeGraph, file: string): string[] => { + const ids = graph.getNodesInFile(file).map((n) => n.id); + return graph + .getOutgoingEdgesFrom(ids) + .filter((e) => e.kind === 'calls') + .map((e) => `${graph.getNode(e.source)!.name} -> ${graph.getNode(e.target)!.qualifiedName}`) + .sort(); + }; + + beforeEach(() => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-generic-factory-')); + kernel = process.env.CODEGRAPH_KERNEL; + }); + + afterEach(() => { + cg?.close(); + cg = undefined; + fs.rmSync(root, { recursive: true, force: true }); + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; + }); + + it.each(['default', 'wasm'])('call a member of the type argument a project factory is given (%s)', async (backend) => { + const graph = await index(LIBRARY, backend); + expect(callsFrom(graph, 'lib/counter/counter_page.dart')).toEqual([ + 'build -> BlocProvider::of', + 'build -> CounterCubit::increment', + 'tap -> BlocProvider::of', + 'tap -> CounterCubit::increment', + // What CounterBloc inherits. + 'tapBloc -> Bloc::add', + 'tapBloc -> BlocProvider::of', + // No type argument says what `of` returns. + 'tapInferred -> BlocProvider::of', + 'tapMaybe -> BlocProvider::maybeOf', + 'tapMaybe -> CounterCubit::increment', + // CounterCubit has no `decrement`; StepCounter's is not this one. + 'tapMissing -> BlocProvider::of', + 'tapPrefixed -> BlocProvider::of', + 'tapPrefixed -> CounterCubit::increment', + 'tapRecovered -> BlocProvider::of', + 'tapRecovered -> CounterCubit::increment', + 'tapWrapped -> BlocProvider::of', + 'tapWrapped -> CounterCubit::increment', + ]); + }); + + it.each(['default', 'wasm'])('call a member of the type argument an outside lookup is given (%s)', async (backend) => { + const graph = await index(APP, backend); + expect(callsFrom(graph, 'lib/counter/counter_page.dart')).toEqual([ + 'save -> TodosRepository::saveTodo', + 'tap -> CounterCubit::increment', + 'tapRecovered -> CounterCubit::increment', + ]); + }); +}); diff --git a/codegraph-kernel/src/dart.rs b/codegraph-kernel/src/dart.rs index 002e0a2f5f..8c4445249c 100644 --- a/codegraph-kernel/src/dart.rs +++ b/codegraph-kernel/src/dart.rs @@ -1219,8 +1219,8 @@ impl<'t> Walker<'t> { /// operator) and the identifier naming its type argument. Recovered when /// the type argument names a type and the code is laid out as a call — /// `<` against the callee, `(` against the `>`. A call chained on it keeps - /// its bare name (the `X().m` encoding resolves through a generic - /// factory's type parameter and finds nothing). + /// its bare name, which the resolver types from the chain written before + /// it, as it types a parsed chain's `X().m` (#750). fn misparsed_generic_call(&self, lt: Node<'t>) -> Option<(Node<'t>, Node<'t>)> { if lt.kind() != "relational_operator" || lt.child(0)?.kind() != "<" { return None; diff --git a/docs/design/dart-kernel-port-checklist.md b/docs/design/dart-kernel-port-checklist.md index f9fbd71f6a..672e41e5d1 100644 --- a/docs/design/dart-kernel-port-checklist.md +++ b/docs/design/dart-kernel-port-checklist.md @@ -754,9 +754,11 @@ recovered form emits what the parsed call does: A call chained on a recovered one keeps its bare name (`increment` in `BlocProvider.of(context).increment()`), unlike the parsed -chain's `BlocProvider.of().increment`: that encoding resolves through `of`'s -return type, which for generic factories is the type parameter, so it would -lose the edge the bare name finds. +chain's `BlocProvider.of().increment`. The resolver gives both the same +method: a bare link is typed from the chain written before it, and so is an +encoded chain whose inner call declares no type of its own to return — a +generic factory's type parameter (`static T of`) or a factory outside the +project (#750). Nothing is gained by re-encoding the recovered chain. The grammar can also end an arrow function in front of a generic call: `(ref) => ref.watch(p)` → `((ref) => ref).watch(p)`, in the @@ -765,7 +767,7 @@ receiver in that place from the end of the arrow's body (Dart writes a member access on an arrow itself in parentheses), for callee names and static-member refs: `ref.watch`, `BlocProvider.of`. dartCalleeOfArgPart / callee_of_arg_part do not, so `() => BlocProvider.of(context).increment()` keeps -`increment` bare, for the reason above. +`increment` bare, which resolves as above. ### Static-member / value-read refs — dart branch (:4759-4767), STATIC_MEMBER_LANGS:346 diff --git a/src/extraction/languages/dart.ts b/src/extraction/languages/dart.ts index c12a02a567..7b2228b61b 100644 --- a/src/extraction/languages/dart.ts +++ b/src/extraction/languages/dart.ts @@ -105,10 +105,11 @@ interface DartMisparsedCall { * the callee and `(` against the `>`. A comparison is written `a < b`. * * A call chained on it keeps the bare name it had (`increment` in - * `BlocProvider.of(context).increment()`) rather than taking - * the `BlocProvider.of().increment` a parsed chain gets: that encoding - * resolves through what `of` returns, and a generic factory like this one - * returns its type parameter, so it would drop the edge the bare name finds. + * `BlocProvider.of(context).increment()`), where a parsed + * chain gets `BlocProvider.of().increment`. The resolver gives both the same + * method: it types a bare link from the chain written before it, and an + * encoded chain the same way when `of` declares no type of its own to return + * (`static T of(…)`, or a factory outside the project) (#750). */ export function dartMisparsedGenericCall(lt: SyntaxNode): DartMisparsedCall | undefined { if (lt.type !== 'relational_operator' || lt.firstChild?.type !== '<') return undefined; diff --git a/src/resolution/name-matcher.ts b/src/resolution/name-matcher.ts index 5668a53482..640d992514 100644 --- a/src/resolution/name-matcher.ts +++ b/src/resolution/name-matcher.ts @@ -8215,6 +8215,21 @@ export function matchDottedCallChain( const factoryMethod = inner.slice(lastDot + 1); if (!factoryClass || !factoryMethod) return null; const ret = lookupCalleeReturnType(`${factoryClass}::${factoryMethod}`, ref, context); + if (ref.language === 'dart') { + const declared = ret + ? resolveMethodOnType(ret, method, ref, context, 0.85, 'instance-method', importedFqnOf(ret, ref, context)) + : null; + if (declared) return declared; + // A generic factory returns its type parameter — `static T of(…)` in + // flutter_bloc's BlocProvider — and one outside the project declares + // nothing here, so `BlocProvider.of(context).increment()` + // had no type to look `increment` up on. The call site has it: read the + // chain there as a later link of a chain is read (#750), where `of`'s + // T is the type argument the call gives. The edge belongs to this ref, not + // to the bare name it was looked up by (see the gin runaway above). + const link = matchDartChainLink({ ...ref, referenceName: method }, context); + return link ? { ...link, original: ref } : null; + } if (!ret) { // Objective-C: a class-message factory — `[X alloc]`, `[X new]`, // `[X sharedFoo]` — returns an instance of the RECEIVER class `X` by From 5f5b8db620c5aa607a022471c9a604a71715ae73 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 15:31:37 +0000 Subject: [PATCH 12/23] fix(js,ts): find a store exported by an export { } list when its name starts or ends with $ (#2384) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TreeSitterExtractor.isExportedLater and its kernel mirror is_exported_later bounded the name in the `export { ... }` branch with `\b`, which takes a `$` for a separator. It never fires beside a leading or trailing `$`, so `const items$ = create(...)` + `export { items$ };` (or `export { $items as default };` for a `$items` store) never matched, and the store's actions were not extracted on either engine. It also matched inside a longer name: `export { useStore$ }` or `export { $useStore }` counted as exporting a store named `useStore`. The clause branch now bounds the name with a character that can't continue an identifier. The regex crate has no look-around, so the bounds consume, and both sides spell the class in ASCII, since the crate's `\w` is Unicode while JS's is ASCII. Plain names decide as before apart from the two false positives. A non-ASCII letter written against the name (`export { éuseStore }`) used to split the engines (the kernel's Unicode `\b` said not exported, the wasm path exported); both now give the wasm answer. Adds kernel/wasm parity cases (ts/tsx/js/jsx) inside 'a store exported by a later statement', and the same cases in store-exported-later.test.ts, for `items$`, `$items as default` and both false-positive shapes. They fail with the unfixed kernel and with the unfixed TS on the wasm path, and pass with both fixes. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/kernel-tsjs-parity.test.ts | 20 ++++++++++++++++++++ __tests__/store-exported-later.test.ts | 14 ++++++++++++++ codegraph-kernel/src/tsjs/extractors.rs | 6 +++++- src/extraction/tree-sitter.ts | 6 +++++- 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0980e8029f..5e9fa96cf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In Dart, a call that passes a type argument and arguments, like `ref.read(repoProvider)`, `ref.watch(counterProvider)`, `Provider((ref) => …)`, `BlocProvider.of(context)` or `RepositoryProvider(create: …)`, now links to the method or class it calls, and the type it passes counts as used there. Depending on the code around it, the parser often read such a call as two comparisons, so it linked nothing, and Riverpod providers, repository reads and bloc lookups were missing from `callers`, impact and `codegraph_explore`. A real comparison like `a < b` is still left alone. Re-index Dart projects after upgrading. - In Dart, a constructor or member written without a body, like flutter_bloc's `const BlocProvider.value(…)`, `Foo._();`, `Point.origin() : x = 0, y = 0;` or an abstract or `external` method, now keeps the `///` documentation and the annotations written above it, the way one with a body already did. Before, that documentation was lost, so searching for words in it didn't find the symbol, and an annotation like `@visibleForTesting` or `@protected` on it wasn't recorded. Re-index Dart projects after upgrading. - In Dart, a call on what a generic lookup returns, like flutter_bloc's `BlocProvider.of(context, listen: false).increment()` or Provider's `Provider.of(context, listen: false).add(item)`, now links to that method of the type in the angle brackets, whether the lookup is declared in your project or comes from a package. Before, such a call often linked nothing — for example whenever the lookup passed `listen: false` — so `callers` and impact missed those methods. A lookup that names no type, like `BlocProvider.of(context)`, still links nothing. Re-index Dart projects after upgrading. (#750) +- In JavaScript and TypeScript, a store whose name starts or ends with a `$`, like `const items$ = create(…)`, now has its actions indexed when an `export { … }` list on a later line exports it, as in `export { items$ };` or `export { $items as default };`. Before, those actions were missing from the graph, so their callers and impact came back empty. A store whose name only lacks the `$`, like `items`, is no longer treated as exported by that list. Re-index JavaScript and TypeScript projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/kernel-tsjs-parity.test.ts b/__tests__/kernel-tsjs-parity.test.ts index 9bf906f144..866d80d30b 100644 --- a/__tests__/kernel-tsjs-parity.test.ts +++ b/__tests__/kernel-tsjs-parity.test.ts @@ -149,6 +149,26 @@ describe.skipIf(!kernelBuilt)('kernel TS/JS extraction parity', () => { const result = assertParity(`store.${ext}`, source, language); expect(result.nodes.some((n) => n.kind === 'function' && n.name === 'inc')).toBe(true); }); + + it.each([ + ['items$', 'export { items$ };', true], + ['$items', 'export { $items as default };', true], + ['items', 'export { items$ };', false], + ['items', 'export { $items };', false], + ] as const)('an export clause names %s only whole: `%s`', (name, exportLine, kept) => { + // `\b` takes a `$` for a separator: it can't bound `items$` or + // `$items`, and it finds `items` inside both. `other` keeps the + // negative cases above assertParity's node floor. + const source = [ + 'import { create } from "zustand";', + `const ${name} = create((set) => ({ inc: () => set({}) }));`, + 'const other = 1;', + exportLine, + '', + ].join('\n'); + const result = assertParity(`store.${ext}`, source, language); + expect(result.nodes.some((n) => n.kind === 'function' && n.name === 'inc')).toBe(kept); + }); }); describe.each([ diff --git a/__tests__/store-exported-later.test.ts b/__tests__/store-exported-later.test.ts index 19c124f1de..c5cf774ef1 100644 --- a/__tests__/store-exported-later.test.ts +++ b/__tests__/store-exported-later.test.ts @@ -48,6 +48,20 @@ describe('store actions on a later-exported const', () => { expect(fnNames(asDefault)).toContain('bump'); }); + it.each([ + ['items$', 'export { items$ };', true], + ['$items', 'export { $items as default };', true], + ['items', 'export { items$ };', false], + ['items', 'export { $items };', false], + ] as const)('an export clause names %s only whole: `%s`', (name, exportLine, kept) => { + // A `$` belongs to the name: `items$` is exported, `items` is not. + const code = ` + const ${name} = create((set) => ({ inc: () => set({}) })) + ${exportLine} + `; + expect(fnNames(code).includes('inc')).toBe(kept); + }); + it('a const nothing exports keeps its members out of the graph', () => { const code = ` const useStore = create((set) => ({ bump: () => set({}) })) diff --git a/codegraph-kernel/src/tsjs/extractors.rs b/codegraph-kernel/src/tsjs/extractors.rs index ef1d3d5171..461ae6d397 100644 --- a/codegraph-kernel/src/tsjs/extractors.rs +++ b/codegraph-kernel/src/tsjs/extractors.rs @@ -366,8 +366,12 @@ impl<'t> Walker<'t> { // `R` (CRLF mode): JS's multiline `^`/`$` treat `\r` as a line end as // well as `\n`; `(?m)` alone sees only `\n`, and would miss `export // default NAME;\r\n` on every Windows autocrlf checkout. + // Inside `{ … }` the name is bounded by a character that can't + // continue an identifier, not by `\b`, which takes a `$` for a + // separator. The crate has no look-around, so the bounds consume. + // ASCII classes, not `\w`: this crate's `\w` is Unicode, JS's is not. let pattern = format!( - r"(?mR)^[ \t]*export\s+(?:default\s+{n}\s*;?[ \t]*$|\{{[^}}]*\b{n}\b[^}}]*\}})", + r"(?mR)^[ \t]*export\s+(?:default\s+{n}\s*;?[ \t]*$|\{{(?:[^}}]*[^0-9A-Za-z_$}}])?{n}(?:[^0-9A-Za-z_$}}][^}}]*)?\}})", n = n ); match regex::Regex::new(&pattern) { diff --git a/src/extraction/tree-sitter.ts b/src/extraction/tree-sitter.ts index bf8f5f35ab..561f7e6434 100644 --- a/src/extraction/tree-sitter.ts +++ b/src/extraction/tree-sitter.ts @@ -2818,8 +2818,12 @@ export class TreeSitterExtractor { // not the character. Escaped as the kernel's `regex::escape` does, so // both paths decide the same. const n = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + // Inside `{ … }` the name is bounded by a character that can't continue + // an identifier, not by `\b`, which takes a `$` for a separator: it can't + // bound `items$` and finds `items` inside it. Spelled in ASCII, as the + // kernel spells it, since the kernel's `\w` is Unicode. const re = new RegExp( - `^[ \\t]*export\\s+(?:default\\s+${n}\\s*;?[ \\t]*$|\\{[^}]*\\b${n}\\b[^}]*\\})`, + `^[ \\t]*export\\s+(?:default\\s+${n}\\s*;?[ \\t]*$|\\{(?:[^}]*[^0-9A-Za-z_$}])?${n}(?:[^0-9A-Za-z_$}][^}]*)?\\})`, 'm' ); return re.test(this.source); From 249d9a860efca3b33659c0d3b3b6798301fce2ba Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 15:40:12 +0000 Subject: [PATCH 13/23] fix(dart): a comment inside a member chain no longer loses a call or a read (#2385) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tree-sitter-dart keeps a comment as a named node wherever it is written, so in a member chain broken over lines (`tester //`, then `.state(…)` on the next line: the empty `//` keeps dart format from joining the lines) the comment, not `tester`, is the sibling right before the `.state` selector. Both extractors (the TS walker and the native kernel) read that sibling as the receiver or the callee: - A call with a comment between the member and its arguments (`box.grow /* by */ (3)`) was lost, and recorded as a read of `box.grow`. - A getter read (`box //` + `.area`) or a static access (`Config //` + `.instance`) written after a comment was lost. - A call after a comment kept only its bare name. Since #2376 the resolver reads such a chain link back past comments, so those calls already linked correctly; they now carry the receiver in the name. Every sibling step along a member chain now skips `comment` and `documentation_comment` nodes: the callee before an argument part, dartReceiverOf / receiver_of, dartCalleeOfArgPart, the type in front of a constructor's type arguments, and the member read's receiver and next selector. The misparsed-generic-call gate keeps reading raw siblings, and now rejects a comment against the `<` (`ref.read /* c */(p)`), so that shape stays a comparison instead of losing its read. Validated with the kernel loaded on felangel/bloc @b9be1e2, rrousselGit/riverpod @4ba1be2 and flutter/samples @63411527. No edge is added or removed: the 14 comment-split chains there are all in riverpod, and its 5 calls among them gain their receiver and stay unlinked. Kernel/wasm parity has 0 diffs on all three. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/dart-comment-split-chains.test.ts | 147 ++++++++++++++++++ .../kernel-parity/TortureCommentChains.dart | 77 +++++++++ __tests__/kernel-dart-parity.test.ts | 11 +- codegraph-kernel/src/dart.rs | 50 ++++-- docs/design/dart-kernel-port-checklist.md | 22 ++- src/extraction/languages/dart.ts | 56 +++++-- 7 files changed, 332 insertions(+), 32 deletions(-) create mode 100644 __tests__/dart-comment-split-chains.test.ts create mode 100644 __tests__/fixtures/kernel-parity/TortureCommentChains.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e9fa96cf3..4e01daceb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In Dart, a constructor or member written without a body, like flutter_bloc's `const BlocProvider.value(…)`, `Foo._();`, `Point.origin() : x = 0, y = 0;` or an abstract or `external` method, now keeps the `///` documentation and the annotations written above it, the way one with a body already did. Before, that documentation was lost, so searching for words in it didn't find the symbol, and an annotation like `@visibleForTesting` or `@protected` on it wasn't recorded. Re-index Dart projects after upgrading. - In Dart, a call on what a generic lookup returns, like flutter_bloc's `BlocProvider.of(context, listen: false).increment()` or Provider's `Provider.of(context, listen: false).add(item)`, now links to that method of the type in the angle brackets, whether the lookup is declared in your project or comes from a package. Before, such a call often linked nothing — for example whenever the lookup passed `listen: false` — so `callers` and impact missed those methods. A lookup that names no type, like `BlocProvider.of(context)`, still links nothing. Re-index Dart projects after upgrading. (#750) - In JavaScript and TypeScript, a store whose name starts or ends with a `$`, like `const items$ = create(…)`, now has its actions indexed when an `export { … }` list on a later line exports it, as in `export { items$ };` or `export { $items as default };`. Before, those actions were missing from the graph, so their callers and impact came back empty. A store whose name only lacks the `$`, like `items`, is no longer treated as exported by that list. Re-index JavaScript and TypeScript projects after upgrading. +- In Dart, a comment inside a chain of calls no longer loses part of it: a call with a comment before its arguments, like `box.grow /* by */ (3)`, now links to the method it calls, and a getter read or a static access written after a comment, like `Config //` followed by `.instance` on the next line (the empty `//` keeps `dart format` from joining the lines), now counts as a use. Re-index Dart projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/dart-comment-split-chains.test.ts b/__tests__/dart-comment-split-chains.test.ts new file mode 100644 index 0000000000..e731d82e45 --- /dev/null +++ b/__tests__/dart-comment-split-chains.test.ts @@ -0,0 +1,147 @@ +/** + * A comment inside a Dart member chain hid what the chain's parts are. + * + * tree-sitter-dart keeps a comment as a named node wherever it is written, so + * in `tester //` + newline + `.state(…)` — the empty `//` keeps dart format + * from joining the lines, a common idiom in riverpod's tests — the comment, + * not `tester`, sat right before the `.state` selector. Both extractors took + * that node for the receiver: + * + * - a call with a block comment between the member and its arguments + * (`box.grow`, the comment, `(3)`) was lost, and recorded as a read of + * `box.grow`; + * - a getter read (`box //` + `.area`) and a static access (`Config //` + + * `.instance`) written after a comment were lost; + * - a call after a comment kept only its bare name (`state`). The resolver now + * reads a bare chain link back past comments, so that one already linked + * right; it keeps doing so with the receiver in the name. + * + * Every sibling step along a chain now skips comments, so each line extracts + * what it would without the comment. + * + * Runs against the native kernel (when built) and the wasm extractor, which + * must agree. + */ +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; +import type { Node } from '../src/types'; + +const FILES: Record = { + 'pubspec.yaml': 'name: app\nenvironment:\n sdk: ">=3.0.0 <4.0.0"\n', + 'lib/model.dart': `class Counter { + int state(int x) => x; +} + +class Box { + int get area => 1; + int grow(int by) => by; +} + +class Config { + static final Config instance = Config(); +} + +class Foo { + static Foo create() => Foo(); + void bar() {} +} +`, + 'test/scope_test.dart': `import 'package:flutter_test/flutter_test.dart'; +import 'package:app/model.dart'; + +// Same-named methods next to the calls, where a guess by name lands. +class Other { + void bar() {} + int grow(int by) => by; +} + +int inline(Box box) => box.grow /* by */ (3); + +int measure(Box box) { + return box // + .area; +} + +void use() { + final config = Config // + .instance; +} + +void scope(WidgetTester tester) { + tester // + .state(find.byType(Counter)); +} + +void run() { + Foo.create() // + .bar(); +} + +int widen(Box box) { + return box + // a whole-line comment + /// and a dartdoc one + .grow(2); +} +`, +}; + +describe('Dart member chains split by a comment', () => { + let root = ''; + let cg: CodeGraph | undefined; + let kernel: string | undefined; + + beforeEach(() => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-comment-chains-')); + for (const [rel, content] of Object.entries(FILES)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + kernel = process.env.CODEGRAPH_KERNEL; + }); + + afterEach(() => { + cg?.close(); + cg = undefined; + fs.rmSync(root, { recursive: true, force: true }); + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; + }); + + it.each(['default', 'wasm'])('extract each part past the comment (%s)', async (backend) => { + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; + cg = await CodeGraph.init(root, { index: true }); + const graph = cg; + const node = (qualifiedName: string): Node => { + const found = graph.getNodesInFile('test/scope_test.dart').find((n) => n.qualifiedName === qualifiedName); + expect(found, qualifiedName).toBeDefined(); + return found!; + }; + const targets = (from: string, kind: string): string[] => + [...new Set(graph + .getOutgoingEdgesFrom([node(from).id]) + .filter((e) => e.kind === kind) + .map((e) => graph.getNode(e.target)!.qualifiedName))] + .sort(); + + // A comment between the member and its arguments: still a call of the + // receiver's method. + expect(targets('inline', 'calls')).toEqual(['Box::grow']); + + // A getter read runs the getter; a static access references its type. + expect(targets('measure', 'calls')).toEqual(['Box::area']); + expect(targets('use', 'references')).toEqual(['Config']); + + // Calls keep resolving with the receiver in the name: `tester.state(…)` is + // WidgetTester's, a type outside the project, not the one `state` the + // project declares; a chain off a factory goes through what `create` + // returns; the receiver's type picks the method past a run of comments. + expect(targets('scope', 'calls')).toEqual([]); + expect(targets('run', 'calls')).toEqual(['Foo::bar', 'Foo::create']); + expect(targets('widen', 'calls')).toEqual(['Box::grow']); + }); +}); diff --git a/__tests__/fixtures/kernel-parity/TortureCommentChains.dart b/__tests__/fixtures/kernel-parity/TortureCommentChains.dart new file mode 100644 index 0000000000..f39d4eda8a --- /dev/null +++ b/__tests__/fixtures/kernel-parity/TortureCommentChains.dart @@ -0,0 +1,77 @@ +// Comments inside member chains. tree-sitter-dart keeps a comment as a named +// sibling between a chain's parts; every sibling step skips it, so each line +// emits what it would without the comment. +import 'package:flutter_test/flutter_test.dart'; + +class ConfigT { + static final ConfigT instance = ConfigT(); + static ConfigT load() => ConfigT(); + int setting = 0; +} + +class FactoryT { + static FactoryT create() => FactoryT(); + void run() {} +} + +class Box { + int get area => 1; + int grow(int by) => by; +} + +// An initializer, walked for its constant. +final initialized = ConfigT // + .instance; + +class Chains extends Box { + void calls(WidgetTester tester, Box box, List xs) { + // dart format's line-break idiom, a whole-line comment, dartdoc, a run of + // block comments. + tester // + .state(find.byType(Box)); + tester + // a whole-line comment + .pump(); + tester /// doc + .a(); + tester /** doc */ .b(); + tester /* c */ /* d */ .c(); + // A comment between the member and its arguments. + tester.d // c + (); + box.grow /* by */ (3); + // Chains: re-encoded off a capitalized call, bare off a lowercase one. + FactoryT.create() // + .run(); + FactoryT // + .create() // + .run(); + xs // + .map((e) => e) // + .toList(); + // `this` / `super` keep the bare name. + this // + .grow(1); + super // + .grow(2); + } + + int reads(Box box, WidgetTester tester) { + final v = box // + .area; + final w = box.area /* c */ .isEven; + final s = ConfigT // + .instance; + ConfigT // static call: a call and a static reference + .load(); + final t = ConfigT /* setting */ .instance.setting; + // A generic call the grammar reads as two comparisons. + final st = tester // + .state(find.byType(Box)); + // A comment against the `<`: not laid out as a call, so a read and two + // comparisons, as written. + final cr = tester.read /* c */(box); + final dr = tester.read /** doc */(box); + return v + w.hashCode + s.setting + t + st.hashCode; + } +} diff --git a/__tests__/kernel-dart-parity.test.ts b/__tests__/kernel-dart-parity.test.ts index 234051ed7e..6fe570177b 100644 --- a/__tests__/kernel-dart-parity.test.ts +++ b/__tests__/kernel-dart-parity.test.ts @@ -30,9 +30,10 @@ * arguments, as statements and as expressions; TortureGenericCalls.dart: * generic calls parsed as two comparisons, recovered as calls; * TortureDeclarationDocs.dart: the dartdoc and annotations of a - * `declaration`-wrapped member with no body, read from before the wrapper) - * and their CRLF variants - * (derived in-memory — #1329), plus defer and generated-file pins. + * `declaration`-wrapped member with no body, read from before the wrapper; + * TortureCommentChains.dart: comments between a member chain's parts skipped + * by every sibling step) and their CRLF variants (derived in-memory — #1329), + * plus defer and generated-file pins. * * The full-repo sweeps live in scripts/kernel-parity.mjs (shelf/bloc/flutter * with --max-deferral 0.3); this suite keeps the invariant alive in @@ -141,6 +142,10 @@ describe.skipIf(!kernelBuilt)('kernel Dart extraction parity', () => { // external members) take their dartdoc and annotations from before the // wrapper; a field's stay with the field. ['TortureDeclarationDocs.dart', 20], + // Comments between a chain's parts — `tester //` + newline + `.state(…)`, + // dartdoc, block comments, one between a member and its arguments — are + // skipped by every sibling step: calls, chains, reads, static references. + ['TortureCommentChains.dart', 10], ] as const; for (const [file, minNodes] of FIXTURES) { diff --git a/codegraph-kernel/src/dart.rs b/codegraph-kernel/src/dart.rs index 8c4445249c..66426688b3 100644 --- a/codegraph-kernel/src/dart.rs +++ b/codegraph-kernel/src/dart.rs @@ -120,6 +120,31 @@ fn is_prefixed(kind: &str) -> bool { matches!(kind, "unary_expression" | "await_expression") } +/// DART_COMMENTS (dart.ts) — line and block comments, and dartdoc. +fn is_comment(node: Node) -> bool { + matches!(node.kind(), "comment" | "documentation_comment") +} + +/// dartPrevNamed (dart.ts) — the named sibling before `node`, past comments: +/// `tester //` + newline + `.state(…)` puts the comment, not `tester`, right +/// before the `.state` selector. +fn prev_named<'t>(node: Node<'t>) -> Option> { + let mut prev = node.prev_named_sibling(); + while let Some(p) = prev.filter(|p| is_comment(*p)) { + prev = p.prev_named_sibling(); + } + prev +} + +/// dartNextNamed (dart.ts) — the named sibling after `node`, past comments. +fn next_named<'t>(node: Node<'t>) -> Option> { + let mut next = node.next_named_sibling(); + while let Some(n) = next.filter(|n| is_comment(*n)) { + next = n.next_named_sibling(); + } + next +} + struct Scope { row: u32, kind: &'static str, @@ -1082,7 +1107,8 @@ impl<'t> Walker<'t> { if !has_arg_part { return None; } - let prev = node.prev_named_sibling()?; + // Past comments: `box.grow /* by */ (3)` calls `box.grow`. + let prev = prev_named(node)?; return self.callee_name(prev); } @@ -1137,11 +1163,11 @@ impl<'t> Walker<'t> { } /// dartReceiverOf (dart.ts) — the receiver of the member access - /// `selector`: the node in front of it, or the end of an arrow function's - /// body when the grammar ended the arrow in front of a generic call - /// (`(ref) => ref.watch(p)` → `((ref) => ref).watch(p)`). + /// `selector`: the node in front of it, past comments, or the end of an + /// arrow function's body when the grammar ended the arrow in front of a + /// generic call (`(ref) => ref.watch(p)` → `((ref) => ref).watch(p)`). fn receiver_of(&self, selector: Node<'t>) -> Option> { - let prev = selector.prev_named_sibling(); + let prev = prev_named(selector); let body = prev .filter(|p| p.kind() == "function_expression") .and_then(|p| p.named_child(p.named_child_count().checked_sub(1)?)); @@ -1242,8 +1268,10 @@ impl<'t> Walker<'t> { if !matches!(args.kind(), "parenthesized_expression" | "record_literal") || args.start_byte() != gt.end_byte() { return None; } + // A comment against the `<` (`ref.read /* c */(p)`) is a + // sibling of its own, so the callee is not against it. let before = lt.prev_named_sibling()?; - if before.end_byte() != lt.start_byte() { + if is_comment(before) || before.end_byte() != lt.start_byte() { return None; } // The type argument: `T`, `p.T`, `T<…>` or `p.T<…>`, and nothing else. @@ -1321,7 +1349,7 @@ impl<'t> Walker<'t> { /// dartCalleeOfArgPart (dart.ts:100-116). fn callee_of_arg_part(&self, arg_part: Node<'t>) -> Option { - let prev = arg_part.prev_named_sibling()?; + let prev = prev_named(arg_part)?; if prev.kind() == "identifier" { return Some(self.text(prev).to_string()); } @@ -1339,7 +1367,7 @@ impl<'t> Walker<'t> { found }); if let Some(method_id) = method_id { - let accessor_prev = prev.prev_named_sibling(); + let accessor_prev = prev_named(prev); if let Some(ap) = accessor_prev { if ap.kind() == "identifier" { return Some(format!("{}.{}", self.text(ap), self.text(method_id))); @@ -1364,7 +1392,7 @@ impl<'t> Walker<'t> { if selector.named_child(0)?.kind() != "type_arguments" { return None; } - let type_node = selector.prev_named_sibling()?; + let type_node = prev_named(selector)?; if type_node.kind() != "identifier" { return None; } @@ -1687,11 +1715,11 @@ impl<'t> Walker<'t> { found }); let Some(member) = member else { return }; - let Some(receiver) = node.prev_named_sibling() else { return }; + let Some(receiver) = prev_named(node) else { return }; if receiver.kind() != "identifier" { return; } - let next = node.next_named_sibling(); + let next = next_named(node); if let Some(next) = next { if next.kind() == "selector" { let mut nc = next.walk(); diff --git a/docs/design/dart-kernel-port-checklist.md b/docs/design/dart-kernel-port-checklist.md index 672e41e5d1..fa80223359 100644 --- a/docs/design/dart-kernel-port-checklist.md +++ b/docs/design/dart-kernel-port-checklist.md @@ -722,6 +722,18 @@ extract-mini.txt): | local-lambda body `final lam = (int a) { helper(a); }` | function_expression recursed transparently | `helper` attributed to the ENCLOSING function; `lam(5)` → `lam` | | `final p = Provider((ref) => Repo(ref.watch(d)))`, `static var s = make()`, `final _c = Controller();` in a class, `var v = load();` | the hook's walkInitializer (§Constants) | the full matrix, from the constant / the class / the file | | ctor initializers (`: size = seed()`), enum-constant args (`ok(200)`), default param values | never body-walked | NOTHING | +| `tester //` + newline + `.state(x)`, `box.grow /* by */ (3)` | comments are named SIBLINGS between the chain's parts | `tester.state` / `box.grow` — every sibling step skips `comment` and `documentation_comment` (dartPrevNamed / dartNextNamed; kernel `prev_named` / `next_named`), so a comment changes nothing | + +Every sibling step along a member chain goes past comments: the callee before +an argument part, dartReceiverOf / receiver_of, dartCalleeOfArgPart's two, +dartTypeArgumentsReceiver's type, and dartMemberRead's receiver and its +next-selector check. tree-sitter-dart keeps a comment as a named node wherever +it is written, so before (2026-10-06) a comment between a member and its +arguments lost the call and emitted a member read, a getter read or static +access after a comment (`Config //`, dart format's line-break idiom) was lost, +and a call after one kept only its bare name. The misparsed-generic-call +layout checks below still read the raw siblings: a comment there means the +code is not laid out as a call. extractCall (:3684), LITERAL_RECEIVER_TYPES (:373-388), SKIP_RECEIVERS, the parenthesized-conversion regex (:4530), template-strip — ALL UNREACHABLE for @@ -743,7 +755,10 @@ selector (`p.Repo`) and/or a type_arguments-only selector (`Map`); the callee part sits under `unary_expression` / `await_expression` for `await` and prefix operators. Recovered at the `<` when the type names a type (`/^[_$]*[A-Z]/` or `int double num bool dynamic void`), `<` touches the callee and `(` touches -the `>`; `a < B > (c)`, `a(c)` and `a (c)` stay comparisons. The +the `>`; `a < B > (c)`, `a(c)` and `a (c)` stay comparisons, and so does +`a.b /* c */(c)`: the comment is a sibling of its own against the `<`, so +it is rejected as the callee (else the gate passed with no call, and the +comment-skipping member read was suppressed). The recovered form emits what the parsed call does: - `calls` at the `<` (the parsed call's argument_part starts there); @@ -773,8 +788,9 @@ do not, so `() => BlocProvider.of(context).increment()` keeps Called from the body walker only (:5218). The DART-SPECIFIC branch (the shared MEMBER_ACCESS_TYPES path is never reached — it returns first): -node.type === `selector` AND it has NO `argument_part` child AND -previousNamedSibling is an `identifier` matching `/^[A-Z][A-Za-z0-9_]*$/` → +node.type === `selector` AND it has NO `argument_part` child AND the +receiver (dartReceiverOf: the previous named sibling past comments) is an +`identifier` matching `/^[A-Z][A-Za-z0-9_]*$/` → `references ` from the enclosing symbol at the **IDENTIFIER's (receiver's) position** (pushStaticMemberRef :4800). Pins: diff --git a/src/extraction/languages/dart.ts b/src/extraction/languages/dart.ts index 7b2228b61b..2b74652b1a 100644 --- a/src/extraction/languages/dart.ts +++ b/src/extraction/languages/dart.ts @@ -63,17 +63,40 @@ function isDartFieldOrTopLevelEntry(node: SyntaxNode): boolean { return owner?.type === 'declaration' && owner.parent !== null && DART_MEMBER_BODIES.has(owner.parent.type); } +/** The comments tree-sitter-dart keeps as named nodes: line and block comments, and dartdoc. */ +const DART_COMMENTS: ReadonlySet = new Set(['comment', 'documentation_comment']); + +/** + * The named sibling before `node`, past any comments. A Dart member chain is + * an identifier followed by sibling selectors, and the grammar keeps a comment + * as a sibling wherever it is written, so in `tester //` + newline + + * `.state(…)` (the empty `//` keeps dart format from joining the lines) the + * comment, not `tester`, is right before the `.state` selector. + */ +function dartPrevNamed(node: SyntaxNode): SyntaxNode | null { + let prev = node.previousNamedSibling; + while (prev && DART_COMMENTS.has(prev.type)) prev = prev.previousNamedSibling; + return prev; +} + +/** The named sibling after `node`, past any comments (see dartPrevNamed). */ +function dartNextNamed(node: SyntaxNode): SyntaxNode | null { + let next = node.nextNamedSibling; + while (next && DART_COMMENTS.has(next.type)) next = next.nextNamedSibling; + return next; +} + /** - * The receiver of the member access `selector`: the node in front of it, or - * the end of an arrow function's body when the grammar ended the arrow in - * front of a generic call — `(ref) => ref.watch(p)` comes out as - * `((ref) => ref).watch(p)`. Dart writes a member access on the arrow - * itself in parentheses, so a receiver in that place is never the arrow. It - * names the call (`ref.watch`) and a static member's class; a call chained on - * that call keeps its bare name (see dartMisparsedGenericCall). + * The receiver of the member access `selector`: the node in front of it, past + * any comments, or the end of an arrow function's body when the grammar ended + * the arrow in front of a generic call — `(ref) => ref.watch(p)` comes + * out as `((ref) => ref).watch(p)`. Dart writes a member access on the + * arrow itself in parentheses, so a receiver in that place is never the + * arrow. It names the call (`ref.watch`) and a static member's class; a call + * chained on that call keeps its bare name (see dartMisparsedGenericCall). */ export function dartReceiverOf(selector: SyntaxNode): SyntaxNode | null { - const prev = selector.previousNamedSibling; + const prev = dartPrevNamed(selector); const body = prev?.type === 'function_expression' ? prev.lastNamedChild : null; return body?.type === 'function_expression_body' ? body.lastNamedChild : prev; } @@ -123,8 +146,10 @@ export function dartMisparsedGenericCall(lt: SyntaxNode): DartMisparsedCall | un const args = outer.namedChild(2); if (args?.type !== 'parenthesized_expression' && args?.type !== 'record_literal') return undefined; if (args.startIndex !== gt.endIndex) return undefined; + // A comment against the `<` (`ref.read /* c */(p)`) is a sibling of + // its own, so the callee is not against it: not laid out as a call. const before = lt.previousNamedSibling; - if (!before || before.endIndex !== lt.startIndex) return undefined; + if (!before || DART_COMMENTS.has(before.type) || before.endIndex !== lt.startIndex) return undefined; // The type argument: `T`, `p.T`, `T<…>` or `p.T<…>`, and nothing else. const head = lt.nextNamedSibling; if (head?.type !== 'identifier') return undefined; @@ -194,9 +219,9 @@ export function dartMemberRead( ); const member = accessor?.namedChildren.find((c: SyntaxNode) => c.type === 'identifier'); if (!member) return undefined; - const receiver = node.previousNamedSibling; + const receiver = dartPrevNamed(node); if (receiver?.type !== 'identifier') return undefined; - const next = node.nextNamedSibling; + const next = dartNextNamed(node); if (next?.type === 'selector' && next.namedChildren.some((c: SyntaxNode) => c.type === 'argument_part')) { return undefined; } @@ -322,7 +347,7 @@ function dartTypeArgumentsReceiver(selector: SyntaxNode | null): string | undefi if (selector?.type !== 'selector' || selector.namedChildCount !== 1 || selector.namedChild(0)?.type !== 'type_arguments') { return undefined; } - const type = selector.previousNamedSibling; + const type = dartPrevNamed(selector); return type?.type === 'identifier' ? type.text : undefined; } @@ -333,7 +358,7 @@ function dartTypeArgumentsReceiver(selector: SyntaxNode | null): string | undefi * `Foo.create`, a bare `create`, or `Foo` (constructor) — or undefined. */ function dartCalleeOfArgPart(argPart: SyntaxNode): string | undefined { - const prev = argPart.previousNamedSibling; + const prev = dartPrevNamed(argPart); if (!prev) return undefined; if (prev.type === 'identifier') return prev.text; // bare `Foo()` / `create()` if (prev.type === 'selector') { @@ -342,7 +367,7 @@ function dartCalleeOfArgPart(argPart: SyntaxNode): string | undefined { ); const methodId = accessor?.namedChildren.find((c: SyntaxNode) => c.type === 'identifier'); if (methodId) { - const accessorPrev = prev.previousNamedSibling; + const accessorPrev = dartPrevNamed(prev); if (accessorPrev?.type === 'identifier') return accessorPrev.text + '.' + methodId.text; const typeName = dartTypeArgumentsReceiver(accessorPrev); if (typeName) return typeName + '.' + methodId.text; @@ -673,7 +698,8 @@ export const dartExtractor: LanguageExtractor = { const hasArgPart = node.namedChildren.some((c: SyntaxNode) => c.type === 'argument_part'); if (!hasArgPart) return undefined; - const prev = node.previousNamedSibling; + // Past comments: `box.grow /* by */ (3)` calls `box.grow`. + const prev = dartPrevNamed(node); return prev ? dartCallee(prev) : undefined; } From 0c860c00b3472573d88e5c96c92a98624685a737 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 16:27:05 +0000 Subject: [PATCH 14/23] fix(dart): a bare call or type name reaches only what its library can see (#2386) A receiver-less Dart call, constructor call or type name now links only to a top-level declaration its library can see: one in the library itself (the file and its parts) or one exported by a library it imports without a prefix, through export chains and show/hide. A type written through an import prefix (`p.Report`) means what that import exports. It is a candidate filter ahead of the ranking in matchByExactName and matchFuzzy, so a visible namesake wins, and a library's own declaration shadows an imported one. The library model (pubspec packages, package: and relative URIs, part / part of, conditional imports) is src/resolution/dart-libraries.ts. A bare call also never reaches another type's enum constant or static constant, a generic `extension on X` counts as unnamed, and an unnamed extension applies in every part of its library. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/dart-library-visibility.test.ts | 344 +++++++++++ src/resolution/dart-libraries.ts | 693 ++++++++++++++++++++++ src/resolution/index.ts | 2 + src/resolution/name-matcher.ts | 96 ++- 5 files changed, 1130 insertions(+), 6 deletions(-) create mode 100644 __tests__/dart-library-visibility.test.ts create mode 100644 src/resolution/dart-libraries.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e01daceb1..07ab7ec64c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In Dart, a call on what a generic lookup returns, like flutter_bloc's `BlocProvider.of(context, listen: false).increment()` or Provider's `Provider.of(context, listen: false).add(item)`, now links to that method of the type in the angle brackets, whether the lookup is declared in your project or comes from a package. Before, such a call often linked nothing — for example whenever the lookup passed `listen: false` — so `callers` and impact missed those methods. A lookup that names no type, like `BlocProvider.of(context)`, still links nothing. Re-index Dart projects after upgrading. (#750) - In JavaScript and TypeScript, a store whose name starts or ends with a `$`, like `const items$ = create(…)`, now has its actions indexed when an `export { … }` list on a later line exports it, as in `export { items$ };` or `export { $items as default };`. Before, those actions were missing from the graph, so their callers and impact came back empty. A store whose name only lacks the `$`, like `items`, is no longer treated as exported by that list. Re-index JavaScript and TypeScript projects after upgrading. - In Dart, a comment inside a chain of calls no longer loses part of it: a call with a comment before its arguments, like `box.grow /* by */ (3)`, now links to the method it calls, and a getter read or a static access written after a comment, like `Config //` followed by `.instance` on the next line (the empty `//` keeps `dart format` from joining the lines), now counts as a use. Re-index Dart projects after upgrading. +- In Dart, a call, a constructor call or a type written without a receiver now links only to a declaration the file can see: one in its own library (the file and its `part` files) or one exported by a library it imports, with `export` chains, `show`, `hide` and `as` prefixes followed the way Dart follows them. So a generated `.g.dart` file reaches its own library's function or type instead of a same-named one in a neighbouring file, a call to a package function such as `fakeAsync`, `runApp` or `unawaited` no longer links to an unrelated project function of that name, and a bare call is never taken for another type's enum value or static constant. Re-index Dart projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/dart-library-visibility.test.ts b/__tests__/dart-library-visibility.test.ts new file mode 100644 index 0000000000..f171430ce3 --- /dev/null +++ b/__tests__/dart-library-visibility.test.ts @@ -0,0 +1,344 @@ +/** + * A Dart name written without a receiver — a call, a type — means a + * declaration its library can see: its own (the file and its `part`s), or one + * a library it imports without a prefix exports, through `export` chains and + * `show` / `hide`. riverpod's generated `async.g.dart` (`part of + * 'async.dart'`) called the `family(…)` async.dart declares, and the call went + * to the `family` of annotated.dart beside it; a test's `fakeAsync(…)` from + * package:fake_async went to a vendored copy nobody imports. + */ +import { describe, it, expect, afterAll, beforeAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; +import { readDartDirectives } from '../src/resolution/dart-libraries'; + +function writeTree(root: string, files: Record): void { + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } +} + +/** ` -> :` for every edge out of `file`. */ +function edgesFrom(cg: CodeGraph, file: string): string[] { + const ids = cg.getNodesInFile(file).map((n) => n.id); + return cg.getOutgoingEdgesFrom(ids) + .filter((e) => e.kind !== 'contains') + .map((e) => { + const t = cg.getNode(e.target)!; + return `${e.kind} ${e.line} ${String(e.metadata?.refName ?? '')} -> ${t.filePath}:${t.qualifiedName}`; + }); +} + +describe('Dart library visibility', () => { + let root = ''; + let cg: CodeGraph; + + beforeAll(async () => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-libs-')); + writeTree(root, { + 'pubspec.yaml': 'name: app\n', + // Generated parts call and name their own library's declarations; a + // library beside them declares the same names. + 'test/integration/annotated.dart': `part 'annotated.g.dart'; + +String family(Object ref, int id) => 'family $id'; +`, + 'test/integration/annotated.g.dart': `part of 'annotated.dart'; + +String annotatedGenerated(Object ref) => family(ref, 1); +`, + 'test/integration/async.dart': `import 'dart:async'; + +part 'async.g.dart'; + +Future family(Object ref, int first) async => '$first'; + +class GenericClass {} +`, + 'test/integration/async.g.dart': `part of 'async.dart'; + +Future asyncGenerated(Object ref) { + return family(ref, 2); +} + +final GenericClass generic = GenericClass(); +`, + 'test/integration/annotated_types.dart': `class GenericClass {} +`, + // package:fake_async's function, and a vendored copy no file imports. + 'test/third_party/fake_async.dart': `T fakeAsync(T Function(Object async) callback) => callback(Object()); +`, + 'test/src/core/devtool_test.dart': `import 'package:fake_async/fake_async.dart'; + +void main() { + fakeAsync((async) {}); +} +`, + // A test imports one utils library; an old copy declares the same function. + 'test/old/utils.dart': `List errorsOf(void Function() cb) => []; +`, + 'test/src/utils.dart': `List errorsOf(void Function() cb) => []; +`, + 'test/feature/uni_directional_test.dart': `import '../src/utils.dart'; + +void main() { + errorsOf(() {}); +} +`, + // A package whose barrel exports with combinators; a prefixed import; a hidden name. + 'packages/kit/pubspec.yaml': 'name: kit\n', + 'packages/kit/lib/kit.dart': `export 'src/impl.dart' + show + // the public API + shown, + Widget; +export 'src/cond_stub.dart' if (dart.library.io) 'src/cond_io.dart'; +`, + 'packages/kit/lib/src/impl.dart': `int shown() => 1; +int notShown() => 2; +class Widget {} +`, + 'packages/kit/lib/src/cond_stub.dart': `int platformName() => 0; +`, + 'packages/kit/lib/src/cond_io.dart': `int platformName() => 1; +`, + 'packages/kit/lib/src/prefixed.dart': `int viaPrefix() => 3; +class Report {} +`, + 'packages/kit/lib/src/hidden.dart': `int hiddenOne() => 4; +int keptOne() => 5; +`, + 'lib/main.dart': `import 'package:kit/kit.dart'; +import 'package:kit/src/prefixed.dart' as p; +import 'package:kit/src/hidden.dart' hide hiddenOne; + +void run(p.Report report) { + shown(); + notShown(); + platformName(); + viaPrefix(); + hiddenOne(); + keptOne(); + Widget(); +} +`, + // Another library's Report, which main.dart does not import. + 'lib/a_report.dart': `class Report {} +`, + // A part declared by library name, and a namesake in another library. + 'lib/named.dart': `library app.named; + +part 'named_part.dart'; + +int namedHelper() => 6; +`, + 'lib/named_part.dart': `part of app.named; + +int usesNamed() => namedHelper(); +`, + 'lib/other_named.dart': `int namedHelper() => 7; +`, + // A library's own declaration shadows the one it imports. + 'lib/a_util.dart': `int helper() => 1; +`, + 'lib/feature.dart': `import 'a_util.dart'; + +part 'feature_part.dart'; + +int runFeature() => helper(); +`, + 'lib/feature_part.dart': `part of 'feature.dart'; + +int helper() => 2; +`, + // A bare call never reaches another type's enum constant or static constant. + 'lib/kinds.dart': `enum Level { info, warning } + +class TypeChecker { + static const allOf = 'any'; +} +`, + 'lib/check.dart': `import 'package:mason_logger/mason_logger.dart'; +import 'package:matcher/matcher.dart'; + +void check(Object value) { + info('checking'); + expect(value, allOf([isNotNull])); +} +`, + // An unnamed extension on Color is no Color. + 'lib/colors.dart': `import 'package:flutter/material.dart'; + +extension on Color { + Color brighten() => this; +} +`, + // Nor is a generic one, beside the file that names the type. + 'lib/models/box.dart': `class Box { + T? value; +} +`, + 'lib/widgets/box_ext.dart': `import '../models/box.dart'; + +extension on Box { + bool get isEmpty => value == null; +} +`, + 'lib/widgets/panel.dart': `import '../models/box.dart'; +import 'box_ext.dart'; + +class Panel { + final Box box; + Panel(this.box); +} +`, + // An unnamed extension applies in every file of its library. + 'lib/shapes/shapes.dart': `part 'area_ext.dart'; +part 'use.dart'; + +class Shape {} +`, + 'lib/shapes/area_ext.dart': `part of 'shapes.dart'; + +extension on Shape { + int area() => 1; +} +`, + 'lib/shapes/use.dart': `part of 'shapes.dart'; + +int total(Shape s) => s.area(); +`, + }); + cg = await CodeGraph.init(root, { index: true }); + }); + + afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + }); + + it("links a generated part's call to its own library's function", () => { + const edges = edgesFrom(cg, 'test/integration/async.g.dart'); + expect(edges).toContain('calls 4 family -> test/integration/async.dart:family'); + expect(edges.filter((e) => e.includes('annotated'))).toEqual([]); + }); + + it("links a generated part's type to its own library's type", () => { + const edges = edgesFrom(cg, 'test/integration/async.g.dart').filter((e) => e.includes('GenericClass')); + expect(edges.length).toBeGreaterThan(0); + expect(edges.every((e) => e.endsWith('test/integration/async.dart:GenericClass'))).toBe(true); + }); + + it('links nothing for a function no imported library declares', () => { + expect(edgesFrom(cg, 'test/src/core/devtool_test.dart').filter((e) => e.includes('fakeAsync'))).toEqual([]); + }); + + it('links the imported library over a namesake no import names', () => { + expect(edgesFrom(cg, 'test/feature/uni_directional_test.dart')).toContain('calls 4 errorsOf -> test/src/utils.dart:errorsOf'); + }); + + it('follows export chains, show, hide and import prefixes', () => { + const edges = edgesFrom(cg, 'lib/main.dart'); + expect(edges).toContain('calls 6 shown -> packages/kit/lib/src/impl.dart:shown'); + expect(edges).toContain('calls 11 keptOne -> packages/kit/lib/src/hidden.dart:keptOne'); + expect(edges.some((e) => e.startsWith('instantiates 12 Widget -> packages/kit/lib/src/impl.dart:Widget'))).toBe(true); + expect(edges.some((e) => / platformName -> packages\/kit\/lib\/src\/cond_(?:stub|io)\.dart:platformName$/.test(e))).toBe(true); + // Not shown, only reachable through the prefix, hidden. + expect(edges.filter((e) => / (?:notShown|viaPrefix|hiddenOne) /.test(e))).toEqual([]); + // `p.Report` is the prefixed library's. + expect(edges.filter((e) => e.includes(' Report '))).toEqual(['references 5 Report -> packages/kit/lib/src/prefixed.dart:Report']); + }); + + it('finds the library a part names by library name', () => { + expect(edgesFrom(cg, 'lib/named_part.dart')).toContain('calls 3 namedHelper -> lib/named.dart:namedHelper'); + }); + + it("prefers the library's own declaration to an imported one", () => { + expect(edgesFrom(cg, 'lib/feature.dart').filter((e) => e.includes('helper'))).toEqual(['calls 5 helper -> lib/feature_part.dart:helper']); + }); + + it("never reaches another type's enum constant or static constant by a bare call", () => { + expect(edgesFrom(cg, 'lib/check.dart').filter((e) => !e.startsWith('imports '))).toEqual([]); + }); + + it('never takes an unnamed extension for the type it extends', () => { + expect(edgesFrom(cg, 'lib/colors.dart').filter((e) => e.includes('Color'))).toEqual([]); + expect(edgesFrom(cg, 'lib/widgets/panel.dart').filter((e) => e.includes(' Box '))).toEqual(['references 5 Box -> lib/models/box.dart:Box']); + }); + + it("applies an unnamed extension in every file of its library", () => { + expect(edgesFrom(cg, 'lib/shapes/use.dart').some((e) => e.endsWith('-> lib/shapes/area_ext.dart:Shape::area'))).toBe(true); + }); +}); + +describe('Dart files outside any package', () => { + let root = ''; + let cg: CodeGraph; + + beforeAll(async () => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-nopkg-')); + // A mason brick's template: no pubspec.yaml says what its imports mean. + writeTree(root, { + 'bricks/feature/__brick__/helper.dart': `int helper() => 1; +`, + 'bricks/feature/__brick__/page.dart': `import 'package:{{name}}/helper.dart'; + +int page() => helper(); +`, + }); + cg = await CodeGraph.init(root, { index: true }); + }); + + afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + }); + + it('are resolved as before, by name', () => { + expect(edgesFrom(cg, 'bricks/feature/__brick__/page.dart')).toContain('calls 3 helper -> bricks/feature/__brick__/helper.dart:helper'); + }); +}); + +describe('readDartDirectives', () => { + it('reads every directive up to the first declaration', () => { + const d = readDartDirectives(`// Copyright +@TestOn('vm') +library app.main; + +import 'dart:async'; +import 'package:kit/kit.dart' show A, B hide B; +import 'stub.dart' if (dart.library.io) 'io.dart' if (dart.library.js_interop == 'true') 'web.dart'; +import 'lazy.dart' deferred as lazy; +export 'src/a.dart' + show + // one + One, + Two; +part 'main.g.dart'; + +void main() {} +import 'late.dart'; +`); + expect(d.libraryName).toBe('app.main'); + expect(d.partOf).toBeNull(); + expect(d.parts).toEqual(['main.g.dart']); + expect(d.imports.map((i) => i.uris)).toEqual([['dart:async'], ['package:kit/kit.dart'], ['stub.dart', 'io.dart', 'web.dart'], ['lazy.dart']]); + expect(d.imports.map((i) => i.prefix)).toEqual([null, null, null, 'lazy']); + expect([...d.imports[1]!.filter.show!]).toEqual(['A', 'B']); + expect([...d.imports[1]!.filter.hide!]).toEqual(['B']); + expect(d.exports.map((e) => [e.uris, [...(e.filter.show ?? [])]])).toEqual([[['src/a.dart'], ['One', 'Two']]]); + }); + + it('reads `part of` by URI and by library name, and an unnamed library', () => { + expect(readDartDirectives(`part of 'async.dart';\n`).partOf).toEqual({ uri: 'async.dart' }); + expect(readDartDirectives(`part of app.named;\n`).partOf).toEqual({ name: 'app.named' }); + expect(readDartDirectives(`/// Docs\nlibrary;\n\nimport 'a.dart';\n`)).toMatchObject({ libraryName: '', imports: [{ uris: ['a.dart'] }] }); + }); + + it('stops at a declaration that looks like a directive', () => { + expect(readDartDirectives(`import 'a.dart';\npart() => 1;\nimport 'b.dart';\n`).imports.map((i) => i.uris[0])).toEqual(['a.dart']); + }); +}); diff --git a/src/resolution/dart-libraries.ts b/src/resolution/dart-libraries.ts new file mode 100644 index 0000000000..18c2d7930f --- /dev/null +++ b/src/resolution/dart-libraries.ts @@ -0,0 +1,693 @@ +/** + * Which files' top-level declarations a Dart file can name without a prefix. + * + * A Dart library is a file and its `part`s. Its top-level scope holds its own + * declarations, private `_` names included, and every name exported by a + * library it imports without a prefix: that library's own public declarations + * and, through its `export`s, other libraries'. Every import and export is + * narrowed by its `show` / `hide` combinators. A conditional import (`import + * 'stub.dart' if (dart.library.io) 'io.dart'`) brings in every alternative. + * `dart:` libraries and packages outside the repository (flutter, test, + * mockito, …) export nothing of the project. + * + * `package:/` is `/lib/` of the package whose + * pubspec.yaml says `name: `: the nearest pubspec.yaml above an indexed + * .dart file, never above the project root. When packages share a name + * (example apps), the importing file's own package wins, then the one + * enclosing it, else all of them count. + * + * Directives are read from the head of each file at resolution time; + * extraction, and the kernel's, are unchanged. Where the library cannot be + * established — a `part of` naming no library this can find, a file it cannot + * read, a file in no package — every file counts as visible, so the rule only + * narrows where the library is known. + */ +import * as path from 'path'; +import type { ResolutionContext } from './types'; + +/** The names an import's or export's `show` / `hide` combinators let through; `show` null lets every name through. */ +export interface NameFilter { + readonly show: ReadonlySet | null; + readonly hide: ReadonlySet | null; + /** Identifies equal filters, so a namespace keeps each once. */ + readonly key: string; +} + +const EVERY_NAME: NameFilter = { show: null, hide: null, key: '*|' }; + +function makeFilter(show: ReadonlySet | null, hide: ReadonlySet | null): NameFilter { + const hidden = hide && hide.size > 0 ? hide : null; + if (show === null && hidden === null) return EVERY_NAME; + return { show, hide: hidden, key: `${show ? [...show].sort().join(',') : '*'}|${hidden ? [...hidden].sort().join(',') : ''}` }; +} + +/** `a`, then `b`: a name gets through when both let it. */ +function composeFilters(a: NameFilter, b: NameFilter): NameFilter { + if (a === EVERY_NAME) return b; + if (b === EVERY_NAME) return a; + const show = a.show && b.show ? new Set([...a.show].filter((n) => b.show!.has(n))) : (a.show ?? b.show); + const hide = a.hide && b.hide ? new Set([...a.hide, ...b.hide]) : (a.hide ?? b.hide); + return makeFilter(show, hide); +} + +function lets(filter: NameFilter, name: string): boolean { + return (filter.show === null || filter.show.has(name)) && (filter.hide === null || !filter.hide.has(name)); +} + +/** An `import` or `export` directive. */ +export interface DartNamespaceDirective { + /** The URI, then each conditional alternative (`if (dart.library.io) 'io.dart'`). */ + uris: string[]; + /** The prefix of `import '…' as p`, or null. */ + prefix: string | null; + filter: NameFilter; +} + +/** The directives at the head of a Dart file. */ +export interface DartDirectives { + /** `library a.b;` gives `a.b`, `library;` gives '', no directive null. */ + libraryName: string | null; + partOf: { uri: string } | { name: string } | null; + parts: string[]; + imports: DartNamespaceDirective[]; + exports: DartNamespaceDirective[]; +} + +const DIRECTIVE_KEYWORDS: ReadonlySet = new Set(['library', 'import', 'export', 'part']); +const IDENTIFIER = /[A-Za-z_$][\w$]*/y; + +/** The index past the whitespace and comments at `i` (Dart block comments nest). */ +function skipTrivia(src: string, i: number): number { + const n = src.length; + while (i < n) { + const c = src.charCodeAt(i); + if (c === 32 || (c >= 9 && c <= 13) || c === 0xfeff) { + i++; + } else if (c === 47 && src.charCodeAt(i + 1) === 47) { + const newline = src.indexOf('\n', i + 2); + i = newline < 0 ? n : newline + 1; + } else if (c === 47 && src.charCodeAt(i + 1) === 42) { + let depth = 1; + i += 2; + while (i < n && depth > 0) { + if (src.charCodeAt(i) === 47 && src.charCodeAt(i + 1) === 42) { + depth++; + i += 2; + } else if (src.charCodeAt(i) === 42 && src.charCodeAt(i + 1) === 47) { + depth--; + i += 2; + } else { + i++; + } + } + } else { + break; + } + } + return i; +} + +/** The string literal at `i` — `'…'`, `"…"`, triple-quoted or raw — as its value and the index past it, or null. */ +function readString(src: string, i: number): { value: string; end: number } | null { + let raw = false; + if (src[i] === 'r' && (src[i + 1] === "'" || src[i + 1] === '"')) { + raw = true; + i++; + } + const quote = src[i]; + if (quote !== "'" && quote !== '"') return null; + const close = src.startsWith(quote.repeat(3), i) ? quote.repeat(3) : quote; + let j = i + close.length; + let value = ''; + while (j < src.length) { + if (src.startsWith(close, j)) return { value, end: j + close.length }; + const c = src[j]!; + if (c === '\n' && close.length === 1) return null; + if (c === '\\' && !raw) { + value += src[j + 1] ?? ''; + j += 2; + } else if (c === '$' && !raw && src[j + 1] === '{') { + let depth = 1; + j += 2; + while (j < src.length && depth > 0) { + const inner = readString(src, j); + if (inner) { + j = inner.end; + continue; + } + if (src[j] === '{') depth++; + else if (src[j] === '}') depth--; + j++; + } + } else { + value += c; + j++; + } + } + return null; +} + +/** The index past the balanced `open` … `close` group at `i`, strings and comments skipped; -1 if it never closes. */ +function skipGroup(src: string, i: number, open: string, close: string): number { + let depth = 0; + while (i < src.length) { + i = skipTrivia(src, i); + const literal = readString(src, i); + if (literal) { + i = literal.end; + continue; + } + const c = src[i]; + if (c === open) depth++; + else if (c === close && --depth === 0) return i + 1; + i++; + } + return -1; +} + +/** The index past the metadata annotation at `i` (`@TestOn('vm')`, `@Tags(['slow'])`, `@JS()`). */ +function skipAnnotation(src: string, i: number): number { + i++; + for (;;) { + i = skipTrivia(src, i); + IDENTIFIER.lastIndex = i; + const name = IDENTIFIER.exec(src); + if (!name) return i; + i += name[0].length; + const next = skipTrivia(src, i); + if (src[next] !== '.') break; + i = next + 1; + } + i = skipTrivia(src, i); + if (src[i] === '<') { + const end = skipGroup(src, i, '<', '>'); + if (end < 0) return src.length; + i = skipTrivia(src, end); + } + if (src[i] === '(') { + const end = skipGroup(src, i, '(', ')'); + return end < 0 ? src.length : end; + } + return i; +} + +type DirectiveToken = + | { kind: 'string'; value: string } + | { kind: 'word'; value: string } + | { kind: 'condition' } + | { kind: 'punctuation'; value: string }; + +/** + * The tokens of a directive, from just past its keyword to its `;`, and the + * index past that `;` — or null when a body (`{`, `=>`) comes first, as in a + * function named `part`, or the file ends. + */ +function readDirectiveTokens(src: string, i: number): { tokens: DirectiveToken[]; end: number } | null { + const tokens: DirectiveToken[] = []; + for (;;) { + i = skipTrivia(src, i); + if (i >= src.length || tokens.length > 2000) return null; + const c = src[i]!; + if (c === ';') return { tokens, end: i + 1 }; + if (c === '{' || c === '}' || (c === '=' && src[i + 1] === '>')) return null; + const literal = readString(src, i); + if (literal) { + tokens.push({ kind: 'string', value: literal.value }); + i = literal.end; + continue; + } + if (c === '(') { + // A configuration condition: `(dart.library.io)`, `(dart.library.js_interop == 'true')`. + i = skipGroup(src, i, '(', ')'); + if (i < 0) return null; + tokens.push({ kind: 'condition' }); + continue; + } + IDENTIFIER.lastIndex = i; + const word = IDENTIFIER.exec(src); + if (word) { + tokens.push({ kind: 'word', value: word[0] }); + i += word[0].length; + continue; + } + tokens.push({ kind: 'punctuation', value: c }); + i++; + } +} + +/** A dotted library name (`app.named`), as the words and dots it is written with. */ +function dottedName(tokens: readonly DirectiveToken[]): string | null { + let name = ''; + for (const t of tokens) { + if (t.kind === 'word' || (t.kind === 'punctuation' && t.value === '.')) name += t.value; + else return null; + } + return name; +} + +/** Record the directive `keyword` with `tokens` in `out`; false when the tokens are no such directive. */ +function addDirective(out: DartDirectives, keyword: string, tokens: DirectiveToken[]): boolean { + const first = tokens[0]; + if (keyword === 'library') { + const name = dottedName(tokens); + if (name === null) return false; + out.libraryName = name; + return true; + } + if (keyword === 'part') { + if (first?.kind === 'word' && first.value === 'of') { + const target = tokens[1]; + const name = target?.kind === 'string' ? null : dottedName(tokens.slice(1)); + if (target?.kind === 'string') out.partOf = { uri: target.value }; + else if (name) out.partOf = { name }; + else return false; + return true; + } + if (first?.kind !== 'string') return false; + out.parts.push(first.value); + return true; + } + if (first?.kind !== 'string') return false; + const uris = [first.value]; + let prefix: string | null = null; + let filter = EVERY_NAME; + let k = 1; + // Adjacent literals are one string: `'package:a/' 'b.dart'`. + for (let t = tokens[k]; t?.kind === 'string'; t = tokens[++k]) uris[0] += t.value; + while (k < tokens.length) { + const t = tokens[k]!; + const next = tokens[k + 1]; + const uri = tokens[k + 2]; + if (t.kind === 'word' && t.value === 'if' && next?.kind === 'condition' && uri?.kind === 'string') { + uris.push(uri.value); + k += 3; + } else if (t.kind === 'word' && t.value === 'as' && next?.kind === 'word') { + prefix = next.value; + k += 2; + } else if (t.kind === 'word' && (t.value === 'show' || t.value === 'hide')) { + const names = new Set(); + k++; + while (tokens[k]?.kind === 'word') { + names.add((tokens[k] as { value: string }).value); + const comma = tokens[k + 1]; + if (comma?.kind !== 'punctuation' || comma.value !== ',') { + k++; + break; + } + k += 2; + } + filter = composeFilters(filter, t.value === 'show' ? makeFilter(names, null) : makeFilter(null, names)); + } else { + // `deferred`, and anything this does not model. + k++; + } + } + (keyword === 'import' ? out.imports : out.exports).push({ uris, prefix, filter }); + return true; +} + +/** + * The `library`, `part`, `part of`, `import` and `export` directives at the + * head of a Dart source file — past its script tag, comments and metadata, + * up to its first declaration. + */ +export function readDartDirectives(source: string): DartDirectives { + const out: DartDirectives = { libraryName: null, partOf: null, parts: [], imports: [], exports: [] }; + let i = source.charCodeAt(0) === 0xfeff ? 1 : 0; + if (source.startsWith('#!', i)) { + const newline = source.indexOf('\n', i); + i = newline < 0 ? source.length : newline + 1; + } + for (;;) { + i = skipTrivia(source, i); + if (i >= source.length) break; + if (source[i] === '@') { + i = skipAnnotation(source, i); + continue; + } + IDENTIFIER.lastIndex = i; + const keyword = IDENTIFIER.exec(source)?.[0]; + if (keyword === undefined || !DIRECTIVE_KEYWORDS.has(keyword)) break; + const directive = readDirectiveTokens(source, i + keyword.length); + if (!directive || !addDirective(out, keyword, directive.tokens)) break; + i = directive.end; + } + return out; +} + +/** A pub package of the project: its pubspec.yaml's `name`, and the directory holding it ('' for the project root). */ +interface PubPackage { + name: string; + root: string; +} + +/** What a file's imports and its library's own files make visible. */ +interface FileScope { + /** The library's files: the library, its parts, and the file itself. */ + own: ReadonlySet; + /** The files whose imports apply here: the file, and for a part each file up to its library. */ + importers: readonly string[]; + /** By import prefix ('' for none), the libraries those imports name, each with the import's filter (read on first use). */ + imported: Map> | null; + /** By prefix and declaring file, the filters through which the imports bring in its names (read on first use). */ + visible: Map; +} + +interface Memo { + directives: Map; + packageOfDir: Map; + packages: Map | null; + libraryNames: Map | null; + libraryOf: Map; + /** A part's parent: the file its `part of` names. */ + parentOf: Map; + members: Map>; + exports: Map>; + scopes: Map; +} + +const memos = new WeakMap(); + +function memoFor(context: ResolutionContext): Memo { + let memo = memos.get(context); + if (!memo) { + memo = { + directives: new Map(), + packageOfDir: new Map(), + packages: null, + libraryNames: null, + libraryOf: new Map(), + parentOf: new Map(), + members: new Map(), + exports: new Map(), + scopes: new Map(), + }; + memos.set(context, memo); + } + return memo; +} + +/** Drop the memos (see ReferenceResolver.clearCaches). */ +export function clearDartLibraryMemos(context: ResolutionContext): void { + memos.delete(context); +} + +function parentDir(file: string): string { + const cut = file.lastIndexOf('/'); + return cut < 0 ? '' : file.slice(0, cut); +} + +function directivesOf(file: string, context: ResolutionContext, memo: Memo): DartDirectives | null { + const hit = memo.directives.get(file); + if (hit !== undefined) return hit; + const source = context.readFile(file); + const directives = source === null ? null : readDartDirectives(source); + memo.directives.set(file, directives); + return directives; +} + +const PUBSPEC_NAME = /^name[ \t]*:[ \t]*['"]?([A-Za-z_]\w*)/m; + +/** The package of the nearest pubspec.yaml at or above project-relative `dir`, never above the project root. */ +function packageOfDir(dir: string, context: ResolutionContext, memo: Memo): PubPackage | null { + const walked: string[] = []; + let found: PubPackage | null | undefined; + for (let d = dir; ; d = parentDir(d)) { + found = memo.packageOfDir.get(d); + if (found !== undefined) break; + walked.push(d); + const pubspec = d ? `${d}/pubspec.yaml` : 'pubspec.yaml'; + const name = context.fileExists(pubspec) ? PUBSPEC_NAME.exec(context.readFile(pubspec) ?? '')?.[1] : undefined; + if (name) { + found = { name, root: d }; + break; + } + if (d === '') { + found = null; + break; + } + } + for (const d of walked) memo.packageOfDir.set(d, found); + return found; +} + +/** The project's packages named `name`: the packages that hold an indexed .dart file. */ +function packagesNamed(name: string, context: ResolutionContext, memo: Memo): readonly PubPackage[] { + if (!memo.packages) { + const byName = new Map(); + const seen = new Set(); + for (const file of context.getAllFiles()) { + if (!file.endsWith('.dart')) continue; + const pkg = packageOfDir(parentDir(file), context, memo); + if (!pkg || seen.has(pkg)) continue; + seen.add(pkg); + const list = byName.get(pkg.name); + if (list) list.push(pkg); + else byName.set(pkg.name, [pkg]); + } + memo.packages = byName; + } + return memo.packages.get(name) ?? []; +} + +/** The project files a URI written in `from` names: none for `dart:` and other schemes, or a package outside the project. */ +function resolveDartUri(from: string, uri: string, context: ResolutionContext, memo: Memo): string[] { + if (uri.startsWith('package:')) { + const slash = uri.indexOf('/'); + if (slash < 0) return []; + const name = uri.slice('package:'.length, slash); + const rest = uri.slice(slash + 1); + let chosen = packagesNamed(name, context, memo); + if (chosen.length > 1) { + const own = packageOfDir(parentDir(from), context, memo); + const enclosing = chosen.filter((p) => p.root === '' || from.startsWith(`${p.root}/`)); + if (own && own.name === name) chosen = [own]; + else if (enclosing.length > 0) chosen = [enclosing.reduce((a, b) => (b.root.length > a.root.length ? b : a))]; + } + return chosen.map((p) => path.posix.normalize(p.root ? `${p.root}/lib/${rest}` : `lib/${rest}`)); + } + if (/^[A-Za-z][\w+.-]*:/.test(uri)) return []; + const joined = path.posix.normalize(path.posix.join(parentDir(from) || '.', uri)); + return joined === '..' || joined.startsWith('../') || joined.startsWith('/') ? [] : [joined]; +} + +/** The files declaring `library ;`. */ +function libraryFilesNamed(name: string, context: ResolutionContext, memo: Memo): readonly string[] { + if (!memo.libraryNames) { + const byName = new Map(); + for (const file of context.getAllFiles()) { + if (!file.endsWith('.dart') || context.fileContains?.(file, 'library') === false) continue; + const declared = directivesOf(file, context, memo)?.libraryName; + if (!declared) continue; + const list = byName.get(declared); + if (list) list.push(file); + else byName.set(declared, [file]); + } + memo.libraryNames = byName; + } + return memo.libraryNames.get(name) ?? []; +} + +/** The file a part's `part of` names, or null when it names none this can find. */ +function partParent(file: string, partOf: NonNullable, context: ResolutionContext, memo: Memo): string | null { + const candidates = 'uri' in partOf + ? resolveDartUri(file, partOf.uri, context, memo).filter((f) => directivesOf(f, context, memo) !== null) + : libraryFilesNamed(partOf.name, context, memo); + if (candidates.length <= 1) return candidates[0] ?? null; + const listing = candidates.filter((c) => + (directivesOf(c, context, memo)?.parts ?? []).some((uri) => resolveDartUri(c, uri, context, memo).includes(file))); + return listing.length === 1 ? listing[0]! : null; +} + +/** The library file `file` belongs to: itself, or for a part the library its `part of` chain ends at; null when unknown. */ +function libraryOf(file: string, context: ResolutionContext, memo: Memo): string | null { + const hit = memo.libraryOf.get(file); + if (hit !== undefined) return hit; + // A part cycle ends at null. + memo.libraryOf.set(file, null); + const directives = directivesOf(file, context, memo); + let library: string | null = null; + if (directives && !directives.partOf) { + library = file; + } else if (directives?.partOf) { + const parent = partParent(file, directives.partOf, context, memo); + if (parent !== null) { + memo.parentOf.set(file, parent); + library = libraryOf(parent, context, memo); + } + } + memo.libraryOf.set(file, library); + return library; +} + +/** A library's files: the library and its parts, theirs included. */ +function membersOf(library: string, context: ResolutionContext, memo: Memo): ReadonlySet { + const hit = memo.members.get(library); + if (hit) return hit; + const files = new Set([library]); + const queue = [library]; + while (queue.length > 0 && files.size < 1000) { + const file = queue.shift()!; + for (const uri of directivesOf(file, context, memo)?.parts ?? []) { + for (const part of resolveDartUri(file, uri, context, memo)) { + if (files.has(part)) continue; + files.add(part); + queue.push(part); + } + } + } + memo.members.set(library, files); + return files; +} + +function addFilter(namespace: Map, file: string, filter: NameFilter): void { + const filters = namespace.get(file); + if (!filters) namespace.set(file, [filter]); + else if (filters[0] === EVERY_NAME) return; + else if (filter === EVERY_NAME) filters.splice(0, filters.length, EVERY_NAME); + else if (!filters.some((f) => f.key === filter.key)) filters.push(filter); +} + +/** + * The files whose public names `library` exports, each with the filters on + * the way: its own files, and what its `export`s reach. `low` is the + * shallowest library still on `stack` that the walk came back to; a result + * that leans on one is incomplete until that library finishes, so it is kept + * only when the walk came back to nothing shallower than this library. + */ +function exportsOf( + library: string, + context: ResolutionContext, + memo: Memo, + stack: Map, +): { namespace: ReadonlyMap; low: number } { + const hit = memo.exports.get(library); + if (hit) return { namespace: hit, low: Infinity }; + const depth = stack.size; + stack.set(library, depth); + const namespace = new Map(); + let low = Infinity; + const members = membersOf(library, context, memo); + for (const file of members) addFilter(namespace, file, EVERY_NAME); + for (const file of members) { + for (const directive of directivesOf(file, context, memo)?.exports ?? []) { + for (const uri of directive.uris) { + for (const target of resolveDartUri(file, uri, context, memo)) { + const exported = libraryOf(target, context, memo); + if (exported === null) continue; + const onStack = stack.get(exported); + if (onStack !== undefined) { + low = Math.min(low, onStack); + continue; + } + const inner = exportsOf(exported, context, memo, stack); + low = Math.min(low, inner.low); + for (const [f, filters] of inner.namespace) { + for (const filter of filters) addFilter(namespace, f, composeFilters(directive.filter, filter)); + } + } + } + } + } + stack.delete(library); + if (low >= depth) memo.exports.set(library, namespace); + return { namespace, low }; +} + +/** + * What `file` can see, or null when that is unknown: its library cannot be + * found, or no pubspec.yaml above it says which package its `package:` + * imports start from (a mason brick's template, a project indexed below its + * package root). + */ +function scopeOf(file: string, context: ResolutionContext, memo: Memo): FileScope | null { + const hit = memo.scopes.get(file); + if (hit !== undefined) return hit; + const library = packageOfDir(parentDir(file), context, memo) === null ? null : libraryOf(file, context, memo); + let scope: FileScope | null = null; + if (library !== null) { + const own = new Set(membersOf(library, context, memo)); + own.add(file); + const importers: string[] = []; + for (let f: string | undefined = file; f !== undefined && importers.length < 32; f = memo.parentOf.get(f)) { + importers.push(f); + if (f === library) break; + } + scope = { own, importers, imported: null, visible: new Map() }; + } + memo.scopes.set(file, scope); + return scope; +} + +/** + * The filters through which the imports written with `prefix` ('' for none) + * bring `declFile`'s names in — empty when they bring in none of them — or + * null when no import has that prefix. + */ +function importedFilters(scope: FileScope, prefix: string, declFile: string, context: ResolutionContext, memo: Memo): readonly NameFilter[] | null { + if (!scope.imported) { + scope.imported = new Map(); + for (const importer of scope.importers) { + for (const directive of directivesOf(importer, context, memo)?.imports ?? []) { + const key = directive.prefix ?? ''; + const libraries = scope.imported.get(key) ?? []; + scope.imported.set(key, libraries); + for (const uri of directive.uris) { + for (const target of resolveDartUri(importer, uri, context, memo)) { + const library = libraryOf(target, context, memo); + if (library !== null) libraries.push({ filter: directive.filter, library }); + } + } + } + } + } + const libraries = scope.imported.get(prefix); + if (!libraries) return prefix === '' ? [] : null; + const key = `${prefix}\0${declFile}`; + const hit = scope.visible.get(key); + if (hit) return hit; + const through = new Map(); + for (const { filter, library } of libraries) { + for (const exported of exportsOf(library, context, memo, new Map()).namespace.get(declFile) ?? []) { + addFilter(through, declFile, composeFilters(filter, exported)); + } + } + const filters = through.get(declFile) ?? []; + scope.visible.set(key, filters); + return filters; +} + +/** + * Whether the library of `fromFile` can name `name`, declared at the top level + * of `declFile`, without a prefix: `declFile` is one of the library's own + * files, or a library it imports unprefixed exports the name. True when the + * library of `fromFile` cannot be established. + */ +export function dartLibrarySees(fromFile: string, declFile: string, name: string, context: ResolutionContext): boolean { + if (fromFile === declFile) return true; + const memo = memoFor(context); + const scope = scopeOf(fromFile, context, memo); + if (!scope || scope.own.has(declFile)) return true; + if (name.startsWith('_')) return false; + return (importedFilters(scope, '', declFile, context, memo) ?? []).some((f) => lets(f, name)); +} + +/** + * Whether `prefix.name` in `fromFile` can mean `name` declared at the top + * level of `declFile`: a library imported `as prefix` exports it. True when + * no import of the file's library has that prefix, or the library is unknown. + */ +export function dartPrefixSees(fromFile: string, prefix: string, declFile: string, name: string, context: ResolutionContext): boolean { + const memo = memoFor(context); + const scope = scopeOf(fromFile, context, memo); + if (!scope) return true; + const filters = importedFilters(scope, prefix, declFile, context, memo); + return filters === null || (!name.startsWith('_') && filters.some((f) => lets(f, name))); +} + +/** Whether `declFile` is a file of the library `fromFile` belongs to (false when that library is unknown). */ +export function inSameDartLibrary(fromFile: string, declFile: string, context: ResolutionContext): boolean { + if (fromFile === declFile) return true; + const scope = scopeOf(fromFile, context, memoFor(context)); + return scope !== null && scope.own.has(declFile); +} diff --git a/src/resolution/index.ts b/src/resolution/index.ts index 8964590a79..5fdbf2d9be 100644 --- a/src/resolution/index.ts +++ b/src/resolution/index.ts @@ -25,6 +25,7 @@ import { isPythonSelfCall, matchJsStoreBindingCall, isUnresolvedJsMemberCall, ma import { isVisibleCppMacro, clearCppMacroVisibility } from './cpp-macro-visibility'; import { isCppConstructorRef, matchCppConstructor } from './cpp-constructor'; import { gateSwiftTypeTarget, clearSwiftTypeVisibility, swiftExtendedConformances } from './swift-type-visibility'; +import { clearDartLibraryMemos } from './dart-libraries'; import { clearVbnetReceiverMemos, isVbMemberRead, isVbPathCall, matchVbMemberRead, matchVbPathCall } from './vbnet-receivers'; import { gateTypeParameter, clearTypeParameterMemos } from './type-parameters'; import { gateDartLocal, clearDartLocalScopeMemos } from './dart-local-scope'; @@ -470,6 +471,7 @@ export class ReferenceResolver { clearNameMatcherMemos(this.context); clearCppMacroVisibility(this.context); clearSwiftTypeVisibility(this.context); + clearDartLibraryMemos(this.context); clearVbnetReceiverMemos(this.context); clearTypeParameterMemos(this.context); clearDartLocalScopeMemos(this.context); diff --git a/src/resolution/name-matcher.ts b/src/resolution/name-matcher.ts index 640d992514..4b382c0a3f 100644 --- a/src/resolution/name-matcher.ts +++ b/src/resolution/name-matcher.ts @@ -11,6 +11,7 @@ import { UnresolvedRef, ResolvedRef, ResolutionContext, ImportMapping, isSuperty import { blankStringContents, stripCommentsForRegex } from './strip-comments'; import { JS_BUILT_INS, JS_BUILTIN_METHODS, TS_PRIMITIVE_TYPES } from './js-builtins'; import { SWIFT_TYPE_PATH_CALL, resolveSwiftTypePathCall } from './swift-type-visibility'; +import { dartLibrarySees, dartPrefixSees, inSameDartLibrary } from './dart-libraries'; import { breakVbTie, isVbMemberInScope, isVbNestedTypeInScope, isVbTypeQualifiedBy, matchVbTypedCall, preferVbProject, sameVbProject } from './vbnet-receivers'; import { isTestPath } from '../search/query-utils'; import { isMinifiedContent } from '../extraction/generated-detection'; @@ -2225,7 +2226,7 @@ export function isVisibleAcrossFiles(candidate: Node, ref: UnresolvedRef, contex if (dartExtensionDecl(candidate, context)?.named === false) return false; // And it applies only in its own library: flutter_test's `find.text(…)` is // no other file's `extension on TaskStatus { String get text }`. - if (candidate.filePath !== ref.filePath && isDartUnnamedExtensionMember(candidate, context)) return false; + if (isDartUnnamedExtensionMember(candidate, context) && !inSameDartLibrary(ref.filePath, candidate.filePath, context)) return false; // A Scala package object's member is in scope in its package and those under // it, or through an import: cats.laws' `Eq` is the `cats` package object's // alias, not the `algebra` one's (752 refs went there). @@ -2968,6 +2969,72 @@ function isDartMember(n: Node): boolean { return n.kind === 'method' || (n.kind === 'function' && n.qualifiedName.includes('::')); } +/** + * A value a Dart type holds — an enum constant, a `static const` / `final` — + * which a bare name reaches only from inside the type, like its methods: + * bloc's brick hook calls `info(…)` on mason's `Logger`, and the call went to + * bloc_lint's enum constant `LinterRuleState.info`. + */ +function isDartTypeValue(n: Node): boolean { + return n.language === 'dart' && (n.kind === 'enum_member' || VALUE_KINDS.has(n.kind)) && n.qualifiedName.includes('::'); +} + +/** What a Dart library declares at its top level: a function, a type, a typedef, a top-level `final` / `const`. */ +const DART_LIBRARY_DECL_KINDS: ReadonlySet = new Set(['function', 'class', 'enum', 'type_alias', 'constant', 'variable', 'interface', 'struct', 'trait', 'mixin', 'extension']); + +function isDartLibraryDecl(n: Node): boolean { + return n.language === 'dart' && DART_LIBRARY_DECL_KINDS.has(n.kind) && !n.qualifiedName.includes('::'); +} + +/** + * Whether a Dart name written without a receiver — a call, a type — can mean + * `candidate` when it is declared at the top level of a library: the caller's + * own library declares it, or a library the caller imports without a prefix + * exports it, `show` / `hide` and `export` chains followed (see + * ./dart-libraries). A name written through an import prefix (`p.Report`) + * means only what the imports with that prefix export. riverpod's generated + * `async.g.dart` (`part of 'async.dart'`) calls the `family(…)` async.dart + * declares, and the call went to annotated.dart's `family` beside it; a test's + * `fakeAsync(…)` from package:fake_async went to a vendored copy no file imports. + */ +function isDartTopLevelVisible(candidate: Node, ref: UnresolvedRef, context: ResolutionContext, prefix: string | null = null): boolean { + if (!isDartLibraryDecl(candidate)) return true; + return prefix === null + ? dartLibrarySees(ref.filePath, candidate.filePath, candidate.name, context) + : dartPrefixSees(ref.filePath, prefix, candidate.filePath, candidate.name, context); +} + +/** + * The import prefix a Dart type name is written through — the `p` of + * `p.Report`, `p.Color.red` — or null. A type reference's column is the + * name's start; on a line with non-ASCII text before it the nearest whole-word + * occurrence stands in. + */ +function dartImportPrefixOf(ref: UnresolvedRef, context: ResolutionContext): string | null { + const line = context.getFileLines?.(ref.filePath)?.[ref.line - 1] ?? context.readFile(ref.filePath)?.split(/\r?\n/)[ref.line - 1]; + if (line === undefined) return null; + const name = ref.referenceName; + const isWord = (at: number) => line.startsWith(name, at) && !/[\w$]/.test(line[at - 1] ?? '') && !/[\w$]/.test(line[at + name.length] ?? ''); + let start = isWord(ref.column) ? ref.column : -1; + for (let at = line.indexOf(name); start < 0 && at >= 0; at = line.indexOf(name, at + 1)) { + if (isWord(at)) start = at; + } + if (start < 0) return null; + return /([A-Za-z_$][\w$]*)\s*\.\s*$/.exec(line.slice(0, start))?.[1] ?? null; +} + +/** + * A library's own top-level declaration shadows every import of its name, so + * when the caller's library declares one, the imported namesakes are no + * candidates. (A function nested in another body is not the library's.) + */ +function preferOwnDartLibrary(candidates: Node[], ref: UnresolvedRef, context: ResolutionContext): Node[] { + if (candidates.filter(isDartLibraryDecl).length < 2) return candidates; + const own = candidates.filter((n) => + isDartLibraryDecl(n) && inSameDartLibrary(ref.filePath, n.filePath, context) && isLexicallyReachable(n, ref, context)); + return own.length === 0 ? candidates : candidates.filter((n) => !isDartLibraryDecl(n) || own.includes(n)); +} + /** * Whether a bare Dart reference really is receiver-less at its call site. The * extractor keeps one receiver level, so the later links of a chain — @@ -3911,7 +3978,7 @@ function dartMemberOf( const extension = dartExtensionOwner(m, context); let rank: number; if (extension) { - if (!extension.named && m.filePath !== ref.filePath) continue; + if (!extension.named && !inSameDartLibrary(ref.filePath, m.filePath, context)) continue; // `extension ObjectX on T` reaches every type, after every extension // that names one of its lineage — when the type is the project's, so // what it declares is known: a List's own `cast` is not ObjectX's. @@ -4256,7 +4323,10 @@ function dartExtensionDecl(n: Node, context: ResolutionContext): { named: boolea const head = lines.slice(n.startLine - 1, Math.min(n.endLine, n.startLine + 5)).join('\n') .replace(/^\s*(?:(?:@[\w$.]+(?:\s*\((?:[^()]|\([^()]*\))*\))?|\/\/[^\n]*)\s*)*/, ''); if (!/^extension\b(?!\s+type\b)/.test(head)) return null; - return { named: !/^extension\s+on\b/.test(head) }; + // A generic one has no name either: riverpod's `extension on Map<…>` took the + // `Map` type references of riverpod's own library. + return { named: !/^extension\s*(?:<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?\s*on\b/.test(head) }; } /** Whether a Dart method belongs to an unnamed `extension on X`, visible only in its own library. */ @@ -6692,6 +6762,9 @@ export function matchByExactName( const pythonShape = pythonCallShape(ref, context); const javaBare = ref.language === 'java' && ref.referenceKind === 'calls' && /^[A-Za-z_$][\w$]*$/.test(ref.referenceName); const dartBare = ref.language === 'dart' && ref.referenceKind === 'calls' && /^[A-Za-z_$][\w$]*$/.test(ref.referenceName) && isReceiverLessDartCall(ref, context); + // A Dart type name — a declared type, a supertype, the `Color` of `Color.red` — is in scope as a call is, or through its import prefix. + const dartTypeRef = ref.language === 'dart' && (ref.referenceKind === 'references' || isInheritanceRef(ref)) && /^[A-Za-z_$][\w$]*$/.test(ref.referenceName); + const dartPrefix = dartTypeRef ? dartImportPrefixOf(ref, context) : null; const kotlinCall = ref.language === 'kotlin' && ref.referenceKind === 'calls' && /^[A-Za-z_$][\w$]*$/.test(ref.referenceName); const kotlinBare = kotlinCall && isReceiverLessKotlinCall(ref, context); const rubyBare = ref.language === 'ruby' && ref.referenceKind === 'calls' && /^[A-Za-z_]\w*[?!]?$/.test(ref.referenceName); @@ -6737,6 +6810,8 @@ export function matchByExactName( // last link of a chain, not an annotation (riverpod's 210 `@internal` // annotations went to its providers' `internal` constructors). !(ref.language === 'dart' && isDartConstructor(n, context)) && + !(dartBare && isDartTypeValue(n) && !isDartMethodInScope(n, ref, context)) && + !((dartBare || dartTypeRef) && !isDartTopLevelVisible(n, ref, context, dartPrefix)) && !(phpSelf && (n.kind !== 'method' || !isPhpMethodInScope(n, ref, phpSelf, context))) && !(pythonShape && !fitsPythonCallShape(n, pythonShape, ref, context)) && !(rustBare && !isRustNameInScope(n, ref, context)) && @@ -6805,7 +6880,8 @@ export function matchByExactName( // file's symbol of that name, so a bare call has no cross-file candidate. !(bareJs && n.filePath !== ref.filePath && isLocallyBoundJsName(ref.referenceName, ref.filePath, context)) ); - const candidates = dartBare ? nearestDartMembers(filtered, ref, context) + const candidates = dartBare ? nearestDartMembers(preferOwnDartLibrary(filtered, ref, context), ref, context) + : dartTypeRef && dartPrefix === null ? preferOwnDartLibrary(filtered, ref, context) : swiftShape && swiftShape.shape !== 'chained' ? nearestSwiftMembers(filtered, ref, context) : kotlinBare ? lexicalKotlinMembers(filtered, ref, context) : filtered; @@ -9969,7 +10045,7 @@ export function matchMethodCall( // `tester.pumpApp(…)` is the imported `PumpApp`, not flutter_counter's // `extension on WidgetTester`. { - const kept = targetMethods.filter((m) => m.filePath === ref.filePath || !isDartUnnamedExtensionMember(m, context)); + const kept = targetMethods.filter((m) => !isDartUnnamedExtensionMember(m, context) || inSameDartLibrary(ref.filePath, m.filePath, context)); narrowed ||= kept.length !== targetMethods.length; targetMethods = kept; } @@ -11502,6 +11578,9 @@ export function matchFuzzy( const pythonShape = pythonCallShape(ref, context); const javaBare = ref.language === 'java' && ref.referenceKind === 'calls' && /^[A-Za-z_$][\w$]*$/.test(ref.referenceName); const dartBare = ref.language === 'dart' && ref.referenceKind === 'calls' && /^[A-Za-z_$][\w$]*$/.test(ref.referenceName) && isReceiverLessDartCall(ref, context); + // A Dart type name — a declared type, a supertype, the `Color` of `Color.red` — is in scope as a call is, or through its import prefix. + const dartTypeRef = ref.language === 'dart' && (ref.referenceKind === 'references' || isInheritanceRef(ref)) && /^[A-Za-z_$][\w$]*$/.test(ref.referenceName); + const dartPrefix = dartTypeRef ? dartImportPrefixOf(ref, context) : null; const kotlinCall = ref.language === 'kotlin' && ref.referenceKind === 'calls' && /^[A-Za-z_$][\w$]*$/.test(ref.referenceName); const kotlinBare = kotlinCall && isReceiverLessKotlinCall(ref, context); const rubyBare = ref.language === 'ruby' && ref.referenceKind === 'calls' && /^[A-Za-z_]\w*[?!]?$/.test(ref.referenceName); @@ -11540,6 +11619,10 @@ export function matchFuzzy( !(javaBare && n.kind === 'method' && !isJavaMethodInScope(n, ref, context)) && !(dartBare && isDartMember(n) && !isDartMethodInScope(n, ref, context)) && !(ref.language === 'dart' && isDartConstructor(n, context)) && + !((dartBare || dartTypeRef) && !isDartTopLevelVisible(n, ref, context, dartPrefix)) && + // A Dart `extension on Color` is no `Color`, here as in exact matching: + // flutter_weather's `Color brighten(…)` in that extension names Flutter's. + dartExtensionDecl(n, context)?.named !== false && !(kotlinCall && !isKotlinTopLevelVisible(n, ref, context)) && !(kotlinBare && !isKotlinMemberReachable(n, ref, context)) && !isKotlinNumberBitwise(n, ref) && @@ -11563,7 +11646,8 @@ export function matchFuzzy( // Prefer same-language matches const sameLanguageCandidates = callableCandidates.filter(n => n.language === ref.language); - const finalCandidates = sameLanguageCandidates.length > 0 ? sameLanguageCandidates : callableCandidates; + const languageCandidates = sameLanguageCandidates.length > 0 ? sameLanguageCandidates : callableCandidates; + const finalCandidates = dartBare || (dartTypeRef && dartPrefix === null) ? preferOwnDartLibrary(languageCandidates, ref, context) : languageCandidates; // Both post-pipeline visibility guards (#1745 language-local + #1719 sealed // module). The sealed-module test rejects the survivor and never filters the From 99246848994b19220488b485f95d961a0612c791 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 16:29:29 +0000 Subject: [PATCH 15/23] fix(dart): a member keeps the dartdoc written above its annotations (#2387) A Dart member's annotations are siblings that stand between it and the dartdoc written above them: /// Builds the widget. @override Widget build(BuildContext context) { ... } Both extractors read a docstring from the comments directly before the declaration (or its `declaration` wrapper) and stopped at the first node that was not a comment, so the annotation ended the run before the `///` was reached. Members behind `@override`, `@protected`, `@mustCallSuper`, `@pragma(...)`, `@internal` and the like lost their documentation, and searching for words in it didn't find them. Extraction (TS + kernel, at parity): - getPrecedingDocstring takes an optional list of sibling types to step over, and Dart sets `docstringStepOverTypes: ['annotation']`. Stacked, multi-line and inline annotations are passed, and comments on either side of one still join (`/// a` `@x` `// b` gives "a" and "b" on two lines), as adjacent comments already did. Any other node still ends the walk: the previous member's body, a field, a top-level variable, an import or another declaration. - The kernel's shared docstring.rs gains preceding_docstring_stepping_over. preceding_docstring passes an empty list, so every other language is unchanged; only Dart's docstring_of passes ["annotation"]. - Class-like declarations needed nothing: a class, mixin, extension, extension type, enum or typedef node starts at its first annotation, so the dartdoc above it is already the node's previous sibling. Validated on felangel/bloc @b9be1e2 and rrousselGit/riverpod @4ba1be2 at main 249d9a86 (and at 1b752de2) with the kernel loaded: docstrings bloc +26, riverpod +1,072 with 9 changed and none removed. Nodes otherwise, edges, refs and files are byte-identical, full-index kernel and wasm dumps are byte-identical, and the kernel parity sweeps show 0 diffs. Not changed: a comment between an annotation and the declaration still hides the annotation from the decorator scan. Recording those would only add wrong edges until Dart `decorates` resolution stops preferring methods: riverpod's `@riverpod` edges land on an analyzer getter rather than `const riverpod`. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/dart-annotated-member-docs.test.ts | 247 ++++++++++++++++++ .../kernel-parity/TortureAnnotatedDocs.dart | 193 ++++++++++++++ __tests__/fixtures/kernel-parity/torture.dart | 2 +- __tests__/kernel-dart-parity.test.ts | 15 +- codegraph-kernel/src/dart.rs | 15 +- codegraph-kernel/src/docstring.rs | 37 +++ docs/design/dart-kernel-port-checklist.md | 86 +++++- src/extraction/languages/dart.ts | 7 + src/extraction/tree-sitter-helpers.ts | 13 +- src/extraction/tree-sitter-types.ts | 7 + src/extraction/tree-sitter.ts | 6 +- 12 files changed, 610 insertions(+), 19 deletions(-) create mode 100644 __tests__/dart-annotated-member-docs.test.ts create mode 100644 __tests__/fixtures/kernel-parity/TortureAnnotatedDocs.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 07ab7ec64c..9bd122abac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In Dart, `const` constructors and redirecting factories, like flutter_bloc's `const BlocProvider.value(…)` or freezed's `const factory LoginState.loading() = _Loading;`, are now indexed, so a call such as `BlocProvider.value(…)` or `BlocProvider.value(…)` links to that constructor instead of another class's member with the same name. A call through a class name now reaches only that class's own constructors and static members, never a look-alike class, a parent class, an instance getter of the same name, or a project method that merely shares its name with an SDK call like `Uri.parse(…)`, and a constructor is no longer linked from a bare name, the end of a call chain or an annotation like `@internal`. Re-index Dart projects after upgrading. - In Dart, a call that passes a type argument and arguments, like `ref.read(repoProvider)`, `ref.watch(counterProvider)`, `Provider((ref) => …)`, `BlocProvider.of(context)` or `RepositoryProvider(create: …)`, now links to the method or class it calls, and the type it passes counts as used there. Depending on the code around it, the parser often read such a call as two comparisons, so it linked nothing, and Riverpod providers, repository reads and bloc lookups were missing from `callers`, impact and `codegraph_explore`. A real comparison like `a < b` is still left alone. Re-index Dart projects after upgrading. - In Dart, a constructor or member written without a body, like flutter_bloc's `const BlocProvider.value(…)`, `Foo._();`, `Point.origin() : x = 0, y = 0;` or an abstract or `external` method, now keeps the `///` documentation and the annotations written above it, the way one with a body already did. Before, that documentation was lost, so searching for words in it didn't find the symbol, and an annotation like `@visibleForTesting` or `@protected` on it wasn't recorded. Re-index Dart projects after upgrading. +- In Dart, a function or method now keeps the `///` documentation written above its annotations, like the doc on a widget's `@override Widget build(…)` or on a member marked `@protected`, `@mustCallSuper`, `@pragma(…)` or `@internal`. Before, the annotation between the documentation and the declaration hid it, so searching for words in it didn't find the symbol. Re-index Dart projects after upgrading. - In Dart, a call on what a generic lookup returns, like flutter_bloc's `BlocProvider.of(context, listen: false).increment()` or Provider's `Provider.of(context, listen: false).add(item)`, now links to that method of the type in the angle brackets, whether the lookup is declared in your project or comes from a package. Before, such a call often linked nothing — for example whenever the lookup passed `listen: false` — so `callers` and impact missed those methods. A lookup that names no type, like `BlocProvider.of(context)`, still links nothing. Re-index Dart projects after upgrading. (#750) - In JavaScript and TypeScript, a store whose name starts or ends with a `$`, like `const items$ = create(…)`, now has its actions indexed when an `export { … }` list on a later line exports it, as in `export { items$ };` or `export { $items as default };`. Before, those actions were missing from the graph, so their callers and impact came back empty. A store whose name only lacks the `$`, like `items`, is no longer treated as exported by that list. Re-index JavaScript and TypeScript projects after upgrading. - In Dart, a comment inside a chain of calls no longer loses part of it: a call with a comment before its arguments, like `box.grow /* by */ (3)`, now links to the method it calls, and a getter read or a static access written after a comment, like `Config //` followed by `.instance` on the next line (the empty `//` keeps `dart format` from joining the lines), now counts as a use. Re-index Dart projects after upgrading. diff --git a/__tests__/dart-annotated-member-docs.test.ts b/__tests__/dart-annotated-member-docs.test.ts new file mode 100644 index 0000000000..c66d6480bc --- /dev/null +++ b/__tests__/dart-annotated-member-docs.test.ts @@ -0,0 +1,247 @@ +/** + * A Dart member's annotations sit between it and the dartdoc written above + * them: + * + * /// Builds the widget. + * @override + * Widget build(BuildContext context) { … } + * + * Both extractors read a docstring from the comments directly before the + * declaration and stopped at the first node that was not a comment, so the + * annotation ended the run before the `///` was reached and the member lost + * its documentation. `@override`, `@protected`, `@mustCallSuper`, `@pragma`, + * `@internal` and `@visibleForTesting` are everywhere in Flutter code. + * + * The walk now steps over annotations, stacked and multi-line ones included, + * and a comment between an annotation and the member joins the dartdoc above + * the way adjacent comments already did. Whatever else comes first (a field, + * the previous member's body, a top-level variable, an import) still ends it. + * A class, mixin, extension, enum or typedef kept its dartdoc already: its + * annotations open its own node, so the dartdoc above them is that node's + * previous sibling. + * + * Runs against the native kernel (when built) and the wasm extractor, which + * must agree. + */ +import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as path from 'path'; +import { extractFromSource } from '../src/extraction'; +import { initGrammars, loadGrammarsForLanguages } from '../src/extraction/grammars'; +import { tryKernelExtract, resetKernelForTests } from '../src/extraction/kernel'; +import type { ExtractionResult } from '../src/types'; + +const KERNEL_PATH = path.join( + __dirname, + '..', + 'codegraph-kernel', + 'prebuilds', + `${process.platform}-${process.arch}`, + 'codegraph-kernel.node' +); +const kernelAvailable = fs.existsSync(KERNEL_PATH) || process.env.CODEGRAPH_KERNEL_EXPECT === '1'; + +const SOURCE = `// Copyright 2026 the authors. +import 'package:meta/meta.dart'; + +@visibleForTesting +void afterImport() {} + +/// Runs at startup. +@pragma('vm:entry-point') +void main() {} + +/// Calls into the platform. +@pragma('vm:external-name', 'version') +external int platformVersion(); + +/// Watches the counter. +@riverpod +@Deprecated('Use the generated provider') +int counter(Ref ref) => 0; + +/// The answer. +final answer = 42; + +@visibleForTesting +void afterVariable() {} + +abstract class Repository { + /// Loads the user with [id]. + @protected + Future load(String id); +} + +/// A counter. +@immutable +class Counter { + /// Starts at zero. + @literal + const Counter.zero() : value = 0; + + /// Reads a counter from JSON. + @visibleForTesting + factory Counter.fromJson(Map json) => const Counter.zero(); + + /// Builds the widget. + @override + Widget build(BuildContext context) => const Text('0'); + + /// Releases resources. + /// + /// Call it once. + @protected + @mustCallSuper + void dispose() {} + + /// The current count. + @override + int get count => value; + + /// Use [build] instead. + @Deprecated( + 'Use build. ' + 'Removed in 2.0.', + ) + + Widget render() => const Text(''); + + /// Joined with the comment below the annotation. + @protected + // ignore: must_call_super + void joined() {} + + /// The cached value. + @JsonKey(name: 'value') + final int value; + + @override + void afterField() {} + + void before() {} + @override + void afterBody() {} +} + +/// A mixin. +@internal +mixin Logging on Counter {} + +/// An extension. +@internal +extension CounterX on Counter {} + +/// An enum. +@JsonEnum() +enum Mode { light, dark } + +/// A typedef. +@internal +typedef Callback = void Function(); +@visibleForTesting +void afterTypedef() {} +`; + +const ENV_KEYS = ['CODEGRAPH_KERNEL', 'CODEGRAPH_KERNEL_LANGS'] as const; + +describe('Dart members keep the dartdoc written above their annotations', () => { + let savedEnv: Record = {}; + + beforeAll(async () => { + await initGrammars(); + await loadGrammarsForLanguages(['dart']); + }); + + beforeEach(() => { + savedEnv = Object.fromEntries(ENV_KEYS.map((k) => [k, process.env[k]])); + resetKernelForTests(); + }); + + afterEach(() => { + for (const k of ENV_KEYS) { + if (savedEnv[k] === undefined) delete process.env[k]; + else process.env[k] = savedEnv[k]; + } + resetKernelForTests(); + }); + + function extract(backend: 'kernel' | 'wasm', source: string): ExtractionResult { + if (backend === 'wasm') { + process.env.CODEGRAPH_KERNEL = '0'; + return extractFromSource('lib/counter.dart', source, 'dart'); + } + delete process.env.CODEGRAPH_KERNEL; + process.env.CODEGRAPH_KERNEL_LANGS = 'all'; + const result = tryKernelExtract('lib/counter.dart', source, 'dart'); + expect(result, 'kernel extraction').not.toBeNull(); + return result!; + } + + const backends = kernelAvailable ? (['kernel', 'wasm'] as const) : (['wasm'] as const); + + for (const crlf of [false, true]) { + it.each(backends)(`%s${crlf ? ' (CRLF)' : ''}`, (backend) => { + const result = extract(backend, crlf ? SOURCE.replace(/\n/g, '\r\n') : SOURCE); + const node = (qualifiedName: string) => { + const found = result.nodes.find((n) => n.qualifiedName === qualifiedName); + expect(found, qualifiedName).toBeDefined(); + return found!; + }; + const doc = (qualifiedName: string) => node(qualifiedName).docstring; + const decorators = (qualifiedName: string): string[] => { + const id = node(qualifiedName).id; + return result.unresolvedReferences + .filter((r) => r.referenceKind === 'decorates' && r.fromNodeId === id) + .map((r) => r.referenceName) + .sort(); + }; + + // Top-level functions, an external one and stacked annotations. + expect(doc('main')).toBe('Runs at startup.'); + expect(doc('platformVersion')).toBe('Calls into the platform.'); + expect(doc('counter')).toBe('Watches the counter.'); + + // Members: methods, a getter, a factory, a member with no body and a + // `const` constructor (both read from before their `declaration`). + expect(doc('Counter::build')).toBe('Builds the widget.'); + expect(doc('Counter::count')).toBe('The current count.'); + expect(doc('Counter::fromJson')).toBe('Reads a counter from JSON.'); + expect(doc('Repository::load')).toBe('Loads the user with [id].'); + expect(doc('Counter::zero')).toBe('Starts at zero.'); + expect(doc('Counter::dispose')).toBe('Releases resources.\n\nCall it once.'); + + // A multi-line annotation, with a blank line before the member. + expect(doc('Counter::render')).toBe('Use [build] instead.'); + + // A comment between the annotation and the member joins the dartdoc, + // as adjacent comments do. + expect(doc('Counter::joined')).toBe( + 'Joined with the comment below the annotation.\nignore: must_call_super' + ); + + // What comes before the annotations still ends the walk: an import, a + // top-level variable, a field (whose dartdoc and annotation are its + // own), the previous member's body and another declaration. + expect(doc('afterImport')).toBeUndefined(); + expect(doc('afterVariable')).toBeUndefined(); + expect(doc('Counter::afterField')).toBeUndefined(); + expect(doc('Counter::afterBody')).toBeUndefined(); + expect(doc('afterTypedef')).toBeUndefined(); + + // Class-like declarations kept theirs already: the annotations open + // their own node. + expect(doc('Counter')).toBe('A counter.'); + expect(doc('Logging')).toBe('A mixin.'); + expect(doc('CounterX')).toBe('An extension.'); + expect(doc('Mode')).toBe('An enum.'); + expect(doc('Callback')).toBe('A typedef.'); + + // The annotations are still recorded where they were. + expect(decorators('counter')).toEqual(['Deprecated', 'riverpod']); + expect(decorators('Counter::build')).toEqual(['override']); + expect(decorators('Counter::dispose')).toEqual(['mustCallSuper', 'protected']); + expect(decorators('Counter::zero')).toEqual(['literal']); + expect(decorators('Counter::afterField')).toEqual(['override']); + }); + } +}); diff --git a/__tests__/fixtures/kernel-parity/TortureAnnotatedDocs.dart b/__tests__/fixtures/kernel-parity/TortureAnnotatedDocs.dart new file mode 100644 index 0000000000..efd5b95621 --- /dev/null +++ b/__tests__/fixtures/kernel-parity/TortureAnnotatedDocs.dart @@ -0,0 +1,193 @@ +// A member's annotations sit between it and the dartdoc written above them; +// the docstring walk steps over them. A class-like declaration opens with its +// annotations, so the dartdoc above them precedes its node. + +import 'package:meta/meta.dart'; + +@visibleForTesting +void afterImport() {} + +/// Top function doc. +@pragma('vm:entry-point') +void top() {} + +/// External top doc. +@pragma('vm:external-name', 'f') +external int extTop(); + +/// Stacked, prefixed and generic annotations. +@meta.immutable +@JsonSerializable(explicitToJson: true) +@Deprecated('x') +void stacked() {} + +/// Top getter doc (no node). +@x +int get topGetter => 1; + +/** Block dartdoc above an annotation. */ +@x +void blockDoc() {} + +// Plain comment above an annotation. +@x +void plainAbove() {} + +/* Inline block */ @x void inlineBlock() {} + +/// a +@x +// b +@y +/* c */ +void interleaved() {} + +/// Doc, then blank lines. + +@x + +void blanks() {} + +/// A variable's doc. +final answer = 42; +@x +void afterVariable() {} + +const kLimit = 3; +@x +void afterConst() {} + +class C { + /// Operator doc. + @override + bool operator ==(Object other) => true; + + /// Factory doc. + @x + factory C.make() => C._(); + + /// Bodied constructor doc. + @x + C.named() {} + + /// Static method doc. + @x + static void s() {} + + /// External member doc. + @x + external void extMember(); + + /// Bodiless member doc. + @override + void bodiless(); + + /// Const constructor doc. + @literal + const C.c(); + + /// Redirecting factory doc. + @x + const factory C.r() = C.c; + + /// Static field doc. + @x + static const int k = 1; + @x + void afterStaticField() {} + + /// Multi-line annotation. + @Deprecated( + 'Use other. ' + 'Removed in 3.0', + ) + void multi() {} + + @override // ignore: must_call_super + void trailingComment() {} + + /// Doc above, ignore below. + @override + // ignore: invalid_use_of_protected_member + void ignoreBelow() {} + + @x + /// Doc below an annotation. + void docBelow() {} + + /// Field doc. + @JsonKey(name: 'x') + final int field = 0; + @override + void afterField() {} + + void before() {} // trailing comment + @override + void afterBody() {} + + /// Getter doc. + @override + int get value => 1; + + /// Setter doc. + @override + set value(int v) {} + + C._(); +} + +/// Class doc above a comment. +@immutable +// ignore: something +class D {} + +@immutable +/// Class doc below an annotation. +class E {} + +/// Mixin doc. +@internal +mixin M on C { + /// Mixin member doc. + @mustCallSuper + void m() {} +} + +/// Extension doc. +@internal +extension X on C { + /// Extension member doc. + @pragma('vm:prefer-inline') + void e() {} +} + +/// Extension type doc. +@internal +extension type Meters(double value) { + /// Extension type member doc. + @redeclare + double km() => value / 1000; +} + +/// Enum doc. +@JsonEnum() +enum Mode { + @JsonValue('on') + on, + off; + + /// Enum member doc. + @override + String toString() => name; +} + +/// Typedef doc. +@internal +typedef Cb = void Function(); + +void outer() { + /// Local function doc. + @pragma('vm:prefer-inline') + void local() {} + local(); +} diff --git a/__tests__/fixtures/kernel-parity/torture.dart b/__tests__/fixtures/kernel-parity/torture.dart index fa4f73b389..a76203e8ad 100644 --- a/__tests__/fixtures/kernel-parity/torture.dart +++ b/__tests__/fixtures/kernel-parity/torture.dart @@ -16,7 +16,7 @@ int blockDoc() => 1; // Plain comment doc. String plainDoc() => 'x'; -/// Broken by annotation. +/// Kept past the annotation. @deprecated void annotated() {} diff --git a/__tests__/kernel-dart-parity.test.ts b/__tests__/kernel-dart-parity.test.ts index 6fe570177b..104d6f423d 100644 --- a/__tests__/kernel-dart-parity.test.ts +++ b/__tests__/kernel-dart-parity.test.ts @@ -6,8 +6,8 @@ * ExtractionResult as the wasm TreeSitterExtractor — nodes, edges, and * unresolved refs compared as canonicalized multisets — over the checked-in * fixtures (torture.dart: the master inventory — imports incl. deferred - * invisibility, dartdoc in all three comment forms with the - * annotation-broken chain, stacked annotations in reverse order, the + * invisibility, dartdoc in all three comment forms and above an + * annotation, stacked annotations in reverse order, the * static_final_declaration constants hook, the full ctor set with the * unnamed-ctor skip and named-ctor renaming, operator methods as * ``, the extractBareCall matrix incl. cascade invisibility and @@ -32,8 +32,10 @@ * TortureDeclarationDocs.dart: the dartdoc and annotations of a * `declaration`-wrapped member with no body, read from before the wrapper; * TortureCommentChains.dart: comments between a member chain's parts skipped - * by every sibling step) and their CRLF variants (derived in-memory — #1329), - * plus defer and generated-file pins. + * by every sibling step; TortureAnnotatedDocs.dart: the dartdoc above a + * member's annotations, read past them, and what still ends the walk) and + * their CRLF variants (derived in-memory — #1329), plus defer and + * generated-file pins. * * The full-repo sweeps live in scripts/kernel-parity.mjs (shelf/bloc/flutter * with --max-deferral 0.3); this suite keeps the invariant alive in @@ -146,6 +148,11 @@ describe.skipIf(!kernelBuilt)('kernel Dart extraction parity', () => { // dartdoc, block comments, one between a member and its arguments — are // skipped by every sibling step: calls, chains, reads, static references. ['TortureCommentChains.dart', 10], + // The dartdoc above a member's annotations (stacked, multi-line, inline, + // with comments between them) is read past them; a field, a variable, an + // import or the previous member's body still ends the walk. Class-like + // declarations open with their annotations. + ['TortureAnnotatedDocs.dart', 40], ] as const; for (const [file, minNodes] of FIXTURES) { diff --git a/codegraph-kernel/src/dart.rs b/codegraph-kernel/src/dart.rs index 66426688b3..98a83fa7c1 100644 --- a/codegraph-kernel/src/dart.rs +++ b/codegraph-kernel/src/dart.rs @@ -36,7 +36,7 @@ use crate::buffers::{ RefRow, StrRef, Tables, FLAG_IS_ASYNC, FLAG_IS_EXPORTED, FLAG_IS_STATIC, FUNCTION_REF_CODE, NONE, NONE_STR, }; -use crate::docstring::preceding_docstring; +use crate::docstring::preceding_docstring_stepping_over; use crate::ids; use crate::textutil as util; use regex::Regex; @@ -46,6 +46,11 @@ use tree_sitter::{Node, Parser}; const MAX_VALUE_REF_NODES: usize = 20_000; +/// docstringStepOverTypes (dart.ts) — a member's annotations stand between it +/// and the dartdoc written above them (`/// Builds the widget.` `@override` +/// `Widget build(…)`), so the docstring walk steps over them. +const DOCSTRING_STEP_OVER: &[&str] = &["annotation"]; + /// NAME_STOPLIST (function-ref.ts). fn is_stoplisted(name: &str) -> bool { matches!( @@ -625,9 +630,13 @@ impl<'t> Walker<'t> { } /// docstringFor (tree-sitter.ts) — the preceding comment run, looked up - /// from the declaration wrapper when there is one. + /// from the declaration wrapper when there is one, past annotations. fn docstring_of(&self, node: Node<'t>) -> Option { - preceding_docstring(self.declaration_wrapper(node).unwrap_or(node), self.src) + preceding_docstring_stepping_over( + self.declaration_wrapper(node).unwrap_or(node), + self.src, + DOCSTRING_STEP_OVER, + ) } /// resolveBody (dart.ts:158-171). diff --git a/codegraph-kernel/src/docstring.rs b/codegraph-kernel/src/docstring.rs index de9a55afcd..9b307ca833 100644 --- a/codegraph-kernel/src/docstring.rs +++ b/codegraph-kernel/src/docstring.rs @@ -131,6 +131,18 @@ pub fn clean_comment_markers(comment: &str) -> String { /// Returns None when there is no preceding comment (a PRESENT-but-empty /// docstring after cleaning still returns Some(""), matching the TS helper). pub fn preceding_docstring(node: Node, src: &str) -> Option { + preceding_docstring_stepping_over(node, src, &[]) +} + +/// getPrecedingDocstring's `stepOver` — sibling kinds that may stand between +/// the declaration and its comments without ending the run (Dart's +/// `annotation`: `/// Builds it.` `@override` `Widget build(…)`). They are not +/// part of the docstring; the comments on either side of one still join. +pub fn preceding_docstring_stepping_over( + node: Node, + src: &str, + step_over: &[&str], +) -> Option { let mut anchor = node; while let Some(parent) = anchor.parent() { if is_wrapper(parent.kind()) { @@ -146,6 +158,8 @@ pub fn preceding_docstring(node: Node, src: &str) -> Option { if is_comment(s.kind()) { comments.push(&src[s.byte_range()]); sibling = s.prev_named_sibling(); + } else if step_over.contains(&s.kind()) { + sibling = s.prev_named_sibling(); } else { break; } @@ -194,4 +208,27 @@ mod tests { "a\r\nb" ); } + + /// A `step_over` kind is passed without ending the run, and the comments + /// on either side of it join; any other node still ends it. With no + /// step-over kinds the walk stops at the first non-comment, as before. + #[test] + fn steps_over_only_the_listed_kinds() { + let grammar = crate::langs::grammar_for("dart").expect("dart grammar"); + let mut parser = tree_sitter::Parser::new(); + parser.set_language(&grammar).unwrap(); + let src = "void g() {}\n/// a\n@x\n// b\nvoid f() {}\n"; + let tree = parser.parse(src, None).unwrap(); + let root = tree.root_node(); + let f = (0..root.named_child_count()) + .filter_map(|i| root.named_child(i)) + .filter(|n| n.kind() == "function_signature") + .nth(1) + .expect("f's signature"); + assert_eq!(preceding_docstring(f, src).as_deref(), Some("b")); + assert_eq!( + preceding_docstring_stepping_over(f, src, &["annotation"]).as_deref(), + Some("a\nb") + ); + } } diff --git a/docs/design/dart-kernel-port-checklist.md b/docs/design/dart-kernel-port-checklist.md index fa80223359..ac165a0b82 100644 --- a/docs/design/dart-kernel-port-checklist.md +++ b/docs/design/dart-kernel-port-checklist.md @@ -855,14 +855,21 @@ BUILTIN_TYPES (:5768-5782), at each leaf's position. Consequences (pinned): Dart annotations are `annotation` (with `name:` field; args form has an `arguments` child) or `marker_annotation`-free — probed: both `@override` (bare) and `@Deprecated('x')` (args) are node type `annotation`, PRECEDING -SIBLINGS of the declaration they decorate (inside program / class_body). +SIBLINGS of the function or method they decorate (inside program / +class_body); a class-like declaration's annotations open its own node +instead (scan #1). extractDecoratorsFor (:4897) is called for classes (:1710), functions (:1599), methods (:1819) — NOT for hook-minted constants, enums(!), or type aliases (extractEnum/extractTypeAlias never call it — an annotated enum emits nothing). Mechanics for dart: - Scan #1 (direct children :4976-4988): annotations are never children of - the signature → inert (no `modifiers` node either). + the signature → inert for functions and methods (no `modifiers` node + either). A class-like declaration is different: class, mixin, extension + and extension type nodes START at their first annotation, which is the + node's own leading child, so scan #1 emits it (`@immutable class Foo` → + decorates `immutable`). Enums and typedefs are built the same way, but + nothing scans them. - Scan #2 (preceding siblings :5002-5023): walk BACKWARD from the declaration; `annotation` is in the accepted set (:5017); stop at the first non-annotation sibling. consider(): target = first namedChild of @@ -876,8 +883,24 @@ enum emits nothing). Mechanics for dart: `@Deprecated('x')\n@pragma('vm:entry-point')\nvoid f()` → decorates `pragma` FIRST, then `Deprecated` (pinned). - For a method: the previous member's function_body (or any declaration) - breaks the chain correctly. The annotation-BETWEEN-doc-and-decl also - breaks the DOCSTRING chain (§Docstrings). + breaks the chain correctly. (The docstring walk steps OVER annotations + since 2026-10-06 — §Docstrings.) +- **A comment between an annotation and the declaration ends the scan**, so + the annotation above it attaches to nothing: `@override` `// ignore: + must_call_super` `void f()`, `@x` `/// Doc below.` `void f()` (pinned in + TortureAnnotatedDocs.dart). Measured 2026-10-06: bloc @b9be1e2 hides 7 + annotations this way (all `@override`), riverpod @4ba1be2 55 on 49 + declarations (`@override` 33, `@riverpod` 16 in the lint fixtures, + `@internal` 6). Left as is ON PURPOSE: stepping over comments here is + right for Dart (an annotation always belongs to the next declaration), but + Dart nodes store no decorator list, so the only effect would be edges, and + `override`/`internal` resolve to nothing, while `decorates` scoring prefers + function/method candidates (name-matcher.ts), so `@riverpod` lands on the + analyzer getter `RiverpodAnnotatedAnnotatedNodeOfX::riverpod` (0.4) + instead of `const riverpod = Riverpod()`. That is already true of + riverpod's 506 existing `@riverpod` edges. Fix that ranking for Dart (a + const or a class, never a method) first, then add `comment` / + `documentation_comment` to scan #2's step-over in both arms. - Members with no body (declaration-wrapped ctors, const ctors, redirecting factories, abstract and `external` members): the signature's PARENT is the `declaration`, so until 2026-10-06 the backward scan ran over the @@ -908,10 +931,55 @@ shared code, port nothing**. DOCSTRING_WRAPPER_TYPES contains no dart kinds getDeclarationWrapper's `declaration` for a member with no body (until 2026-10-06 those looked inside the wrapper and found nothing, e.g. `const BlocProvider.value(…)`'s dartdoc; validation added 32 docstrings on -bloc and 126 on riverpod, none changed or removed). **An `annotation` between the comment run and the -declaration BREAKS the chain** (pinned: `/// Broken by annotation.` -`@deprecated` `void annotated()` → doc undefined — the dominant real-world -loss since `@override` is ubiquitous). Docstrings attach to: functions, +bloc and 126 on riverpod, none changed or removed). + +**The walk steps OVER `annotation` siblings** (since 2026-10-06). Until then +an annotation between the comment run and the declaration ended the walk: +`/// Builds it.` `@override` `Widget build(…)` lost its dartdoc, the +dominant real-world loss since `@override` is everywhere. Now dart.ts sets +`docstringStepOverTypes: ['annotation']`, which docstringFor hands to +getPrecedingDocstring's `stepOver`. The kernel's `docstring_of` calls +docstring.rs's `preceding_docstring_stepping_over(…, &["annotation"])`. +`preceding_docstring` and every other language keep the empty list. +- Stepped over: stacked annotations, multi-line ones (`@Deprecated(` … + `)`), inline ones (`/* c */ @x void f()`, freezed's `@optionalTypeArgs + TResult maybeMap…` on the declaration line), and blank lines, which are + not nodes. This works from a `declaration` wrapper too. +- Comments on either side of an annotation keep the join semantics: + `/// a` `@x` `// b` `void f()` → `a\nb` (was `b`), and `/// Doc.` + `@override` `// ignore: …` → `Doc.\nignore: …`. +- Still ends the walk: any other named sibling, such as the previous + member's `function_body`, a field's or a bodiless member's `declaration`, + a top-level variable (`static_final_declaration_list` / + `initialized_identifier_list`), an `import_or_export` or `part_directive`, + or a class-like declaration. A comment trailing the previous member on its + line (`void a() {} // note`) is collected, as it already was for a member + with no annotation. +- Class-like declarations needed nothing. A class, mixin, extension, + extension type, enum or typedef node starts at its first annotation + (§Decorators), so the dartdoc above the annotations is the node's previous + sibling and was always kept. A comment written BETWEEN such an annotation + and the keyword (`@JsonEnum(…)` `/// The state…` `enum LinterRuleState`) + is inside the node and is NOT read (pinned). bloc has 1 such dartdoc, + riverpod none (23 `// ignore:` lines and 1 plain comment). A member's + comment below its annotation IS read: it is the signature's previous + sibling. +- Local functions get no docstring with or without annotations: the + signature sits in `local_function_declaration > lambda_expression`, with + no previous sibling. +- Validation (bloc @b9be1e2 / riverpod @4ba1be2, 3f96f80f plus the + declaration-wrapper fix, kernel loaded): docstrings +26 / +1,072, changed + 0 / 9 (each a `// ignore:` line below the annotation, now joined after + the dartdoc above), removed 0. Everything else in the dumps (nodes, + edges, refs, files) is byte-identical; kernel and wasm full-index dumps + are byte-identical; the parity sweeps show 0 diffs. bloc's 26 are all + hand-written dartdoc, mostly behind `@mustCallSuper` / `@override`. Of + riverpod's 1,072, 667 runs hold a dartdoc (401 in generated + `.freezed.dart` / `.g.dart` files, 266 hand-written) and 405 are plain + comments only (`// ignore: riverpod_lint/…` in the lint fixtures, the + website's snippet markers). + +Docstrings attach to: functions, methods (incl. `` operators), classes/mixins/extensions, enums, type aliases. NOT to: hook-minted constants (extra carries only signature — pinned drop), enum members, imports, the file node. No comment-gluing into @@ -1152,7 +1220,7 @@ NO unwrap, NO ungatedModes, NO addressOfOnly. Pins: `extract-torture.txt` is the expected-output pin). Inventory by branch: imports (dart:, package: with `as`+`show`, export with `hide`, **deferred → invisible**, part → invisible); doc shapes (`///` run, - `/** */` kept, `//` kept, annotation-broken chain); annotations (bare, + `/** */` kept, `//` kept, a `///` above an annotation); annotations (bare, with-args, stacked → reverse order, on class); top-level constants (CAPS/lowercase/multi/typed/derived, sig truncation ≥100 chars); top-level var/typed-var/getter/setter (all invisible); async vs diff --git a/src/extraction/languages/dart.ts b/src/extraction/languages/dart.ts index 2b74652b1a..0997821c57 100644 --- a/src/extraction/languages/dart.ts +++ b/src/extraction/languages/dart.ts @@ -532,6 +532,13 @@ export const dartExtractor: LanguageExtractor = { if (parent?.type !== 'declaration') return undefined; return parent.firstNamedChild?.equals(node) ? parent : undefined; }, + // A member's annotations stand between it and the dartdoc written above them + // (`/// Builds the widget.` `@override` `Widget build(…)`), so the docstring + // walk steps over them instead of stopping there. A class-like declaration + // (class, mixin, extension, extension type, enum, typedef) needs none of + // this: its annotations open its own node, and the dartdoc above them is + // that node's previous sibling. + docstringStepOverTypes: ['annotation'], resolveBody: (node, bodyField) => { // Dart: function_body is a next sibling of function_signature/method_signature if (node.type === 'function_signature' || node.type === 'method_signature') { diff --git a/src/extraction/tree-sitter-helpers.ts b/src/extraction/tree-sitter-helpers.ts index 8d355a7a05..8ef15f41d5 100644 --- a/src/extraction/tree-sitter-helpers.ts +++ b/src/extraction/tree-sitter-helpers.ts @@ -129,8 +129,17 @@ function cleanCommentMarkers(comment: string): string { /** * Get the docstring/comment preceding a node + * + * `stepOver` lists node types that may stand between the comments and the + * declaration without ending the run: Dart's annotations, in `/// Builds it.` + * `@override` `Widget build(…)`. They are not part of the docstring, and the + * comments on either side of one join as if it weren't there. Default: none. */ -export function getPrecedingDocstring(node: SyntaxNode, source: string): string | undefined { +export function getPrecedingDocstring( + node: SyntaxNode, + source: string, + stepOver: readonly string[] = [] +): string | undefined { // Climb out of any wrapper(s) so a comment preceding the WHOLE construct // (export-, decorator-, or const-arrow-wrapped) is reachable as a sibling. // The emitted node's own `previousNamedSibling` is empty (export/const) or a @@ -153,6 +162,8 @@ export function getPrecedingDocstring(node: SyntaxNode, source: string): string ) { comments.unshift(getNodeText(sibling, source)); sibling = sibling.previousNamedSibling; + } else if (stepOver.includes(sibling.type)) { + sibling = sibling.previousNamedSibling; } else { break; } diff --git a/src/extraction/tree-sitter-types.ts b/src/extraction/tree-sitter-types.ts index d82a66b3c3..5dfafd2053 100644 --- a/src/extraction/tree-sitter-types.ts +++ b/src/extraction/tree-sitter-types.ts @@ -174,6 +174,13 @@ export interface LanguageExtractor { * `void m();`) in a `declaration` node. Returns undefined when there is none. */ getDeclarationWrapper?: (node: SyntaxNode) => SyntaxNode | undefined; + /** + * Node types that may stand between a declaration and the comments written + * above it without ending the comment run its docstring is read from. Dart + * writes annotations there (`/// Builds it.` `@override` `Widget build(…)`): + * each one is stepped over, and comments on either side of it still join. + */ + docstringStepOverTypes?: string[]; /** Extract visibility from node */ getVisibility?: (node: SyntaxNode) => 'public' | 'private' | 'protected' | 'internal' | undefined; /** Check if node is exported */ diff --git a/src/extraction/tree-sitter.ts b/src/extraction/tree-sitter.ts index 561f7e6434..c3bd6fd98a 100644 --- a/src/extraction/tree-sitter.ts +++ b/src/extraction/tree-sitter.ts @@ -563,7 +563,11 @@ export class TreeSitterExtractor { */ private docstringFor(node: SyntaxNode): string | undefined { const anchor = this.extractor?.getDeclarationWrapper?.(node) ?? node; - const preceding = getPrecedingDocstring(anchor, this.source); + const preceding = getPrecedingDocstring( + anchor, + this.source, + this.extractor?.docstringStepOverTypes + ); const body = this.extractor?.getBodyDocstring?.(node, this.source); if (preceding && body) return `${preceding}\n\n${body}`; return body || preceding; From 631df0138e3f6accfc7026a9a8bf9af42bbb5963 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 17:09:46 +0000 Subject: [PATCH 16/23] fix(dart): an import or export links the file its URI names, not a namesake (#2388) A Dart `import` / `export` now resolves its URI through the library model in src/resolution/dart-libraries.ts: `package:/` is `/lib/` of the project package whose pubspec.yaml says `name: `, any other URI is a path from the importing file, and a `dart:` library, a package from outside the project or a file the index does not hold links nothing. The ref never reaches the name-matcher, which took the URI's last segment for a file name (`package:flutter/widgets.dart` reached riverpod_analyzer_utils' widgets.dart from 130 files, bloc_tools' `package:args/command_runner.dart` its own command_runner.dart) or bound it to the importing file's own `import` node. When packages share a name and neither the importer's own package nor one enclosing it settles which, the importing package's `path:` dependency of that name (pubspec_overrides.yaml, then pubspec.yaml) does: bloc's two example apps each keep an authentication_repository. Library visibility reads the same answer. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/dart-import-uris.test.ts | 200 +++++++++++++++++++++++++++++ src/resolution/dart-libraries.ts | 80 +++++++++++- src/resolution/import-resolver.ts | 19 +++ src/resolution/index.ts | 8 +- 5 files changed, 304 insertions(+), 4 deletions(-) create mode 100644 __tests__/dart-import-uris.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bd122abac..cb03bc15a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In JavaScript and TypeScript, a store whose name starts or ends with a `$`, like `const items$ = create(…)`, now has its actions indexed when an `export { … }` list on a later line exports it, as in `export { items$ };` or `export { $items as default };`. Before, those actions were missing from the graph, so their callers and impact came back empty. A store whose name only lacks the `$`, like `items`, is no longer treated as exported by that list. Re-index JavaScript and TypeScript projects after upgrading. - In Dart, a comment inside a chain of calls no longer loses part of it: a call with a comment before its arguments, like `box.grow /* by */ (3)`, now links to the method it calls, and a getter read or a static access written after a comment, like `Config //` followed by `.instance` on the next line (the empty `//` keeps `dart format` from joining the lines), now counts as a use. Re-index Dart projects after upgrading. - In Dart, a call, a constructor call or a type written without a receiver now links only to a declaration the file can see: one in its own library (the file and its `part` files) or one exported by a library it imports, with `export` chains, `show`, `hide` and `as` prefixes followed the way Dart follows them. So a generated `.g.dart` file reaches its own library's function or type instead of a same-named one in a neighbouring file, a call to a package function such as `fakeAsync`, `runApp` or `unawaited` no longer links to an unrelated project function of that name, and a bare call is never taken for another type's enum value or static constant. Re-index Dart projects after upgrading. +- In Dart, an `import` or `export` now links to the file it names: `package:my_app/src/cart.dart` to that package's `lib/src/cart.dart`, and a relative path to the file it points to from the importing file. Before, only the file name at the end was matched, so `import 'package:flutter/widgets.dart'` linked to whichever project file was called `widgets.dart`, and most imports of your own files didn't link to the file at all, which threw off `codegraph affected` and the files listed as using a file. An import of a Dart SDK library or of a package from outside your project now links nothing, and when packages in one repository share a name, the one the importing app depends on by `path:` is used. Re-index Dart projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/dart-import-uris.test.ts b/__tests__/dart-import-uris.test.ts new file mode 100644 index 0000000000..62ed0396ab --- /dev/null +++ b/__tests__/dart-import-uris.test.ts @@ -0,0 +1,200 @@ +/** + * A Dart `import` / `export` names a library by URI, and links the file the + * URI names or nothing. `package:/` is `/lib/` of the + * project package whose pubspec.yaml says `name: `; any other URI is a + * path from the importing file; `dart:` and a package from outside the project + * name no project file. The URI's last path segment is not a file name to + * match: riverpod's `import 'package:flutter/foundation.dart'` went to its own + * packages/riverpod/lib/src/core/foundation.dart, bloc_tools' + * `package:args/command_runner.dart` to the importing file itself, and the + * import of an indexed project file went to the importing file's own `import` + * node, which says nothing. + */ +import { describe, it, expect, afterAll, beforeAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; + +function writeTree(root: string, files: Record): void { + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } +} + +/** ` -> ` for every `imports` edge out of `file`: a file by its path, anything else by kind, file and name. */ +function importsFrom(cg: CodeGraph, file: string): string[] { + const ids = cg.getNodesInFile(file).map((n) => n.id); + return cg.getOutgoingEdgesFrom(ids, ['imports']) + .map((e) => { + const t = cg.getNode(e.target)!; + return `${e.line} -> ${t.kind === 'file' ? t.filePath : `${t.kind} ${t.filePath}#${t.name}`}`; + }) + .sort(); +} + +/** The URIs of `file`'s imports left unresolved. */ +function unresolvedImportsOf(cg: CodeGraph, file: string): string[] { + const fileNode = cg.getNodesInFile(file).find((n) => n.kind === 'file')!; + return cg.getUnresolvedReferencesFrom(fileNode.id) + .filter((r) => r.referenceKind === 'imports') + .map((r) => r.referenceName) + .sort(); +} + +describe('Dart import and export URIs', () => { + let root = ''; + let cg: CodeGraph; + + beforeAll(async () => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-uris-')); + writeTree(root, { + // riverpod: an example app imports flutter's foundation.dart and the + // project's own riverpod package; riverpod has a foundation.dart too. + 'packages/riverpod/pubspec.yaml': 'name: riverpod\n', + 'packages/riverpod/lib/riverpod.dart': `export 'src/core/foundation.dart'; +export 'package:meta/meta.dart' show internal; +`, + 'packages/riverpod/lib/src/core/foundation.dart': `class ProviderBase {} +`, + 'packages/riverpod/lib/src/core/container.dart': `import 'dart:async'; + +import 'package:meta/meta.dart'; + +import 'foundation.dart'; + +class Container extends ProviderBase {} +`, + 'examples/pub/pubspec.yaml': 'name: pub\n', + 'examples/pub/lib/pub_repository.dart': `import 'package:flutter/foundation.dart'; +import 'package:riverpod/riverpod.dart'; +import 'package:riverpod/src/core/foundation.dart' as core; + +class PubRepository {} +`, + // bloc_tools imports package:args' command_runner.dart from its own command_runner.dart. + 'packages/bloc_tools/pubspec.yaml': 'name: bloc_tools\n', + 'packages/bloc_tools/lib/src/command_runner.dart': `import 'package:args/command_runner.dart'; + +class BlocToolsCommandRunner {} +`, + // An integration test imports package:integration_test; a driver beside it is named integration_test.dart. + 'examples/flutter_counter/pubspec.yaml': 'name: flutter_counter\n', + 'examples/flutter_counter/integration_test/app_test.dart': `import 'package:integration_test/integration_test.dart'; + +void main() {} +`, + 'examples/flutter_counter/test_driver/integration_test.dart': `import 'package:integration_test/integration_test_driver.dart'; + +Future main() async {} +`, + // A relative import, and an old file with the same name. + 'pubspec.yaml': 'name: app\n', + 'test/src/utils.dart': `int errorsOf() => 0; +`, + 'test/old/utils.dart': `int errorsOf() => 0; +`, + 'test/feature/uni_directional_test.dart': `import '../src/utils.dart'; + +void main() {} +`, + // A translated copy of a docs page whose sibling was never translated. + 'website/docs/cancel/detail_screen/codegen.dart': `class DetailScreen {} +`, + 'website/i18n/it/cancel/home_screen.dart': `import 'detail_screen/codegen.dart'; + +class HomeScreen {} +`, + // Two apps each keep a package named auth_repo, and each app's pubspec says which by path. + 'examples/login_a/pubspec.yaml': `name: login_a +dependencies: + auth_repo: + # the app's own copy + path: packages/auth_repo + bloc: ^9.0.0 +`, + 'examples/login_a/packages/auth_repo/pubspec.yaml': 'name: auth_repo\n', + 'examples/login_a/packages/auth_repo/lib/auth_repo.dart': `class AuthRepo {} +`, + 'examples/login_a/lib/app.dart': `import 'package:auth_repo/auth_repo.dart'; + +class AppA {} +`, + 'examples/login_b/pubspec.yaml': `name: login_b +dependencies: + auth_repo: { path: "packages/auth_repo" } +`, + 'examples/login_b/packages/auth_repo/pubspec.yaml': 'name: auth_repo\n', + 'examples/login_b/packages/auth_repo/lib/auth_repo.dart': `class AuthRepo {} +`, + 'examples/login_b/lib/app.dart': `import 'package:auth_repo/auth_repo.dart'; + +class AppB {} +`, + // A third app says nothing about which auth_repo it means. + 'examples/login_c/pubspec.yaml': 'name: login_c\n', + 'examples/login_c/lib/app.dart': `import 'package:auth_repo/auth_repo.dart'; + +class AppC {} +`, + // Packages named example: each one's own package: imports mean itself. + 'packages/a/example/pubspec.yaml': 'name: example\n', + 'packages/a/example/lib/main.dart': `import 'package:example/src/screen.dart'; + +void main() {} +`, + 'packages/a/example/lib/src/screen.dart': `class ScreenA {} +`, + 'packages/b/example/pubspec.yaml': 'name: example\n', + 'packages/b/example/lib/src/screen.dart': `class ScreenB {} +`, + // A package import of a file the project doesn't have (a generated file nobody committed). + 'packages/riverpod/lib/src/missing_user.dart': `import 'package:riverpod/src/core/foundation.g.dart'; +import 'package:riverpod/src/missing_user.dart'; +`, + }); + cg = await CodeGraph.init(root, { index: true }); + }); + + afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + }); + + it("links an outside package's import to no project file of the same name", () => { + expect(importsFrom(cg, 'examples/pub/lib/pub_repository.dart')).toEqual([ + '2 -> packages/riverpod/lib/riverpod.dart', + '3 -> packages/riverpod/lib/src/core/foundation.dart', + ]); + expect(unresolvedImportsOf(cg, 'examples/pub/lib/pub_repository.dart')).toEqual(['package:flutter/foundation.dart']); + }); + + it('never links a file to itself or a namesake for an outside package', () => { + expect(importsFrom(cg, 'packages/bloc_tools/lib/src/command_runner.dart')).toEqual([]); + expect(importsFrom(cg, 'examples/flutter_counter/integration_test/app_test.dart')).toEqual([]); + expect(importsFrom(cg, 'examples/flutter_counter/test_driver/integration_test.dart')).toEqual([]); + }); + + it('links a relative import and an export to the file they name, and dart: or outside packages to nothing', () => { + expect(importsFrom(cg, 'packages/riverpod/lib/src/core/container.dart')).toEqual([ + '5 -> packages/riverpod/lib/src/core/foundation.dart', + ]); + expect(unresolvedImportsOf(cg, 'packages/riverpod/lib/src/core/container.dart')).toEqual(['dart:async', 'package:meta/meta.dart']); + expect(importsFrom(cg, 'packages/riverpod/lib/riverpod.dart')).toEqual(['1 -> packages/riverpod/lib/src/core/foundation.dart']); + expect(importsFrom(cg, 'test/feature/uni_directional_test.dart')).toEqual(['1 -> test/src/utils.dart']); + }); + + it('links nothing when the file a URI names is not in the project', () => { + expect(importsFrom(cg, 'website/i18n/it/cancel/home_screen.dart')).toEqual([]); + // Nor does a file's import of itself say anything. + expect(importsFrom(cg, 'packages/riverpod/lib/src/missing_user.dart')).toEqual([]); + }); + + it("tells same-named packages apart by the importing package's own name or its path dependency", () => { + expect(importsFrom(cg, 'examples/login_a/lib/app.dart')).toEqual(['1 -> examples/login_a/packages/auth_repo/lib/auth_repo.dart']); + expect(importsFrom(cg, 'examples/login_b/lib/app.dart')).toEqual(['1 -> examples/login_b/packages/auth_repo/lib/auth_repo.dart']); + expect(importsFrom(cg, 'examples/login_c/lib/app.dart')).toEqual([]); + expect(importsFrom(cg, 'packages/a/example/lib/main.dart')).toEqual(['1 -> packages/a/example/lib/src/screen.dart']); + }); +}); diff --git a/src/resolution/dart-libraries.ts b/src/resolution/dart-libraries.ts index 18c2d7930f..270fe34090 100644 --- a/src/resolution/dart-libraries.ts +++ b/src/resolution/dart-libraries.ts @@ -14,7 +14,9 @@ * pubspec.yaml says `name: `: the nearest pubspec.yaml above an indexed * .dart file, never above the project root. When packages share a name * (example apps), the importing file's own package wins, then the one - * enclosing it, else all of them count. + * enclosing it, then the one its package depends on by `path:`, else all of + * them count. An `import` / `export` edge links the one file its URI names + * (`dartDirectiveFile`). * * Directives are read from the head of each file at resolution time; * extraction, and the kernel's, are unchanged. Where the library cannot be @@ -357,6 +359,8 @@ interface Memo { directives: Map; packageOfDir: Map; packages: Map | null; + /** By package root and dependency name, the directories its `path:` dependencies of that name point at. */ + pathDependencies: Map; libraryNames: Map | null; libraryOf: Map; /** A part's parent: the file its `part of` names. */ @@ -375,6 +379,7 @@ function memoFor(context: ResolutionContext): Memo { directives: new Map(), packageOfDir: new Map(), packages: null, + pathDependencies: new Map(), libraryNames: null, libraryOf: new Map(), parentOf: new Map(), @@ -450,6 +455,62 @@ function packagesNamed(name: string, context: ResolutionContext, memo: Memo): re return memo.packages.get(name) ?? []; } +/** + * The `path:` a pubspec gives its dependency `name`, written as a block + * (`name:`, then `path: x` below it) or a flow mapping (`name: {path: x}`). + * A git dependency's `path:` (inside its `git:` mapping) is a path in that + * repository, so only `path:` directly under the name counts. + */ +function yamlPathDependencies(text: string, name: string): string[] { + const out: string[] = []; + const lines = text.split(/\r?\n/); + for (let i = 0; i < lines.length; i++) { + const key = /^([ \t]+)(['"]?)([A-Za-z_]\w*)\2[ \t]*:(?:[ \t]+(.*))?$/.exec(lines[i]!); + if (!key || key[3] !== name) continue; + const value = (key[4] ?? '').replace(/(?:^|[ \t])#.*$/, '').trim(); + if (value !== '') { + const flow = /^\{[^{}]*\}$/.test(value) + ? /[{,][ \t]*path[ \t]*:[ \t]*(?:"([^"]*)"|'([^']*)'|([^,}\s]+))/.exec(value) + : null; + if (flow) out.push(flow[1] ?? flow[2] ?? flow[3]!); + continue; + } + let childIndent = -1; + for (let j = i + 1; j < lines.length; j++) { + const line = lines[j]!; + if (/^[ \t]*(?:#.*)?$/.test(line)) continue; + const indent = /^[ \t]*/.exec(line)![0].length; + if (indent <= key[1]!.length) break; + if (childIndent < 0) childIndent = indent; + const dep = indent === childIndent ? /^[ \t]*path[ \t]*:[ \t]*(?:"([^"]*)"|'([^']*)'|([^\s#]+))/.exec(line) : null; + if (dep) out.push(dep[1] ?? dep[2] ?? dep[3]!); + } + } + return out; +} + +/** The project directories `pkg`'s pubspec_overrides.yaml and pubspec.yaml give as the `path:` of its dependency `name`. */ +function pathDependencies(pkg: PubPackage, name: string, context: ResolutionContext, memo: Memo): readonly string[] { + const key = `${pkg.root}\0${name}`; + const hit = memo.pathDependencies.get(key); + if (hit) return hit; + const dirs: string[] = []; + for (const file of ['pubspec_overrides.yaml', 'pubspec.yaml']) { + const pubspec = pkg.root ? `${pkg.root}/${file}` : file; + const text = context.fileExists(pubspec) ? context.readFile(pubspec) : null; + for (const written of text ? yamlPathDependencies(text, name) : []) { + const dep = written.replace(/\\/g, '/'); + if (dep.startsWith('/') || /^[A-Za-z]:/.test(dep)) continue; + const dir = path.posix.normalize(path.posix.join(pkg.root || '.', dep)).replace(/\/+$/, ''); + if (dir === '..' || dir.startsWith('../')) continue; + const root = dir === '.' ? '' : dir; + if (!dirs.includes(root)) dirs.push(root); + } + } + memo.pathDependencies.set(key, dirs); + return dirs; +} + /** The project files a URI written in `from` names: none for `dart:` and other schemes, or a package outside the project. */ function resolveDartUri(from: string, uri: string, context: ResolutionContext, memo: Memo): string[] { if (uri.startsWith('package:')) { @@ -463,6 +524,13 @@ function resolveDartUri(from: string, uri: string, context: ResolutionContext, m const enclosing = chosen.filter((p) => p.root === '' || from.startsWith(`${p.root}/`)); if (own && own.name === name) chosen = [own]; else if (enclosing.length > 0) chosen = [enclosing.reduce((a, b) => (b.root.length > a.root.length ? b : a))]; + else if (own) { + // Example apps that each keep a same-named package (bloc's two + // authentication_repository) name theirs as a path dependency. + const dirs = pathDependencies(own, name, context, memo); + const declared = chosen.filter((p) => dirs.includes(p.root)); + if (declared.length === 1) chosen = declared; + } } return chosen.map((p) => path.posix.normalize(p.root ? `${p.root}/lib/${rest}` : `lib/${rest}`)); } @@ -471,6 +539,16 @@ function resolveDartUri(from: string, uri: string, context: ResolutionContext, m return joined === '..' || joined.startsWith('../') || joined.startsWith('/') ? [] : [joined]; } +/** + * The project file a Dart `import` or `export` in `from` names by `uri`, or + * null: a `dart:` library, a package from outside the project, a path out of + * it, or a package name the project repeats with nothing to say which. + */ +export function dartDirectiveFile(from: string, uri: string, context: ResolutionContext): string | null { + const files = resolveDartUri(from, uri, context, memoFor(context)); + return files.length === 1 ? files[0]! : null; +} + /** The files declaring `library ;`. */ function libraryFilesNamed(name: string, context: ResolutionContext, memo: Memo): readonly string[] { if (!memo.libraryNames) { diff --git a/src/resolution/import-resolver.ts b/src/resolution/import-resolver.ts index 07236bfc92..b6a8e66bb7 100644 --- a/src/resolution/import-resolver.ts +++ b/src/resolution/import-resolver.ts @@ -12,6 +12,7 @@ import { applyAliases } from './path-aliases'; import { extractLocalExportAliases } from './alias-binding'; import { resolveWorkspaceImport } from './workspace-packages'; import { stripCommentsForRegex } from './strip-comments'; +import { dartDirectiveFile } from './dart-libraries'; import { resolveMethodOnType, resolveObjectLiteralMember, @@ -892,6 +893,17 @@ export function isCobolCopybookRef(ref: UnresolvedRef): boolean { return ref.language === 'cobol' && ref.referenceKind === 'imports'; } +/** + * Is this a Dart `import` / `export`? Its name is the URI, which names one + * library file (see ./dart-libraries) or none — `dart:async`, a package from + * outside the project — and never a symbol: the name-matcher took the URI's + * last segment for a file name (`package:flutter/foundation.dart` went to + * riverpod's own foundation.dart) or bound it to the file's own `import` node. + */ +export function isDartImportRef(ref: UnresolvedRef): boolean { + return ref.language === 'dart' && ref.referenceKind === 'imports'; +} + /** * Resolve a PHP include/require path to a project-relative file path. * @@ -1639,6 +1651,13 @@ export function resolveViaImport( const fileNode = file && file !== ref.filePath ? context.getNodesInFile(file).find((n) => n.kind === 'file') : undefined; if (fileNode) return { original: ref, targetNodeId: fileNode.id, confidence: 0.9, resolvedBy: 'import' }; } + // A Dart `import` / `export` URI names a library file: `package:app/x.dart` + // is app's lib/x.dart, any other path is from the importing file. + if (isDartImportRef(ref)) { + const file = dartDirectiveFile(ref.filePath, ref.referenceName, context); + const fileNode = file && file !== ref.filePath ? context.getNodesInFile(file).find((n) => n.kind === 'file') : undefined; + return fileNode ? { original: ref, targetNodeId: fileNode.id, confidence: 0.9, resolvedBy: 'import' } : null; + } // C/C++ #include references — resolve directly to the included file // (file→file edge), bypassing symbol lookup. The extractor emits these // with `referenceKind: 'imports'` and `referenceName: ` diff --git a/src/resolution/index.ts b/src/resolution/index.ts index 5fdbf2d9be..f94cf0a16d 100644 --- a/src/resolution/index.ts +++ b/src/resolution/index.ts @@ -29,7 +29,7 @@ import { clearDartLibraryMemos } from './dart-libraries'; import { clearVbnetReceiverMemos, isVbMemberRead, isVbPathCall, matchVbMemberRead, matchVbPathCall } from './vbnet-receivers'; import { gateTypeParameter, clearTypeParameterMemos } from './type-parameters'; import { gateDartLocal, clearDartLocalScopeMemos } from './dart-local-scope'; -import { resolveViaImport, resolvePhpImportedStaticCall, resolvePhpQualifiedClassRef, resolveJvmImport, extractImportMappings, extractReExports, loadCppIncludeDirs, isPhpIncludePathRef, isCobolCopybookRef, isNixPathImportRef, isJsPathImportRef, isBoundToOutOfRepoImport, clearImportResolverMemos, resolveImportPath, isExternalImport } from './import-resolver'; +import { resolveViaImport, resolvePhpImportedStaticCall, resolvePhpQualifiedClassRef, resolveJvmImport, extractImportMappings, extractReExports, loadCppIncludeDirs, isPhpIncludePathRef, isCobolCopybookRef, isNixPathImportRef, isDartImportRef, isJsPathImportRef, isBoundToOutOfRepoImport, clearImportResolverMemos, resolveImportPath, isExternalImport } from './import-resolver'; import { ResolverPool, minRefsForPool, shouldEngageAdaptively } from './resolver-pool'; import { resolveAliasBinding } from './alias-binding'; import { detectFrameworks } from './frameworks'; @@ -1354,8 +1354,10 @@ export class ReferenceResolver { // bind outside its module directory), so the name-matcher's // qualified-name fallback would only ever add wrong cross-module edges. // Nix static path imports are file references for the same reason — - // falling through would let "./x.nix" name-match an unrelated node. - if (isPhpIncludePathRef(ref) || isCobolCopybookRef(ref) || isNixPathImportRef(ref) || ref.language === 'terraform') { + // falling through would let "./x.nix" name-match an unrelated node. So + // is a Dart import's URI: `package:flutter/foundation.dart` matched by + // its last segment went to riverpod's own foundation.dart. + if (isPhpIncludePathRef(ref) || isCobolCopybookRef(ref) || isNixPathImportRef(ref) || isDartImportRef(ref) || ref.language === 'terraform') { return candidates.length > 0 ? candidates.reduce((best, curr) => curr.confidence > best.confidence ? curr : best From d2fb323e5101046fe198d16ec3900854b2e9b1ce Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 17:27:41 +0000 Subject: [PATCH 17/23] fix(dart): an annotation links the constant or constructor it names, even behind a comment (#2390) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A Dart annotation is a constant expression: a const variable (`@riverpod`, `@meta.immutable`, a type's static constant or enum value) or a call of a const constructor (`@Riverpod(keepAlive: true)`, `@Foo.named(…)`). It was ranked like a Python decorator, which favours a function or method of that name over a class and scores a constant not at all, so riverpod's 506 `@riverpod` annotations went to riverpod_analyzer_utils' extension getter `riverpod` (0.4) instead of riverpod_annotation's `const riverpod = Riverpod();`. matchDartAnnotation (name-matcher.ts) now takes every Dart `decorates` ref before any other strategy, and nothing falls through. It reads the annotation as written from its `@` and links a constant or (called) a class the file's library can see, through the import prefix it is written with (isDartImportPrefix, dart-libraries.ts); a type's own static constant, enum value or (called) named constructor (isDartConstructor); or, on a member, a static constant of the type around it. Never a method, getter or function. The decorator scan also stopped at the first sibling that was not an annotation, so a comment between an annotation and its declaration (`@override` `// ignore: must_call_super` `void f()`, riverpod_lint's `@riverpod` `// expect_lint: …` fixtures) hid the annotation. Dart's decoratorStepOverTypes lists its two comment kinds, which the scan now steps over, and the kernel's extract_decorators_for steps over the same. Validated on rrousselGit/riverpod @4ba1be2 and felangel/bloc @b9be1e2 with the kernel loaded: riverpod's 506 `@riverpod` edges move to `const riverpod` and 16 annotations behind a comment add an edge each, with nothing removed; bloc gains 7 `@override` refs and no edge changes. Kernel and wasm full-index dumps are byte-identical, and the parity sweeps show 0 diffs. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 2 + __tests__/dart-annotation-comments.test.ts | 167 +++++++++++++++++ __tests__/dart-annotation-targets.test.ts | 167 +++++++++++++++++ .../TortureAnnotatedComments.dart | 175 ++++++++++++++++++ __tests__/kernel-dart-parity.test.ts | 12 +- codegraph-kernel/src/dart.rs | 12 +- docs/design/dart-kernel-port-checklist.md | 95 +++++++--- src/extraction/languages/dart.ts | 4 + src/extraction/tree-sitter-types.ts | 7 + src/extraction/tree-sitter.ts | 5 +- src/resolution/dart-libraries.ts | 11 ++ src/resolution/index.ts | 5 +- src/resolution/name-matcher.ts | 129 ++++++++++++- 13 files changed, 761 insertions(+), 30 deletions(-) create mode 100644 __tests__/dart-annotation-comments.test.ts create mode 100644 __tests__/dart-annotation-targets.test.ts create mode 100644 __tests__/fixtures/kernel-parity/TortureAnnotatedComments.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index cb03bc15a3..e088fa7a79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,8 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In Dart, a comment inside a chain of calls no longer loses part of it: a call with a comment before its arguments, like `box.grow /* by */ (3)`, now links to the method it calls, and a getter read or a static access written after a comment, like `Config //` followed by `.instance` on the next line (the empty `//` keeps `dart format` from joining the lines), now counts as a use. Re-index Dart projects after upgrading. - In Dart, a call, a constructor call or a type written without a receiver now links only to a declaration the file can see: one in its own library (the file and its `part` files) or one exported by a library it imports, with `export` chains, `show`, `hide` and `as` prefixes followed the way Dart follows them. So a generated `.g.dart` file reaches its own library's function or type instead of a same-named one in a neighbouring file, a call to a package function such as `fakeAsync`, `runApp` or `unawaited` no longer links to an unrelated project function of that name, and a bare call is never taken for another type's enum value or static constant. Re-index Dart projects after upgrading. - In Dart, an `import` or `export` now links to the file it names: `package:my_app/src/cart.dart` to that package's `lib/src/cart.dart`, and a relative path to the file it points to from the importing file. Before, only the file name at the end was matched, so `import 'package:flutter/widgets.dart'` linked to whichever project file was called `widgets.dart`, and most imports of your own files didn't link to the file at all, which threw off `codegraph affected` and the files listed as using a file. An import of a Dart SDK library or of a package from outside your project now links nothing, and when packages in one repository share a name, the one the importing app depends on by `path:` is used. Re-index Dart projects after upgrading. +- In Dart, an annotation now links to the constant or constructor it names, read the way it is written: `@riverpod` reaches Riverpod's `const riverpod = Riverpod();`, `@Riverpod(keepAlive: true)` the `Riverpod` class, an annotation written through a class, like `@SomeClass.value` or `@SomeClass.named(…)`, that class's own constant, enum value or constructor, and `@meta.immutable` only what the `meta` import brings in. Before, an annotation was matched like a function decorator, so a method, getter or function that only shared its name won: every `@riverpod` provider in Riverpod's own repository was linked to an unrelated getter called `riverpod`, and `callers` and impact for the real annotation missed them. Re-index Dart projects after upgrading. +- In Dart, an annotation is no longer lost when a comment sits between it and the declaration, like `@override` followed by `// ignore: must_call_super`, a `///` comment written below the annotations, or `@riverpod` followed by an `// expect_lint: …` line. Before, the comment hid the annotation, so a provider written that way was missing from the annotation's `callers` and impact. Re-index Dart projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/dart-annotation-comments.test.ts b/__tests__/dart-annotation-comments.test.ts new file mode 100644 index 0000000000..567678be07 --- /dev/null +++ b/__tests__/dart-annotation-comments.test.ts @@ -0,0 +1,167 @@ +/** + * A comment between a Dart annotation and the declaration it belongs to hid + * the annotation: + * + * @override + * // ignore: must_call_super + * void dispose() { … } + * + * Both extractors look for a member's annotations among the siblings before + * it, and stopped at the first one that was not an annotation, so the comment + * ended the scan and `@override` was recorded nowhere. felangel/bloc hid 7 + * annotations this way and rrousselGit/riverpod 55, among them its lint + * fixtures' `@riverpod` `// expect_lint: …` providers. + * + * An annotation always belongs to the declaration that follows it, so the + * scan now steps over line, block and doc comments of either form, wherever + * they sit among stacked annotations. Whatever else comes first (a field, the + * previous member's body, a top-level variable, an import) still ends it. + * + * Runs against the native kernel (when built) and the wasm extractor, which + * must agree. + */ +import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as path from 'path'; +import { extractFromSource } from '../src/extraction'; +import { initGrammars, loadGrammarsForLanguages } from '../src/extraction/grammars'; +import { tryKernelExtract, resetKernelForTests } from '../src/extraction/kernel'; +import type { ExtractionResult } from '../src/types'; + +const KERNEL_PATH = path.join( + __dirname, + '..', + 'codegraph-kernel', + 'prebuilds', + `${process.platform}-${process.arch}`, + 'codegraph-kernel.node' +); +const kernelAvailable = fs.existsSync(KERNEL_PATH) || process.env.CODEGRAPH_KERNEL_EXPECT === '1'; + +const SOURCE = `import 'package:meta/meta.dart'; +// After the import. +@visibleForTesting +// Below the annotation. +void afterImport() {} + +@override // On the annotation's line. +void trailing() {} + +@riverpod +// expect_lint: functional_ref +int counter(Ref ref) => 0; + +@Deprecated('x') +/// Doc below the annotation. +/* And a block comment. */ +void docBelow() {} + +@a +// one +@b +/** two */ +@c +void stacked() {} + +@x +final answer = 42; +// After a variable. +void afterVariable() {} + +class Counter { + @override + // ignore: must_call_super + void dispose() {} + + @protected + // A comment. + void bodiless(); + + @literal + // A comment. + const Counter.zero(); + + @x /* inline */ void inline() {} + + @JsonKey(name: 'value') + final int value = 0; + // After a field. + void afterField() {} + + void before() {} // Trailing the previous member. + @override + void afterBody() {} +} +`; + +const ENV_KEYS = ['CODEGRAPH_KERNEL', 'CODEGRAPH_KERNEL_LANGS'] as const; + +describe('Dart annotations behind a comment still decorate the declaration', () => { + let savedEnv: Record = {}; + + beforeAll(async () => { + await initGrammars(); + await loadGrammarsForLanguages(['dart']); + }); + + beforeEach(() => { + savedEnv = Object.fromEntries(ENV_KEYS.map((k) => [k, process.env[k]])); + resetKernelForTests(); + }); + + afterEach(() => { + for (const k of ENV_KEYS) { + if (savedEnv[k] === undefined) delete process.env[k]; + else process.env[k] = savedEnv[k]; + } + resetKernelForTests(); + }); + + function extract(backend: 'kernel' | 'wasm', source: string): ExtractionResult { + if (backend === 'wasm') { + process.env.CODEGRAPH_KERNEL = '0'; + return extractFromSource('lib/counter.dart', source, 'dart'); + } + delete process.env.CODEGRAPH_KERNEL; + process.env.CODEGRAPH_KERNEL_LANGS = 'all'; + const result = tryKernelExtract('lib/counter.dart', source, 'dart'); + expect(result, 'kernel extraction').not.toBeNull(); + return result!; + } + + const backends = kernelAvailable ? (['kernel', 'wasm'] as const) : (['wasm'] as const); + + for (const crlf of [false, true]) { + it.each(backends)(`%s${crlf ? ' (CRLF)' : ''}`, (backend) => { + const result = extract(backend, crlf ? SOURCE.replace(/\n/g, '\r\n') : SOURCE); + /** The annotation names recorded on a declaration, in the order they were emitted. */ + const decorators = (qualifiedName: string): string[] => { + const node = result.nodes.find((n) => n.qualifiedName === qualifiedName); + expect(node, qualifiedName).toBeDefined(); + return result.unresolvedReferences + .filter((r) => r.referenceKind === 'decorates' && r.fromNodeId === node!.id) + .map((r) => r.referenceName); + }; + + // Line, block and doc comments between an annotation and its declaration. + expect(decorators('afterImport')).toEqual(['visibleForTesting']); + expect(decorators('trailing')).toEqual(['override']); + expect(decorators('counter')).toEqual(['riverpod']); + expect(decorators('docBelow')).toEqual(['Deprecated']); + // Stacked ones still come in reverse source order. + expect(decorators('stacked')).toEqual(['c', 'b', 'a']); + + // Members, one with no body and a `const` constructor (both read from + // before their `declaration`), and a comment on the member's line. + expect(decorators('Counter::dispose')).toEqual(['override']); + expect(decorators('Counter::bodiless')).toEqual(['protected']); + expect(decorators('Counter::zero')).toEqual(['literal']); + expect(decorators('Counter::inline')).toEqual(['x']); + expect(decorators('Counter::afterBody')).toEqual(['override']); + + // An annotation before a top-level variable or a field is theirs. + expect(decorators('afterVariable')).toEqual([]); + expect(decorators('Counter::afterField')).toEqual([]); + }); + } +}); diff --git a/__tests__/dart-annotation-targets.test.ts b/__tests__/dart-annotation-targets.test.ts new file mode 100644 index 0000000000..7d5640a1cd --- /dev/null +++ b/__tests__/dart-annotation-targets.test.ts @@ -0,0 +1,167 @@ +/** + * A Dart annotation is a constant expression: a reference to a `const` + * variable (`@riverpod`, `@override`, `@meta.immutable`, a type's static + * constant `@Riverpod.scoped` or enum value) or a call of a `const` + * constructor (`@Riverpod(keepAlive: true)`, `@Riverpod.forever()`). It is + * never a method, a getter or a function. + * + * The extractor records only an annotation's last name, and `decorates` + * references were ranked like Python decorators, which are functions: a + * function or method of that name scored above a class, and a constant scored + * nothing. So riverpod's 506 `@riverpod` annotations went to + * riverpod_analyzer_utils' extension getter `riverpod` instead of + * riverpod_annotation's `const riverpod = Riverpod();`. + * + * An annotation now means what its library can see, read from how it is + * written: a constant or a class (through its import prefix, if it has one), + * a constant, enum value or named constructor of the type it is written + * through, or, on a member, a static constant of the type around it. A + * comment between it and the declaration (riverpod_lint's `@riverpod` + * `// expect_lint: …` fixtures) no longer hides it. + * + * Runs against the native kernel (when built) and the wasm extractor. + */ +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; + +const FILES: Record = { + 'packages/riverpod_annotation/pubspec.yaml': 'name: riverpod_annotation\n', + 'packages/riverpod_annotation/lib/riverpod_annotation.dart': `export 'src/riverpod_annotation.dart'; +`, + 'packages/riverpod_annotation/lib/src/riverpod_annotation.dart': `final class Riverpod { + const Riverpod({this.keepAlive = false}); + + const Riverpod.forever() : keepAlive = true; + + static const scoped = Riverpod(); + + final bool keepAlive; +} + +const riverpod = Riverpod(); + +enum Retry { never, always } +`, + // A getter and a function sharing annotation names, in a package the app + // does not import. + 'packages/riverpod_analyzer_utils/pubspec.yaml': 'name: riverpod_analyzer_utils\n', + 'packages/riverpod_analyzer_utils/lib/src/nodes.dart': `part 'nodes/annotation.dart'; + +const _ast = Object(); + +class AnnotatedNode {} + +bool protected(Object node) => true; +`, + 'packages/riverpod_analyzer_utils/lib/src/nodes/annotation.dart': `part of '../nodes.dart'; + +@_ast +extension RiverpodAnnotatedAnnotatedNodeOfX on AnnotatedNode { + Object? get riverpod => null; +} +`, + 'examples/counter/pubspec.yaml': 'name: counter\n', + 'examples/counter/lib/counter.dart': `import 'package:meta/meta.dart' as meta; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +@riverpod +int counter(Object ref) => 0; + +@riverpod +// expect_lint: functional_ref +int linted(Object ref) => 0; + +@Riverpod(keepAlive: true) +class Todos { + static const marker = Riverpod(); + + @marker + void add() {} + + @meta.protected + void reset() {} +} + +@Riverpod.forever() +int kept(Object ref) => 0; + +@Riverpod.scoped +int scopedCounter(Object ref) => 0; + +@Retry.always +int retried(Object ref) => 0; + +@meta.immutable +class Frozen {} +`, + // A constant of an annotation's name that counter.dart does not import. + 'examples/counter/lib/immutable.dart': `const immutable = Object(); +`, +}; + +describe('Dart annotations name a constant or a constructor', () => { + let root = ''; + let cg: CodeGraph | undefined; + let kernel: string | undefined; + + beforeEach(() => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-annotations-')); + for (const [rel, content] of Object.entries(FILES)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + kernel = process.env.CODEGRAPH_KERNEL; + }); + + afterEach(() => { + cg?.close(); + cg = undefined; + fs.rmSync(root, { recursive: true, force: true }); + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; + }); + + /** ` @ -> :` for each `decorates` edge. */ + function decorations(graph: CodeGraph): string[] { + const files = Object.keys(FILES).filter((f) => f.endsWith('.dart')); + const ids = files.flatMap((f) => graph.getNodesInFile(f).map((n) => n.id)); + return graph.getOutgoingEdgesFrom(ids) + .filter((e) => e.kind === 'decorates') + .map((e) => { + const from = graph.getNode(e.source)!; + const to = graph.getNode(e.target)!; + return `${from.qualifiedName} @${String(e.metadata?.refName ?? '')} -> ${to.kind} ${to.filePath}:${to.qualifiedName}`; + }) + .sort(); + } + + it.each(['default', 'wasm'])('link what the annotation is written as (%s)', async (backend) => { + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; + cg = await CodeGraph.init(root, { index: true }); + + const annotation = 'packages/riverpod_annotation/lib/src/riverpod_annotation.dart'; + const app = 'examples/counter/lib/counter.dart'; + expect(decorations(cg)).toEqual([ + // A private constant of the library, declared in the file the part belongs to. + `RiverpodAnnotatedAnnotatedNodeOfX @_ast -> constant packages/riverpod_analyzer_utils/lib/src/nodes.dart:_ast`, + // A constructor call names the class; a named one, its constructor. + `Todos @Riverpod -> class ${annotation}:Riverpod`, + // On a member, a static constant of the class around it. + `Todos::add @marker -> constant ${app}:Todos::marker`, + // The constant riverpod_annotation exports — not the analyzer's getter. + `counter @riverpod -> constant ${annotation}:riverpod`, + `kept @forever -> method ${annotation}:Riverpod::forever`, + // A comment between the annotation and the declaration hides nothing. + `linted @riverpod -> constant ${annotation}:riverpod`, + // An enum value and a static constant, written through their type. + `retried @always -> enum_member ${annotation}:Retry::always`, + `scopedCounter @scoped -> constant ${annotation}:Riverpod::scoped`, + // `@meta.protected` and `@meta.immutable` are package:meta's: not the + // project's function `protected`, nor a constant counter.dart cannot see. + ]); + }); +}); diff --git a/__tests__/fixtures/kernel-parity/TortureAnnotatedComments.dart b/__tests__/fixtures/kernel-parity/TortureAnnotatedComments.dart new file mode 100644 index 0000000000..87d32a23da --- /dev/null +++ b/__tests__/fixtures/kernel-parity/TortureAnnotatedComments.dart @@ -0,0 +1,175 @@ +// An annotation belongs to the declaration after it, whatever comments come +// between them; the decorator scan steps over `//`, `/* */`, `///` and +// `/** */` comments. Anything else before the annotations still ends it. + +import 'package:meta/meta.dart'; +// A comment after the import. +@visibleForTesting +// And one below the annotation. +void afterImport() {} + +@x // A comment on the annotation's line. +void trailing() {} + +@override +// ignore: must_call_super +void lineBelow() {} + +@x +/// Doc below an annotation. +void docBelow() {} + +@x +/** Block doc below an annotation. */ +void blockDocBelow() {} + +@x +/* A block comment. */ +void blockBelow() {} + +@a +// one +@b +/// two +/* three */ +@c +// four +void interleaved() {} + +@riverpod +// expect_lint: functional_ref +int counter(Ref ref) => 0; + +@x +// A comment. + +void blankLines() {} + +@pragma('vm:external-name', 'f') +// A comment. +external int extTop(); + +@x +// A comment. +int get topGetter => 1; + +@x +final answer = 42; +// A comment. +void afterVariable() {} + +void before() {} // A trailing comment. +@x +void afterBody() {} + +class C { + @override + // ignore: must_call_super + void method() {} + + @x /* inline */ void inline() {} + + @override + // A comment. + void bodiless(); + + @x + // A comment. + C.named() {} + + @literal + // A comment. + const C.c(); + + @x + /// Doc below. + factory C.make() => C._(); + + @x + // A comment. + const factory C.r() = C.c; + + @x + // A comment. + static void s() {} + + @override + // A comment. + bool operator ==(Object other) => true; + + @override + // A comment. + int get value => 1; + + @override + // A comment. + set value(int v) {} + + @x + // A comment. + external void ext(); + + /// Doc above. + @a + // between + @b + void docAbove() {} + + @JsonKey(name: 'f') + final int f = 0; + // A comment after a field. + @override + void afterField() {} + + void prior() {} // A trailing comment. + @override + void afterMember() {} + + C._(); +} + +@immutable +// ignore: something +class D {} + +@internal +// A comment. +mixin M on C { + @mustCallSuper + // A comment. + void m() {} +} + +@internal +// A comment. +extension X on C { + @pragma('vm:prefer-inline') + // A comment. + void e() {} +} + +@internal +/// Doc below. +extension type Meters(double value) { + @redeclare + // A comment. + double km() => value / 1000; +} + +enum Mode { + @JsonValue('on') + // A comment. + on, + off; + + @override + // A comment. + String toString() => name; +} + +void outer() { + @pragma('vm:prefer-inline') + // A comment. + void local() {} + local(); +} diff --git a/__tests__/kernel-dart-parity.test.ts b/__tests__/kernel-dart-parity.test.ts index 104d6f423d..08aec13e5c 100644 --- a/__tests__/kernel-dart-parity.test.ts +++ b/__tests__/kernel-dart-parity.test.ts @@ -33,9 +33,10 @@ * `declaration`-wrapped member with no body, read from before the wrapper; * TortureCommentChains.dart: comments between a member chain's parts skipped * by every sibling step; TortureAnnotatedDocs.dart: the dartdoc above a - * member's annotations, read past them, and what still ends the walk) and - * their CRLF variants (derived in-memory — #1329), plus defer and - * generated-file pins. + * member's annotations, read past them, and what still ends the walk; + * TortureAnnotatedComments.dart: the comments between annotations and their + * declaration, stepped over by the decorator scan) and their CRLF variants + * (derived in-memory — #1329), plus defer and generated-file pins. * * The full-repo sweeps live in scripts/kernel-parity.mjs (shelf/bloc/flutter * with --max-deferral 0.3); this suite keeps the invariant alive in @@ -153,6 +154,11 @@ describe.skipIf(!kernelBuilt)('kernel Dart extraction parity', () => { // import or the previous member's body still ends the walk. Class-like // declarations open with their annotations. ['TortureAnnotatedDocs.dart', 40], + // Comments of every form between annotations and the declaration they + // belong to — stacked, on the annotation's line, before members with no + // body — are stepped over by the decorator scan; a field, a variable, an + // import or the previous member's body still ends it. + ['TortureAnnotatedComments.dart', 30], ] as const; for (const [file, minNodes] of FIXTURES) { diff --git a/codegraph-kernel/src/dart.rs b/codegraph-kernel/src/dart.rs index 98a83fa7c1..4fdfcdee94 100644 --- a/codegraph-kernel/src/dart.rs +++ b/codegraph-kernel/src/dart.rs @@ -51,6 +51,12 @@ const MAX_VALUE_REF_NODES: usize = 20_000; /// `Widget build(…)`), so the docstring walk steps over them. const DOCSTRING_STEP_OVER: &[&str] = &["annotation"]; +/// decoratorStepOverTypes (dart.ts) — an annotation belongs to the next +/// declaration, whatever comments come between them (`@override` +/// `// ignore: must_call_super` `void f()`), so the decorator scan steps over +/// them. +const DECORATOR_STEP_OVER: &[&str] = &["comment", "documentation_comment"]; + /// NAME_STOPLIST (function-ref.ts). fn is_stoplisted(name: &str) -> bool { matches!( @@ -1457,7 +1463,8 @@ impl<'t> Walker<'t> { } // Scan 2: preceding siblings, backward, stop at the first // non-annotation — stacked annotations emit in REVERSE source order. - // A `declaration`-wrapped member's annotations precede the wrapper. + // A `declaration`-wrapped member's annotations precede the wrapper, + // and the comments between annotations and declaration are stepped over. let anchor = self.declaration_wrapper(decl).unwrap_or(decl); if let Some(parent) = anchor.parent() { let decl_start = anchor.start_byte(); @@ -1473,6 +1480,9 @@ impl<'t> Walker<'t> { if let Some(di) = decl_idx { for j in (0..di).rev() { let Some(sib) = parent.named_child(j) else { continue }; + if DECORATOR_STEP_OVER.contains(&sib.kind()) { + continue; + } if !matches!(sib.kind(), "decorator" | "annotation" | "marker_annotation") { break; } diff --git a/docs/design/dart-kernel-port-checklist.md b/docs/design/dart-kernel-port-checklist.md index ac165a0b82..8943485fe0 100644 --- a/docs/design/dart-kernel-port-checklist.md +++ b/docs/design/dart-kernel-port-checklist.md @@ -871,12 +871,16 @@ enum emits nothing). Mechanics for dart: decorates `immutable`). Enums and typedefs are built the same way, but nothing scans them. - Scan #2 (preceding siblings :5002-5023): walk BACKWARD from the - declaration; `annotation` is in the accepted set (:5017); stop at the - first non-annotation sibling. consider(): target = first namedChild of - accepted types → the `identifier` (`override`, `deprecated`, `pragma`, - `immutable`, `Deprecated`) → `<`-strip + last-`.`-segment (`@ui.Widget` - style would strip to `Widget`) → **`decorates` ref {from the decorated - node, name, line/col of the ANNOTATION node}**. With-args annotations + declaration; `annotation` is in the accepted set (:5017); step over + `comment` / `documentation_comment` siblings (since 2026-10-06, below); + stop at the first other non-annotation sibling. consider(): target = + first namedChild of accepted types → the `identifier` (`override`, + `deprecated`, `pragma`, `immutable`, `Deprecated`) or `scoped_identifier` + (`meta.immutable`, `Foo.named`, `p.Foo.named`) → `<`-strip + last-`.`-segment + (`@meta.immutable` → `immutable`, `@p.Foo.named(…)` → `named`; the strip + runs first, so `@Foo.named(…)`, which parses with an ERROR inside the + name, → `Foo`) → **`decorates` ref {from the decorated node, name, + line/col of the ANNOTATION node, i.e. its `@`}**. With-args annotations emit their NAME; the argument expressions are never visited (no refs from `@Deprecated('use other')`'s string). - **Stacked annotations emit in REVERSE source order** (the backward walk): @@ -885,22 +889,34 @@ enum emits nothing). Mechanics for dart: - For a method: the previous member's function_body (or any declaration) breaks the chain correctly. (The docstring walk steps OVER annotations since 2026-10-06 — §Docstrings.) -- **A comment between an annotation and the declaration ends the scan**, so - the annotation above it attaches to nothing: `@override` `// ignore: - must_call_super` `void f()`, `@x` `/// Doc below.` `void f()` (pinned in - TortureAnnotatedDocs.dart). Measured 2026-10-06: bloc @b9be1e2 hides 7 - annotations this way (all `@override`), riverpod @4ba1be2 55 on 49 - declarations (`@override` 33, `@riverpod` 16 in the lint fixtures, - `@internal` 6). Left as is ON PURPOSE: stepping over comments here is - right for Dart (an annotation always belongs to the next declaration), but - Dart nodes store no decorator list, so the only effect would be edges, and - `override`/`internal` resolve to nothing, while `decorates` scoring prefers - function/method candidates (name-matcher.ts), so `@riverpod` lands on the - analyzer getter `RiverpodAnnotatedAnnotatedNodeOfX::riverpod` (0.4) - instead of `const riverpod = Riverpod()`. That is already true of - riverpod's 506 existing `@riverpod` edges. Fix that ranking for Dart (a - const or a class, never a method) first, then add `comment` / - `documentation_comment` to scan #2's step-over in both arms. +- **Comments between the annotations and the declaration are stepped over** + (since 2026-10-06). An annotation always belongs to the next declaration, + so dart.ts sets `decoratorStepOverTypes: ['comment', + 'documentation_comment']`, which scan #2 skips, and the kernel's + `extract_decorators_for` skips the same `DECORATOR_STEP_OVER` list. No + other language sets one. Until then the comment ended the scan and the + annotation above it attached to nothing. Now these all attach: `@override` + `// ignore: must_call_super` `void f()`, `@x` `/// Doc below.` `void f()`, + `@x /* c */ void f()`, a comment on the annotation's own line, and comments + between stacked annotations (still in reverse order). Pinned in + TortureAnnotatedComments.dart and dart-annotation-comments.test.ts. + - Still ends the scan, comments or not: a field's `declaration`, a + top-level variable, an import, the previous member's body (`void a() {} + // note` `@x void b()` gives `b` only `x`), a class-like declaration. + - Class-likes are unaffected. Their leading annotations are scan #1's, + which reads every child, comments among them included. + - Validation (bloc @b9be1e2 / riverpod @4ba1be2, kernel loaded, on top of + the annotation resolution below): `decorates` refs +7 / +54, edges +0 / + +16, nothing else in the dumps changed. bloc's 7 are all `@override`. + riverpod's 54 (on 48 declarations) are `@override` 32, `@internal` 6 and + `@riverpod` 16 (lint fixtures and one website snippet), and each + `@riverpod` links `const riverpod`. Kernel and wasm full-index dumps are + byte-identical, and the parity sweeps show 0 diffs. + - The AST scan's 55th riverpod site is `@override` `// ignore: …` on a + FIELD, which no extractor records. A scan that also counts annotation → + comment runs INSIDE class-like nodes finds riverpod's 24 `@riverpod` + `// ignore: …` `class X` lint fixtures and bloc's `@JsonEnum(…)` `/// …` + `enum`. Scan #1 already reads those (an enum's, never: see above). - Members with no body (declaration-wrapped ctors, const ctors, redirecting factories, abstract and `external` members): the signature's PARENT is the `declaration`, so until 2026-10-06 the backward scan ran over the @@ -914,6 +930,41 @@ enum emits nothing). Mechanics for dart: refs, all SDK or package:meta names (`useResult`, `override`, `internal`, `visibleForTesting`, …), so no edges; before #2380, riverpod's 23 new `@internal` refs on `X.internal(…)` ctors resolved to the ctor itself. +- **Resolution is TS-side and Dart-specific** (since 2026-10-06): + resolveOneInner hands every Dart `decorates` ref to name-matcher.ts's + `matchDartAnnotation` before any other strategy, and nothing falls + through. A Dart annotation is a const variable or a const constructor + call, never a method, getter or function, so the shared decorator ranking + (findBestMatch: +25 function/method, +15 class, nothing for a constant) + never sees one. That ranking sent riverpod's 506 `@riverpod` to the + analyzer's extension getter `RiverpodAnnotatedAnnotatedNodeOfX::riverpod` + (0.4) instead of `const riverpod = Riverpod();`. + - The matcher re-reads the written form from the `@` in comment-blanked + source. It is a call only when `(` follows on the same line, so a record + return type on the next line is not taken for arguments. + - `@x`: on a member, the enclosing type's own static `constant` / + `enum_member` `x` (a class-like's own annotations stand outside its + body); else a top-level `constant` the library can see (#2386's model, + the own library shadowing imports). `@X(…)`: a visible class `X`, not + an extension. + - `@p.x` / `@p.X(…)`, when `p` is an import prefix (dart-libraries.ts + `isDartImportPrefix`, the imports of the file's whole library): the same + through that prefix. Otherwise `@T.x` → T's own `constant` / + `enum_member` `x`, and `@T.named(…)` → T's named constructor (#2380's + `isDartConstructor`); `@p.T.x` / `@p.T.named(…)` likewise through `p`. + - A sole candidate links at 0.9 (`exact-match`, or `qualified-name` + through a type). Several (only where the library model can't establish + the library) fall back to findBestMatch's proximity at 0.7 / 0.4. + - Not modelled: a `final` is not told apart from a `const` (compiling code + never annotates with a visible `final`), nor a typedef used to call a + constructor. + - Validation (main 99246848, kernel loaded): bloc 0 edges changed (no + annotation there names a project declaration); riverpod exactly the 506 + `@riverpod` edges retargeted to `const riverpod` at 0.9, every other + `decorates` edge (`$internal`, `Riverpod`, `Dependencies`, …) identical, + nodes, refs and files identical. Every extracted annotation in both + repos is written with one name, so the prefixed and `T.x` forms are + pinned by dart-annotation-targets.test.ts only. ### Docstrings (tree-sitter-helpers.ts:95-127) — dartdoc is KEPT, both forms diff --git a/src/extraction/languages/dart.ts b/src/extraction/languages/dart.ts index 0997821c57..f5b7b8a258 100644 --- a/src/extraction/languages/dart.ts +++ b/src/extraction/languages/dart.ts @@ -539,6 +539,10 @@ export const dartExtractor: LanguageExtractor = { // this: its annotations open its own node, and the dartdoc above them is // that node's previous sibling. docstringStepOverTypes: ['annotation'], + // An annotation belongs to the next declaration, whatever comments come + // between them: `@override` `// ignore: must_call_super` `void f()`, or a + // dartdoc written below the annotations. The decorator scan steps over them. + decoratorStepOverTypes: ['comment', 'documentation_comment'], resolveBody: (node, bodyField) => { // Dart: function_body is a next sibling of function_signature/method_signature if (node.type === 'function_signature' || node.type === 'method_signature') { diff --git a/src/extraction/tree-sitter-types.ts b/src/extraction/tree-sitter-types.ts index 5dfafd2053..bb7c26f783 100644 --- a/src/extraction/tree-sitter-types.ts +++ b/src/extraction/tree-sitter-types.ts @@ -181,6 +181,13 @@ export interface LanguageExtractor { * each one is stepped over, and comments on either side of it still join. */ docstringStepOverTypes?: string[]; + /** + * Node types that may stand between a declaration and the decorators written + * before it without ending the scan for them. Dart writes comments there + * (`@override` `// ignore: must_call_super` `void f()`), and an annotation + * always belongs to the declaration that follows it. + */ + decoratorStepOverTypes?: string[]; /** Extract visibility from node */ getVisibility?: (node: SyntaxNode) => 'public' | 'private' | 'protected' | 'internal' | undefined; /** Check if node is exported */ diff --git a/src/extraction/tree-sitter.ts b/src/extraction/tree-sitter.ts index c3bd6fd98a..29debc3a1e 100644 --- a/src/extraction/tree-sitter.ts +++ b/src/extraction/tree-sitter.ts @@ -6213,8 +6213,10 @@ export class TreeSitterExtractor { // // A grammar that wraps the declaration (Dart's `declaration` // around a member with no body) puts the annotations before the - // wrapper, so the scan starts there. + // wrapper, so the scan starts there. One that lets comments sit + // between the annotations and the declaration (Dart) steps over them. const anchor = this.extractor?.getDeclarationWrapper?.(declNode) ?? declNode; + const stepOver = this.extractor?.decoratorStepOverTypes; const parent = anchor.parent; if (parent) { const declStart = anchor.startIndex; @@ -6230,6 +6232,7 @@ export class TreeSitterExtractor { for (let j = declIdx - 1; j >= 0; j--) { const sibling = parent.namedChild(j); if (!sibling) continue; + if (stepOver?.includes(sibling.type)) continue; if (sibling.type !== 'decorator' && sibling.type !== 'annotation' && sibling.type !== 'marker_annotation') { break; // non-decorator separator → stop consuming } diff --git a/src/resolution/dart-libraries.ts b/src/resolution/dart-libraries.ts index 270fe34090..8d9a0034f0 100644 --- a/src/resolution/dart-libraries.ts +++ b/src/resolution/dart-libraries.ts @@ -769,3 +769,14 @@ export function inSameDartLibrary(fromFile: string, declFile: string, context: R const scope = scopeOf(fromFile, context, memoFor(context)); return scope !== null && scope.own.has(declFile); } + +/** + * Whether `name` is an import prefix where `fromFile` is written: an import + * of its library is `as name` (`p` in `p.Foo`, not the `Foo` of `Foo.bar`). + * Where the library is unknown, the file's own imports say. + */ +export function isDartImportPrefix(fromFile: string, name: string, context: ResolutionContext): boolean { + const memo = memoFor(context); + const importers = scopeOf(fromFile, context, memo)?.importers ?? [fromFile]; + return importers.some((file) => (directivesOf(file, context, memo)?.imports ?? []).some((d) => d.prefix === name)); +} diff --git a/src/resolution/index.ts b/src/resolution/index.ts index f94cf0a16d..88451f6193 100644 --- a/src/resolution/index.ts +++ b/src/resolution/index.ts @@ -21,7 +21,7 @@ import { isImportableKind, CPP_DEFINE_SIGNATURE, } from './types'; -import { isPythonSelfCall, matchJsStoreBindingCall, isUnresolvedJsMemberCall, matchObjectPathCall, thisScopeCaller, isVisibleAcrossFiles, matchReference, matchFunctionRef, matchDottedCallChain, matchScopedCallChain, matchMethodCall, sameLanguageFamily, crossesCodeBoundary, gateLanguageMatch, dumpNameMatcherProfile, clearNameMatcherMemos, isRustNameInScope, CASE_INSENSITIVE_LANGUAGES, isDartMemberRead, matchDartMemberRead, isDartChainLink, matchDartChainLink, isStdMethodName } from './name-matcher'; +import { isPythonSelfCall, matchJsStoreBindingCall, isUnresolvedJsMemberCall, matchObjectPathCall, thisScopeCaller, isVisibleAcrossFiles, matchReference, matchFunctionRef, matchDottedCallChain, matchScopedCallChain, matchMethodCall, sameLanguageFamily, crossesCodeBoundary, gateLanguageMatch, dumpNameMatcherProfile, clearNameMatcherMemos, isRustNameInScope, CASE_INSENSITIVE_LANGUAGES, isDartMemberRead, matchDartMemberRead, isDartChainLink, matchDartChainLink, isDartAnnotation, matchDartAnnotation, isStdMethodName } from './name-matcher'; import { isVisibleCppMacro, clearCppMacroVisibility } from './cpp-macro-visibility'; import { isCppConstructorRef, matchCppConstructor } from './cpp-constructor'; import { gateSwiftTypeTarget, clearSwiftTypeVisibility, swiftExtendedConformances } from './swift-type-visibility'; @@ -1149,6 +1149,9 @@ export class ReferenceResolver { // `events.map(f).transform(…)`), which arrives by its bare name: a member // of what the chain's head and links are declared to be, or nothing (#750). if (isDartChainLink(ref, this.context)) return matchDartChainLink(ref, this.context); + // A Dart annotation (`@riverpod`, `@Riverpod(…)`) is a constant or a + // constructor call, as written — never a method or function by its name. + if (isDartAnnotation(ref)) return matchDartAnnotation(ref, this.context); // Skip built-in/external references if (this.isBuiltInOrExternal(ref)) { diff --git a/src/resolution/name-matcher.ts b/src/resolution/name-matcher.ts index 4b382c0a3f..4ded3cfcee 100644 --- a/src/resolution/name-matcher.ts +++ b/src/resolution/name-matcher.ts @@ -11,7 +11,7 @@ import { UnresolvedRef, ResolvedRef, ResolutionContext, ImportMapping, isSuperty import { blankStringContents, stripCommentsForRegex } from './strip-comments'; import { JS_BUILT_INS, JS_BUILTIN_METHODS, TS_PRIMITIVE_TYPES } from './js-builtins'; import { SWIFT_TYPE_PATH_CALL, resolveSwiftTypePathCall } from './swift-type-visibility'; -import { dartLibrarySees, dartPrefixSees, inSameDartLibrary } from './dart-libraries'; +import { dartLibrarySees, dartPrefixSees, inSameDartLibrary, isDartImportPrefix } from './dart-libraries'; import { breakVbTie, isVbMemberInScope, isVbNestedTypeInScope, isVbTypeQualifiedBy, matchVbTypedCall, preferVbProject, sameVbProject } from './vbnet-receivers'; import { isTestPath } from '../search/query-utils'; import { isMinifiedContent } from '../extraction/generated-detection'; @@ -4049,6 +4049,130 @@ export function matchDartMemberRead(ref: UnresolvedRef, context: ResolutionConte return { original: ref, targetNodeId: found.node.id, confidence: 0.9, resolvedBy: 'instance-method', edgeKind: 'calls' }; } +/** + * Whether a ref is a Dart annotation — `@riverpod`, `@Riverpod(keepAlive: + * true)`, `@meta.immutable` — which the extractor records by its last name, at + * the `@`. + */ +export function isDartAnnotation(ref: UnresolvedRef): boolean { + return ref.language === 'dart' && ref.referenceKind === 'decorates'; +} + +/** + * A Dart annotation is a constant expression: a `const` variable, or a call of + * a `const` constructor. So it links, as it is written, a constant or (called) + * a class its library can see, through the import prefix it is written with; + * a static constant, an enum value or (called) a named constructor of the + * type it is written through (`@Foo.value`, `@Foo.named(…)`); or, on a + * member, a static constant of the type around it. Never a method, a + * getter or a function: riverpod's 506 `@riverpod` annotations went to + * riverpod_analyzer_utils' extension getter `riverpod`, not riverpod_annotation's + * `const riverpod = Riverpod();`. + */ +export function matchDartAnnotation(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null { + const name = ref.referenceName; + if (!context.getNodesByName(name).some((n) => n.language === 'dart')) return null; + const written = dartAnnotationAt(ref, context); + if (!written) return null; + const { names, call } = written; + let pool: Node[]; + let resolvedBy: ResolvedRef['resolvedBy'] = 'exact-match'; + if (names.length === 1 || (names.length === 2 && isDartImportPrefix(ref.filePath, names[0]!, context))) { + const prefix = names.length === 2 ? names[0]! : null; + const own = prefix === null && !call ? dartEnclosingStatic(name, ref, context) : null; + if (own) return { original: ref, targetNodeId: own.id, confidence: 0.9, resolvedBy }; + pool = context.getNodesByName(name).filter((n) => isDartLibraryDecl(n) && + (call ? isDartAnnotationClass(n, context) : n.kind === 'constant') && isDartTopLevelVisible(n, ref, context, prefix)); + if (prefix === null) pool = preferOwnDartLibrary(pool, ref, context); + } else if (names.length === 2 || (names.length === 3 && isDartImportPrefix(ref.filePath, names[0]!, context))) { + const prefix = names.length === 3 ? names[0]! : null; + let owners = context.getNodesByName(names[names.length - 2]!).filter((n) => + isDartLibraryDecl(n) && DART_TYPE_KINDS.has(n.kind) && isDartTopLevelVisible(n, ref, context, prefix)); + if (prefix === null) owners = preferOwnDartLibrary(owners, ref, context); + pool = context.getNodesByName(name).filter((m) => m.language === 'dart' && + owners.some((o) => o.filePath === m.filePath && m.qualifiedName === `${o.qualifiedName}::${name}`) && + (call ? isDartConstructor(m, context) : m.kind === 'constant' || m.kind === 'enum_member')); + resolvedBy = 'qualified-name'; + } else { + return null; + } + if (pool.length <= 1) return pool[0] ? { original: ref, targetNodeId: pool[0].id, confidence: 0.9, resolvedBy } : null; + // Libraries this cannot establish see every file's declarations. + const best = findBestMatch(ref, pool, context); + return best + ? { original: ref, targetNodeId: best.id, confidence: computePathProximity(ref.filePath, best.filePath) >= 30 ? 0.7 : 0.4, resolvedBy } + : null; +} + +/** A class a Dart annotation can call a constructor of: not an extension, which has none. */ +function isDartAnnotationClass(n: Node, context: ResolutionContext): boolean { + return n.kind === 'class' && dartExtensionDecl(n, context) === null; +} + +/** + * The static constant or enum value `name` of the type a Dart annotation is + * written in, which a member's annotation names bare. A class's own + * annotations stand outside its body. + */ +function dartEnclosingStatic(name: string, ref: UnresolvedRef, context: ResolutionContext): Node | null { + let own: Node | null = null; + for (const n of context.getNodesInFile(ref.filePath)) { + if (DART_TYPE_KINDS.has(n.kind) && n.id !== ref.fromNodeId && n.startLine <= ref.line && n.endLine >= ref.line && + (!own || n.startLine >= own.startLine)) own = n; + } + if (!own) return null; + const qualifiedName = `${own.qualifiedName}::${name}`; + return context.getNodesByName(name).find((m) => m.language === 'dart' && m.filePath === ref.filePath && + m.qualifiedName === qualifiedName && (m.kind === 'constant' || m.kind === 'enum_member')) ?? null; +} + +/** + * How a Dart annotation is written — the names of `@p.Foo.named(…)` up to the + * one its ref records, and whether it is called — read from its `@`. The + * extractor records the last name, or the one a type argument list follows + * (`@Foo.named(…)` is `Foo`'s). + */ +function dartAnnotationAt(ref: UnresolvedRef, context: ResolutionContext): { names: string[]; call: boolean } | null { + const code = dartCodeOf(ref.filePath, context); + const from = code?.lineStarts[ref.line - 1]; + if (!code || from === undefined) return null; + const to = code.lineStarts[ref.line] ?? code.text.length; + // On a line with non-ASCII text before it, the `@` whose names fit stands in. + const ats = [from + ref.column]; + for (let k = code.text.indexOf('@', from); k >= 0 && k < to; k = code.text.indexOf('@', k + 1)) { + if (k !== from + ref.column) ats.push(k); + } + for (const at of ats) { + const read = code.text[at] === '@' ? readDartAnnotation(code.text, at + 1) : null; + const end = read ? (read.typeArgsAt >= 0 ? read.typeArgsAt : read.names.length - 1) : -1; + if (read && read.names[end] === ref.referenceName) return { names: read.names.slice(0, end + 1), call: read.call }; + } + return null; +} + +/** A Dart annotation's dotted names, which of them a type argument list follows, and whether `(` comes next on its line. */ +function readDartAnnotation(text: string, i: number): { names: string[]; typeArgsAt: number; call: boolean } | null { + const names: string[] = []; + let typeArgsAt = -1; + const identifier = /[ \t]*([A-Za-z_$][\w$]*)[ \t]*/y; + while (names.length < 8) { + identifier.lastIndex = i; + const m = identifier.exec(text); + if (!m) return null; + names.push(m[1]!); + i = identifier.lastIndex; + if (text[i] === '<' && typeArgsAt < 0) { + const close = dartTypeArgumentsEnd(text, i); + if (close < 0) return null; + typeArgsAt = names.length - 1; + for (i = close + 1; text[i] === ' ' || text[i] === '\t'; i++); + } + if (text[i] !== '.') break; + i++; + } + return { names, typeArgsAt, call: text[i] === '(' }; +} + /** * A member an extension adds to `typeName` — `s.shout()` on an enum `Shape` * through `extension ShapeInfo on Shape` — when the type itself declares none @@ -11530,7 +11654,8 @@ function findBestMatch( // For decorator references (`@Foo`), prefer functions. Class // decorators (Python `@SomeClass`, Java annotation interfaces) - // also resolve here, hence the smaller class bonus. + // also resolve here, hence the smaller class bonus. (A Dart annotation, + // a constant or a constructor call, is matchDartAnnotation's.) if (ref.referenceKind === 'decorates') { if (candidate.kind === 'function' || candidate.kind === 'method') { score += 25; From 837a1866f1fda8d911cc46af133afc7cdcee1dde Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 18:17:12 +0000 Subject: [PATCH 18/23] fix(dart): a call through an import prefix reaches only what that import exports (#2389) A Dart call written through an import prefix - `http.get(uri)` after `import 'package:http/http.dart' as http;` - was resolved like a method call on a receiver named `http`, so it linked to any project member that fit the name: riverpod's docs' `http.get(...)` / `http.post(...)` calls went to a docs example's `Http::get` / `Http::post` by the receiver's capitalized name, and `fmt.describe(...)` to a class's `describe` method. Now `p.name(...)` calls a top-level declaration a library imported with that prefix exports (export chains, show / hide and parts followed through the library model), or nothing when the prefixed library is a package outside the repository. A constructor call (`p.Widget()`) instantiates the prefixed library's class. The same holds where the prefix heads a chain - `p.Box.create()`, `p.Report.empty()` - and for `p.Box.named(...)`, which arrives as `Box.named`: the type is the one the prefix brings in. A parameter, local or member named like the prefix still hides it, and `const p.Box.named()`, which the extractors record as `p.named`, links nothing. The library model's one prefix reader is `dartImportPrefixes`: Dart annotations (#2390's `matchDartAnnotation`) read prefixes through it too, in place of the `isDartImportPrefix` it had alongside. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/dart-import-prefix-calls.test.ts | 200 +++++++++++++++++++++ docs/design/dart-kernel-port-checklist.md | 2 +- src/resolution/dart-libraries.ts | 35 ++-- src/resolution/dart-local-scope.ts | 10 ++ src/resolution/name-matcher.ts | 196 ++++++++++++++++---- 6 files changed, 401 insertions(+), 43 deletions(-) create mode 100644 __tests__/dart-import-prefix-calls.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index e088fa7a79..d87506bdf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In Dart, an `import` or `export` now links to the file it names: `package:my_app/src/cart.dart` to that package's `lib/src/cart.dart`, and a relative path to the file it points to from the importing file. Before, only the file name at the end was matched, so `import 'package:flutter/widgets.dart'` linked to whichever project file was called `widgets.dart`, and most imports of your own files didn't link to the file at all, which threw off `codegraph affected` and the files listed as using a file. An import of a Dart SDK library or of a package from outside your project now links nothing, and when packages in one repository share a name, the one the importing app depends on by `path:` is used. Re-index Dart projects after upgrading. - In Dart, an annotation now links to the constant or constructor it names, read the way it is written: `@riverpod` reaches Riverpod's `const riverpod = Riverpod();`, `@Riverpod(keepAlive: true)` the `Riverpod` class, an annotation written through a class, like `@SomeClass.value` or `@SomeClass.named(…)`, that class's own constant, enum value or constructor, and `@meta.immutable` only what the `meta` import brings in. Before, an annotation was matched like a function decorator, so a method, getter or function that only shared its name won: every `@riverpod` provider in Riverpod's own repository was linked to an unrelated getter called `riverpod`, and `callers` and impact for the real annotation missed them. Re-index Dart projects after upgrading. - In Dart, an annotation is no longer lost when a comment sits between it and the declaration, like `@override` followed by `// ignore: must_call_super`, a `///` comment written below the annotations, or `@riverpod` followed by an `// expect_lint: …` line. Before, the comment hid the annotation, so a provider written that way was missing from the annotation's `callers` and impact. Re-index Dart projects after upgrading. +- In Dart, a call written through an import prefix, like `http.get(…)` after `import 'package:http/http.dart' as http;`, or `utils.Listener()` and `kit.Box.create()` through a prefix of your own, now links to what the library imported with that prefix exports, following its `export` chains, `show` and `hide`, and to nothing when that library is a package outside your project. Before, the prefix was taken for a variable, so `http.get(…)` could link to an unrelated `Http` class's `get` method, and calls made through a prefix into your own libraries were missing from `callers` and impact. Re-index Dart projects after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/dart-import-prefix-calls.test.ts b/__tests__/dart-import-prefix-calls.test.ts new file mode 100644 index 0000000000..8c3b7cdb9f --- /dev/null +++ b/__tests__/dart-import-prefix-calls.test.ts @@ -0,0 +1,200 @@ +/** + * A Dart call written through an import prefix — `http.get(uri)` after + * `import 'package:http/http.dart' as http;` — calls a top-level declaration + * the libraries imported with that prefix export, or nothing in the project. + * It is no method call on a receiver named `http`: riverpod's docs' 25 + * `http.get(…)` / `http.post(…)` calls went to a docs example's `Http` class. + * + * Runs against the native kernel (when built) and the wasm extractor. + */ +import { describe, it, expect, afterAll, beforeAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; + +const FILES: Record = { + 'pubspec.yaml': 'name: app\n', + // Namesakes of everything the prefixes below name, in a library beside the + // callers — nearer than the libraries the prefixes import. + 'lib/legacy.dart': `class Http { + Future get(Uri url) async => ''; +} + +class Client { + Client(); + static Client fromEnv() => Client(); +} + +class Formatter { + String describe(Object value) => ''; +} + +class Loader { + int load() => 0; +} + +class Report { + Report.empty(); + static Report blank() => Report.empty(); +} + +class Box { + const Box.named(); + static Box create() => const Box.named(); +} + +String describe(Object value) => 'legacy'; +int shown() => 0; +`, + 'lib/src/format.dart': `String describe(Object value) => '$value'; + +class Report { + Report(); + Report.empty(); + static Report blank() => Report(); +} +`, + 'lib/src/tools.dart': `int secret() => 1; +int open() => 2; +`, + 'lib/lazy.dart': `int load() => 1; +`, + 'packages/kit/pubspec.yaml': 'name: kit\n', + 'packages/kit/lib/kit.dart': `export 'src/impl.dart' show shown, Widget, Box, named; +`, + 'packages/kit/lib/src/impl.dart': `int shown() => 1; +int notShown() => 2; +int named() => 3; + +class Widget { + Widget(); +} + +class Box { + const Box.named(); + static Box create() => const Box.named(); +} +`, + // package:http is not in the repository. + 'lib/net.dart': `import 'package:http/http.dart' as http; + +Future fetch() async { + await http.get(Uri.parse('https://example.com')); + http.Client(); + http.Client.fromEnv(); +} +`, + 'lib/app.dart': `import 'package:kit/kit.dart' as kit; +import 'src/format.dart' as fmt; +import 'src/tools.dart' as tools hide secret; +import 'lazy.dart' deferred as lazy; + +part 'app_part.dart'; + +String run(Object value) { + fmt.Report(); + fmt.Report.empty(); + fmt.Report.blank(); + kit.shown(); + kit.notShown(); + kit.Widget(); + tools.open(); + tools.secret(); + final box = kit.Box.named(); + kit.Box.create(); + const kit.Box.named(); + return fmt.describe(value); +} + +Future boot() async { + await lazy.loadLibrary(); + return lazy.load(); +} +`, + 'lib/app_part.dart': `part of 'app.dart'; + +String again(Object value) => fmt.describe(value); +`, + // A parameter named like the prefix is the parameter, there. + 'lib/shadow.dart': `import 'package:http/http.dart' as http; +import 'legacy.dart'; + +Future viaParameter(Http http) => http.get(Uri()); +`, +}; + +/** ` -> :` for every call out of `file`. */ +function callsFrom(cg: CodeGraph, file: string): string[] { + const ids = cg.getNodesInFile(file).map((n) => n.id); + return cg.getOutgoingEdgesFrom(ids) + .filter((e) => e.kind === 'calls' || e.kind === 'instantiates') + .map((e) => { + const t = cg.getNode(e.target)!; + return `${e.kind} ${e.line} ${String(e.metadata?.refName ?? '')} -> ${t.filePath}:${t.qualifiedName}`; + }); +} + +describe.each(['default', 'wasm'])('Dart calls through an import prefix (%s)', (backend) => { + let root = ''; + let cg: CodeGraph | undefined; + let kernel: string | undefined; + const calls = (file: string): string[] => callsFrom(cg!, file); + + beforeAll(async () => { + kernel = process.env.CODEGRAPH_KERNEL; + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-prefix-')); + for (const [rel, content] of Object.entries(FILES)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + cg = await CodeGraph.init(root, { index: true }); + }); + + afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; + }); + + it('links nothing for a call into a package outside the repository', () => { + expect(calls('lib/net.dart')).toEqual([]); + }); + + it("links a call to the prefixed library's function, not a namesake or a method", () => { + expect(calls('lib/app.dart')).toContain('calls 20 fmt.describe -> lib/src/format.dart:describe'); + expect(calls('lib/app.dart')).toContain('calls 25 lazy.load -> lib/lazy.dart:load'); + expect(calls('lib/app_part.dart')).toEqual(['calls 3 fmt.describe -> lib/src/format.dart:describe']); + }); + + it('follows the export chain, show and hide of the prefixed import', () => { + const edges = calls('lib/app.dart'); + expect(edges).toContain('calls 12 kit.shown -> packages/kit/lib/src/impl.dart:shown'); + expect(edges).toContain('instantiates 14 kit.Widget -> packages/kit/lib/src/impl.dart:Widget'); + expect(edges).toContain('calls 15 tools.open -> lib/src/tools.dart:open'); + // Not shown by kit.dart, hidden from `tools`, the deferred library's own `loadLibrary`. + expect(edges.filter((e) => / (?:kit\.notShown|tools\.secret|lazy\.loadLibrary) /.test(e))).toEqual([]); + }); + + it("constructs and calls through the prefixed library's type", () => { + const edges = calls('lib/app.dart'); + expect(edges).toContain('instantiates 9 fmt.Report -> lib/src/format.dart:Report'); + expect(edges).toContain('calls 10 empty -> lib/src/format.dart:Report::empty'); + expect(edges).toContain('calls 11 blank -> lib/src/format.dart:Report::blank'); + expect(edges).toContain('calls 17 Box.named -> packages/kit/lib/src/impl.dart:Box::named'); + expect(edges).toContain('calls 18 create -> packages/kit/lib/src/impl.dart:Box::create'); + }); + + it('never lands a prefixed call on another library', () => { + expect(calls('lib/app.dart').filter((e) => e.includes('lib/legacy.dart'))).toEqual([]); + // `const kit.Box.named()` is no call of kit's top-level `named`. + expect(calls('lib/app.dart').filter((e) => e.startsWith('calls 19 '))).toEqual([]); + }); + + it('leaves a name a parameter shadows to the parameter', () => { + expect(calls('lib/shadow.dart')).toEqual(['calls 4 http.get -> lib/legacy.dart:Http::get']); + }); +}); diff --git a/docs/design/dart-kernel-port-checklist.md b/docs/design/dart-kernel-port-checklist.md index 8943485fe0..4e1b2e8f16 100644 --- a/docs/design/dart-kernel-port-checklist.md +++ b/docs/design/dart-kernel-port-checklist.md @@ -948,7 +948,7 @@ enum emits nothing). Mechanics for dart: the own library shadowing imports). `@X(…)`: a visible class `X`, not an extension. - `@p.x` / `@p.X(…)`, when `p` is an import prefix (dart-libraries.ts - `isDartImportPrefix`, the imports of the file's whole library): the same + `dartImportPrefixes`, the imports of the file's whole library): the same through that prefix. Otherwise `@T.x` → T's own `constant` / `enum_member` `x`, and `@T.named(…)` → T's named constructor (#2380's `isDartConstructor`); `@p.T.x` / `@p.T.named(…)` likewise through `p`. diff --git a/src/resolution/dart-libraries.ts b/src/resolution/dart-libraries.ts index 8d9a0034f0..61b328fb65 100644 --- a/src/resolution/dart-libraries.ts +++ b/src/resolution/dart-libraries.ts @@ -368,6 +368,7 @@ interface Memo { members: Map>; exports: Map>; scopes: Map; + prefixes: Map>; } const memos = new WeakMap(); @@ -386,6 +387,7 @@ function memoFor(context: ResolutionContext): Memo { members: new Map(), exports: new Map(), scopes: new Map(), + prefixes: new Map(), }; memos.set(context, memo); } @@ -763,20 +765,31 @@ export function dartPrefixSees(fromFile: string, prefix: string, declFile: strin return filters === null || (!name.startsWith('_') && filters.some((f) => lets(f, name))); } +/** + * The import prefixes written in `fromFile` can stand for — the `p` of + * `import '…' as p` and `deferred as p` — read from the imports of its + * library, which a part (`part of …`) takes from the file it is part of. + */ +export function dartImportPrefixes(fromFile: string, context: ResolutionContext): ReadonlySet { + const memo = memoFor(context); + const hit = memo.prefixes.get(fromFile); + if (hit) return hit; + const prefixes = new Set(); + // Records each part's parent, a library in no package included. + libraryOf(fromFile, context, memo); + let file: string | undefined = fromFile; + for (let hops = 0; file !== undefined && hops < 32; file = memo.parentOf.get(file), hops++) { + for (const directive of directivesOf(file, context, memo)?.imports ?? []) { + if (directive.prefix !== null) prefixes.add(directive.prefix); + } + } + memo.prefixes.set(fromFile, prefixes); + return prefixes; +} + /** Whether `declFile` is a file of the library `fromFile` belongs to (false when that library is unknown). */ export function inSameDartLibrary(fromFile: string, declFile: string, context: ResolutionContext): boolean { if (fromFile === declFile) return true; const scope = scopeOf(fromFile, context, memoFor(context)); return scope !== null && scope.own.has(declFile); } - -/** - * Whether `name` is an import prefix where `fromFile` is written: an import - * of its library is `as name` (`p` in `p.Foo`, not the `Foo` of `Foo.bar`). - * Where the library is unknown, the file's own imports say. - */ -export function isDartImportPrefix(fromFile: string, name: string, context: ResolutionContext): boolean { - const memo = memoFor(context); - const importers = scopeOf(fromFile, context, memo)?.importers ?? [fromFile]; - return importers.some((file) => (directivesOf(file, context, memo)?.imports ?? []).some((d) => d.prefix === name)); -} diff --git a/src/resolution/dart-local-scope.ts b/src/resolution/dart-local-scope.ts index 8fdea685e6..f8d6d93d20 100644 --- a/src/resolution/dart-local-scope.ts +++ b/src/resolution/dart-local-scope.ts @@ -77,6 +77,16 @@ export function gateDartLocal(resolved: ResolvedRef | null, ref: UnresolvedRef, return !nearest || nearest.fn ? resolved : null; } +/** + * Whether a parameter, local or local function `name` is bound at offset `at` + * of the file's source — where it hides a library name, an import prefix + * among them: `http.get(…)` with a parameter `http` calls the parameter's. + */ +export function isDartLocallyBound(filePath: string, name: string, at: number, context: ResolutionContext): boolean { + const bound = fileScopes(filePath, context)?.names.get(name); + return bound !== undefined && bound.some((scope) => at >= scope.start && at <= scope.end); +} + /** * Where on its line a reference's name starts. A Dart ref's column sits just * past the name (a function value's at it); a column counted in bytes misses diff --git a/src/resolution/name-matcher.ts b/src/resolution/name-matcher.ts index 4ded3cfcee..d2f07797e7 100644 --- a/src/resolution/name-matcher.ts +++ b/src/resolution/name-matcher.ts @@ -11,7 +11,8 @@ import { UnresolvedRef, ResolvedRef, ResolutionContext, ImportMapping, isSuperty import { blankStringContents, stripCommentsForRegex } from './strip-comments'; import { JS_BUILT_INS, JS_BUILTIN_METHODS, TS_PRIMITIVE_TYPES } from './js-builtins'; import { SWIFT_TYPE_PATH_CALL, resolveSwiftTypePathCall } from './swift-type-visibility'; -import { dartLibrarySees, dartPrefixSees, inSameDartLibrary, isDartImportPrefix } from './dart-libraries'; +import { dartImportPrefixes, dartLibrarySees, dartPrefixSees, inSameDartLibrary } from './dart-libraries'; +import { isDartLocallyBound } from './dart-local-scope'; import { breakVbTie, isVbMemberInScope, isVbNestedTypeInScope, isVbTypeQualifiedBy, matchVbTypedCall, preferVbProject, sameVbProject } from './vbnet-receivers'; import { isTestPath } from '../search/query-utils'; import { isMinifiedContent } from '../extraction/generated-detection'; @@ -3035,6 +3036,85 @@ function preferOwnDartLibrary(candidates: Node[], ref: UnresolvedRef, context: R return own.length === 0 ? candidates : candidates.filter((n) => !isDartLibraryDecl(n) || own.includes(n)); } +/** + * A Dart call through an import prefix — `http.get(…)` after `import + * 'package:http/http.dart' as http;`, `fmt.describe(…)`, `kit.Widget()` — + * calls a top-level declaration a library imported with that prefix exports, + * `export` chains and `show` / `hide` followed, or nothing of the project: + * never a member found by its name. riverpod's docs' 25 `http.get(…)` calls + * went to a docs example's `Http::get`, by their receiver's capitalized name. + * Undefined when the receiver is no import prefix there, or a parameter, local + * or member of that name hides it. + */ +function matchDartPrefixedCall(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null | undefined { + const parts = DART_MEMBER_READ.exec(ref.referenceName); + if (!parts || !dartImportPrefixes(ref.filePath, context).has(parts[1]!)) return undefined; + const prefix = parts[1]!; + const name = parts[2]!; + const at = dartPrefixedCallSite(ref, prefix, name, context); + // `const p.Box.named()` reaches here as `p.named`: no call of a top-level `named`. + if (at < 0) return null; + if (isDartNameHidden(prefix, ref, at, context)) return undefined; + const found = dartPrefixedDecls(prefix, name, ref, context); + return found.length === 1 ? { original: ref, targetNodeId: found[0]!.id, confidence: 0.9, resolvedBy: 'import' } : null; +} + +/** The top-level Dart declarations named `name` that the imports written with `prefix` bring into the reference's library. */ +function dartPrefixedDecls(prefix: string, name: string, ref: UnresolvedRef, context: ResolutionContext): Node[] { + return context.getNodesByName(name).filter((n) => isDartLibraryDecl(n) && dartPrefixSees(ref.filePath, prefix, n.filePath, name, context)); +} + +/** + * Where `prefix` starts in the code of a Dart call written `prefix.name(…)`, + * or -1 when the call is written otherwise: `const p.Box.named()` arrives as + * `p.named`. (The reference's column sits just past `name`.) + */ +function dartPrefixedCallSite(ref: UnresolvedRef, prefix: string, name: string, context: ResolutionContext): number { + const code = dartCodeOf(ref.filePath, context); + const start = code ? dartNameStart({ ...ref, referenceName: name }, code) : -1; + if (!code || start < 0) return -1; + const text = code.text; + let k = start - 1; + while (k >= 0 && /\s/.test(text[k]!)) k--; + if (text[k] !== '.' || text[k - 1] === '.' || text[k - 1] === '?') return -1; + k--; + while (k >= 0 && /\s/.test(text[k]!)) k--; + const end = k + 1; + while (k >= 0 && /[\w$]/.test(text[k]!)) k--; + if (text.slice(k + 1, end) !== prefix) return -1; + while (k >= 0 && /\s/.test(text[k]!)) k--; + return text[k] === '.' ? -1 : end - prefix.length; +} + +/** + * Whether a parameter or local around offset `at`, or a member of the type the + * reference is written in, is named `name`: it hides a library-level name + * there — an import prefix among them — as Dart's scopes nest. + */ +function isDartNameHidden(name: string, ref: UnresolvedRef, at: number, context: ResolutionContext): boolean { + if (isDartLocallyBound(ref.filePath, name, at, context)) return true; + const own = dartEnclosingType(ref, context); + return own !== null && (classMemberType(own, name, context) !== null || + context.getNodesByName(name).some((n) => n.filePath === own.filePath && n.qualifiedName === `${own.qualifiedName}::${name}`)); +} + +/** + * The import prefix a Dart call through a type is written with — the `p` of + * `p.Box.named(…)`, which arrives as `Box.named` with its column on the + * prefix — or null. + */ +function dartTypeCallPrefix(typeName: string, member: string, ref: UnresolvedRef, context: ResolutionContext): string | null { + const prefixes = dartImportPrefixes(ref.filePath, context); + if (prefixes.size === 0) return null; + const line = context.getFileLines?.(ref.filePath)?.[ref.line - 1] ?? context.readFile(ref.filePath)?.split(/\r?\n/)[ref.line - 1]; + if (line === undefined) return null; + const written = new RegExp(String.raw`(?]|<(?:[^<>]|<[^<>]*>)*>)*>)?\s*\.\s*${member.replace(/\$/g, '\\$')}(?![\w$])`, 'g'); + // The one at the reference's column, else the first: a column counted in bytes misses after non-ASCII text. + const found = [...line.matchAll(written)].filter((m) => prefixes.has(m[1]!)); + return (found.find((m) => m.index === ref.column) ?? found[0])?.[1] ?? null; +} + /** * Whether a bare Dart reference really is receiver-less at its call site. The * extractor keeps one receiver level, so the later links of a chain — @@ -3096,7 +3176,7 @@ export function matchDartChainLink(ref: UnresolvedRef, context: ResolutionContex // Static members are the type's own: `p.Provider.autoDispose(…)` calls the // constant, as `Provider.autoDispose(…)` does. if (receiver.static) { - const member = dartStaticMember(receiver.type, ref.referenceName, ref, context); + const member = dartStaticMember(receiver.type, ref.referenceName, ref, context, dartOwnerOf(receiver)); return member && member.kind !== 'enum_member' ? { original: ref, targetNodeId: member.id, confidence: 0.85, resolvedBy: 'qualified-name' } : null; } @@ -3127,25 +3207,29 @@ interface DartChainLink { name: string; typeArgs: string[]; call: boolean; index /** * What a Dart chain starts from: a name (`x`, `Foo`, `foo(…)`, `Foo(…)`, - * with the keyword written before it — `const`, `new`, `as`, `await`), a - * string literal, or a parenthesized expression. + * with the keyword written before it — `const`, `new`, `as`, `await` — and + * where it starts), a string literal, or a parenthesized expression. */ type DartChainHead = - | { kind: 'name'; name: string; typeArgs: string[]; call: boolean; keyword: string } + | { kind: 'name'; name: string; typeArgs: string[]; call: boolean; keyword: string; at: number } | { kind: 'string' } | { kind: 'paren'; open: number; close: number }; interface DartChain { head: DartChainHead; links: DartChainLink[] } -/** What a Dart chain evaluates to: an instance of `type`, or (`static`) the type itself, before a static member. */ -interface DartValue { type: string; static: boolean; viaSuper?: boolean } +/** + * What a Dart chain evaluates to: an instance of `type`, or (`static`) the + * type itself, before a static member — of the type `owner` declares, when + * the chain says which file that is (`p.Box` names the one `p` brings in). + */ +interface DartValue { type: string; static: boolean; viaSuper?: boolean; owner?: string } /** * A Dart file's code with comments and string contents blanked, where each - * line starts, the import prefixes it declares, and the files of its library - * it names: its `part`s and the file it is `part of`. + * line starts, and the files of its library it names: its `part`s and the + * file it is `part of`. */ -interface DartCode { text: string; lineStarts: number[]; prefixes: Set; parts: string[]; partOf: string | null } +interface DartCode { text: string; lineStarts: number[]; parts: string[]; partOf: string | null } const DART_CODE = new WeakMap>(); @@ -3160,11 +3244,10 @@ function dartCodeOf(filePath: string, context: ResolutionContext): DartCode | nu const text = blankDartCode(source); const lineStarts = [0]; for (let i = 0; i < text.length; i++) if (text[i] === '\n') lineStarts.push(i + 1); - const prefixes = new Set([...text.matchAll(/^\s*import\s+['"][^'"]*['"]\s+(?:deferred\s+)?as\s+([A-Za-z_$][\w$]*)/gm)].map((m) => m[1]!)); const sibling = (uri: string): string => path.posix.normalize(path.posix.join(path.posix.dirname(filePath), uri)); const parts = [...source.matchAll(/^\s*part\s+['"]([^'"]+)['"]\s*;/gm)].map((m) => sibling(m[1]!)); const partOf = /^\s*part\s+of\s+['"]([^'"]+)['"]\s*;/m.exec(source)?.[1]; - code = { text, lineStarts, prefixes, parts, partOf: partOf ? sibling(partOf) : null }; + code = { text, lineStarts, parts, partOf: partOf ? sibling(partOf) : null }; } // Refs arrive file by file, so a few files' worth is enough. if (memo.size >= 64) memo.delete(memo.keys().next().value!); @@ -3350,7 +3433,7 @@ function readDartChain(text: string, end: number): DartChain | null { continue; } const keyword = /([A-Za-z_]\w*)$/.exec(text.slice(Math.max(0, j - 10), j + 1))?.[1] ?? ''; - return { head: { kind: 'name', name, typeArgs, call, keyword }, links: links.reverse() }; + return { head: { kind: 'name', name, typeArgs, call, keyword, at: i + 1 }, links: links.reverse() }; } return null; } @@ -3364,17 +3447,18 @@ function typeDartChain(chain: DartChain, ref: UnresolvedRef, context: Resolution if (head.kind === 'string') value = { type: 'String', static: false }; else if (head.kind === 'paren') value = typeDartParen(head, ref, context, depth); else { - let name = head; // `p.Provider.autoDispose`: an import prefix names a library, so the chain - // starts at the link after it. + // starts at the link after it, which names what that library exports. const first = links[0]; - if (!name.call && name.typeArgs.length === 0 && first && !first.index && dartCodeOf(ref.filePath, context)?.prefixes.has(name.name)) { - name = { kind: 'name', name: first.name, typeArgs: first.typeArgs, call: first.call, keyword: '' }; + if (!head.call && head.typeArgs.length === 0 && first && !first.index && dartImportPrefixes(ref.filePath, context).has(head.name) && + !isDartNameHidden(head.name, ref, head.at, context)) { + value = typeDartPrefixedHead(head.name, first, ref, context, depth); links = links.slice(1); + } else { + // `const Foo.named(…)`: the named constructor is the head's own link. + if ((head.keyword === 'const' || head.keyword === 'new') && !head.call && links[0]?.call) links = links.slice(1); + value = typeDartHead(head, ref, context, depth); } - // `const Foo.named(…)`: the named constructor is the head's own link. - if ((name.keyword === 'const' || name.keyword === 'new') && !name.call && links[0]?.call) links = links.slice(1); - value = typeDartHead(name, ref, context, depth); } for (const link of links) { // Every Dart object's `toString()` returns a String, whatever it is. @@ -3397,10 +3481,15 @@ function typeDartChain(chain: DartChain, ref: UnresolvedRef, context: Resolution /** Whether the type a Dart chain has reached declares the member a link names. */ function dartLinkDeclared(value: DartValue, link: DartChainLink, ref: UnresolvedRef, context: ResolutionContext): boolean { return value.static - ? dartStaticMember(value.type, link.name, ref, context) !== null + ? dartStaticMember(value.type, link.name, ref, context, dartOwnerOf(value)) !== null : dartMemberOf(value.type, link.name, ref, context, (n) => !isDartSetter(n, context), value.viaSuper ? 1 : 0) !== null; } +/** Which of the types named like a chain's value it is: the one its `owner` file declares, when the chain said. */ +function dartOwnerOf(value: DartValue): ((type: Node) => boolean) | undefined { + return value.owner === undefined ? undefined : (type) => type.filePath === value.owner; +} + /** `(x as Foo)` is a Foo; any other parenthesized expression is what its last operand is: `(a ?? Todo(…))`. */ function typeDartParen(head: { open: number; close: number }, ref: UnresolvedRef, context: ResolutionContext, depth: number): DartValue | null { const code = dartCodeOf(ref.filePath, context); @@ -3459,11 +3548,36 @@ function typeDartHead( return type ? { type, static: false } : null; } +/** + * What the first link after an import prefix evaluates to — `p.Provider` + * before a static member, `p.Report(…)`, `p.make(…)`, `p.config` — read from + * the top-level declarations the prefixed import brings in, and nothing when + * it brings in none of that name: a package outside the repository, whatever + * the project declares under the name elsewhere. + */ +function typeDartPrefixedHead(prefix: string, link: DartChainLink, ref: UnresolvedRef, context: ResolutionContext, depth: number): DartValue | null { + const found = dartPrefixedDecls(prefix, link.name, ref, context); + const types = found.filter((n) => DART_TYPE_KINDS.has(n.kind)); + if (types.length > 0) { + return { type: link.name, static: !link.call, owner: types.length === 1 ? types[0]!.filePath : undefined }; + } + if (found.length !== 1) return null; + const decl = found[0]!; + if (decl.kind === 'function') { + const type = link.call ? dartReturnType(decl, link.typeArgs, context) : null; + return type ? { type, static: false } : null; + } + if (decl.kind !== 'constant' && decl.kind !== 'variable') return null; + const held = dartConstantType(decl, ref, context, depth); + if (!held) return null; + return link.call ? dartCallResult(held, link.typeArgs, ref, context) : { type: held, static: false }; +} + /** What one link of a Dart chain makes of the value before it. */ function typeDartLink(value: DartValue, link: DartChainLink, ref: UnresolvedRef, context: ResolutionContext, depth: number): DartValue | null { if (link.index) return null; if (value.static) { - const member = dartStaticMember(value.type, link.name, ref, context); + const member = dartStaticMember(value.type, link.name, ref, context, dartOwnerOf(value)); if (!member) { // `BlocProvider.value(…)`, `AsyncValue.data(…)`: a constructor the index holds no node for. return link.call && context.getNodesByName(value.type).some((n) => n.language === 'dart' && DART_TYPE_KINDS.has(n.kind)) @@ -3548,10 +3662,17 @@ function dartEnclosingType(ref: UnresolvedRef, context: ResolutionContext): Node * The static member `name` the Dart type `typeName` itself declares — a * static method or getter, a named constructor or factory, a static * constant, an enum value — preferring the call site's file, then the - * nearest. Static members are not inherited. + * nearest. Static members are not inherited. `isOwner` narrows the types of + * that name to the one meant (the one an import prefix brings in). */ -function dartStaticMember(typeName: string, name: string, ref: UnresolvedRef, context: ResolutionContext): Node | null { - const owners = context.getNodesByName(typeName).filter((n) => n.language === 'dart' && DART_TYPE_KINDS.has(n.kind)); +function dartStaticMember( + typeName: string, + name: string, + ref: UnresolvedRef, + context: ResolutionContext, + isOwner: (type: Node) => boolean = () => true, +): Node | null { + const owners = context.getNodesByName(typeName).filter((n) => n.language === 'dart' && DART_TYPE_KINDS.has(n.kind) && isOwner(n)); if (owners.length === 0) return null; const found = context.getNodesByName(name).filter((m) => m.language === 'dart' && (m.kind === 'method' || m.kind === 'function' || m.kind === 'constant' || m.kind === 'enum_member') && @@ -4077,14 +4198,14 @@ export function matchDartAnnotation(ref: UnresolvedRef, context: ResolutionConte const { names, call } = written; let pool: Node[]; let resolvedBy: ResolvedRef['resolvedBy'] = 'exact-match'; - if (names.length === 1 || (names.length === 2 && isDartImportPrefix(ref.filePath, names[0]!, context))) { + if (names.length === 1 || (names.length === 2 && dartImportPrefixes(ref.filePath, context).has(names[0]!))) { const prefix = names.length === 2 ? names[0]! : null; const own = prefix === null && !call ? dartEnclosingStatic(name, ref, context) : null; if (own) return { original: ref, targetNodeId: own.id, confidence: 0.9, resolvedBy }; pool = context.getNodesByName(name).filter((n) => isDartLibraryDecl(n) && (call ? isDartAnnotationClass(n, context) : n.kind === 'constant') && isDartTopLevelVisible(n, ref, context, prefix)); if (prefix === null) pool = preferOwnDartLibrary(pool, ref, context); - } else if (names.length === 2 || (names.length === 3 && isDartImportPrefix(ref.filePath, names[0]!, context))) { + } else if (names.length === 2 || (names.length === 3 && dartImportPrefixes(ref.filePath, context).has(names[0]!))) { const prefix = names.length === 3 ? names[0]! : null; let owners = context.getNodesByName(names[names.length - 2]!).filter((n) => isDartLibraryDecl(n) && DART_TYPE_KINDS.has(n.kind) && isDartTopLevelVisible(n, ref, context, prefix)); @@ -4194,8 +4315,10 @@ function dartExtensionMemberOf(typeName: string, name: string, ref: UnresolvedRe * it, and the SDK's `Uri.parse(…)`, past bloc_lint's `extension on Uri`, to a * project `parse`. A static constant's callee is the value it holds (`static * const autoDispose = AutoDisposeFutureProviderBuilder();`). The member is - * found as a chain's static link finds it (dartStaticMember). Undefined when - * the receiver names no Dart type of the project. + * found as a chain's static link finds it (dartStaticMember). Written through + * an import prefix (`p.Box.named(…)`, which arrives as `Box.named`), the + * type is the one that import brings in, if any. Undefined when the receiver + * names no Dart type of the project. */ function matchDartTypeMemberCall( typeName: string, @@ -4203,8 +4326,11 @@ function matchDartTypeMemberCall( ref: UnresolvedRef, context: ResolutionContext, ): ResolvedRef | null | undefined { - if (!context.getNodesByName(typeName).some((n) => n.language === 'dart' && DART_TYPE_KINDS.has(n.kind))) return undefined; - const own = dartStaticMember(typeName, member, ref, context); + const types = context.getNodesByName(typeName).filter((n) => n.language === 'dart' && DART_TYPE_KINDS.has(n.kind)); + const prefix = types.length > 0 || /^[_$]*[A-Z]/.test(typeName) ? dartTypeCallPrefix(typeName, member, ref, context) : null; + const isOwner = (n: Node): boolean => prefix === null || dartPrefixSees(ref.filePath, prefix, n.filePath, typeName, context); + if (!types.some(isOwner)) return prefix === null ? undefined : null; + const own = dartStaticMember(typeName, member, ref, context, isOwner); return own && own.kind !== 'enum_member' ? { original: ref, targetNodeId: own.id, confidence: 0.85, resolvedBy: 'qualified-name' } : null; } @@ -12222,6 +12348,14 @@ function matchReferenceInner( return nmTimed('swiftTypePath', ref, () => resolveSwiftTypePathCall(ref, context)); } + // A Dart call through an import prefix (`http.get(…)`) is to what the + // prefixed import exports, or to nothing: the strategies below would take + // the prefix for a receiver and guess a method by its name. + if (ref.language === 'dart' && ref.referenceKind === 'calls') { + const prefixed = nmTimedT('dartPrefixed', ref, () => matchDartPrefixedCall(ref, context)); + if (prefixed !== undefined) return prefixed; + } + // Try strategies in order of confidence let result: ResolvedRef | null; From 83f54a18532ca9fa8cc3d7c14d425ca8bcaa0e08 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 19:16:55 +0000 Subject: [PATCH 19/23] fix(dart): a library links the files its part directives name (#2391) A Dart `part 'x.g.dart';` now mints an `import` node (name = the URI, signature = the directive) and an `imports` ref from the library's file node, in both extractors. The ref resolves through `dartDirectiveFile` by the rules an import or export follows, so the library's file links the part's file. A library and its parts are one library, so a change to a part, generated or hand-written, now reaches the library and what imports it in `codegraph affected` and the files listed as using the part. Before, neither `part` nor `part of` left a trace, and the two files were joined only by whatever symbol edges happened to cross between them: riverpod's framework.dart, which holds nothing but `part` lines, by none. `part of` still records nothing: the library's edge already joins the two files, and a part -> library edge would list every pair on both import rails of both files and make each a file 2-cycle. The kernel's directive arm now goes on into the directive's children, as the TS ladder does. Its `import_or_export` arm used to return first, so an annotated directive's arguments (`@Tag(f) import 'a.dart';`) were fn-ref candidates on the wasm path only. Validation on rrousselGit/riverpod @4ba1be2 and felangel/bloc @b9be1e2 with the kernel loaded, base 837a1866: - bloc: +53 import nodes, +53 contains, +53 imports (library -> part). - riverpod: +294 import nodes, +294 contains, +258 imports, +36 refs left unresolved (generated parts that are not committed). - Nothing removed; kernel and wasm dumps byte-identical; parity sweeps 0 diffs. Every added edge sits on a `part` line whose URI names the target, and the target's `part of` names the library back (311/311). Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/dart-part-directives.test.ts | 216 ++++++++++++++++++ .../kernel-parity/TortureDirectives.dart | 43 ++++ .../kernel-parity/TorturePartOfName.dart | 10 + __tests__/kernel-dart-parity.test.ts | 12 +- codegraph-kernel/src/dart.rs | 16 +- docs/design/dart-kernel-port-checklist.md | 39 ++-- src/extraction/languages/dart.ts | 34 +-- src/resolution/dart-libraries.ts | 15 +- src/resolution/import-resolver.ts | 16 +- 10 files changed, 353 insertions(+), 49 deletions(-) create mode 100644 __tests__/dart-part-directives.test.ts create mode 100644 __tests__/fixtures/kernel-parity/TortureDirectives.dart create mode 100644 __tests__/fixtures/kernel-parity/TorturePartOfName.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index d87506bdf2..d4d89d3484 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In Dart, a comment inside a chain of calls no longer loses part of it: a call with a comment before its arguments, like `box.grow /* by */ (3)`, now links to the method it calls, and a getter read or a static access written after a comment, like `Config //` followed by `.instance` on the next line (the empty `//` keeps `dart format` from joining the lines), now counts as a use. Re-index Dart projects after upgrading. - In Dart, a call, a constructor call or a type written without a receiver now links only to a declaration the file can see: one in its own library (the file and its `part` files) or one exported by a library it imports, with `export` chains, `show`, `hide` and `as` prefixes followed the way Dart follows them. So a generated `.g.dart` file reaches its own library's function or type instead of a same-named one in a neighbouring file, a call to a package function such as `fakeAsync`, `runApp` or `unawaited` no longer links to an unrelated project function of that name, and a bare call is never taken for another type's enum value or static constant. Re-index Dart projects after upgrading. - In Dart, an `import` or `export` now links to the file it names: `package:my_app/src/cart.dart` to that package's `lib/src/cart.dart`, and a relative path to the file it points to from the importing file. Before, only the file name at the end was matched, so `import 'package:flutter/widgets.dart'` linked to whichever project file was called `widgets.dart`, and most imports of your own files didn't link to the file at all, which threw off `codegraph affected` and the files listed as using a file. An import of a Dart SDK library or of a package from outside your project now links nothing, and when packages in one repository share a name, the one the importing app depends on by `path:` is used. Re-index Dart projects after upgrading. +- In Dart, a `part` directive, like `part 'user.g.dart';` or `part 'src/widgets.dart';`, now links a library to the part's file the way an import does. A library and its parts are one library, so a change to a part, whether a generated `.g.dart` or `.freezed.dart` file or one you wrote, now reaches the library and the code that imports it in `codegraph affected` and in the files listed as using the part. Before, the two files were connected only when a call or a type happened to cross between them, which a library made only of `part` lines never has. A part your project doesn't have, like a generated file that isn't committed, links nothing. Re-index Dart projects after upgrading. - In Dart, an annotation now links to the constant or constructor it names, read the way it is written: `@riverpod` reaches Riverpod's `const riverpod = Riverpod();`, `@Riverpod(keepAlive: true)` the `Riverpod` class, an annotation written through a class, like `@SomeClass.value` or `@SomeClass.named(…)`, that class's own constant, enum value or constructor, and `@meta.immutable` only what the `meta` import brings in. Before, an annotation was matched like a function decorator, so a method, getter or function that only shared its name won: every `@riverpod` provider in Riverpod's own repository was linked to an unrelated getter called `riverpod`, and `callers` and impact for the real annotation missed them. Re-index Dart projects after upgrading. - In Dart, an annotation is no longer lost when a comment sits between it and the declaration, like `@override` followed by `// ignore: must_call_super`, a `///` comment written below the annotations, or `@riverpod` followed by an `// expect_lint: …` line. Before, the comment hid the annotation, so a provider written that way was missing from the annotation's `callers` and impact. Re-index Dart projects after upgrading. - In Dart, a call written through an import prefix, like `http.get(…)` after `import 'package:http/http.dart' as http;`, or `utils.Listener()` and `kit.Box.create()` through a prefix of your own, now links to what the library imported with that prefix exports, following its `export` chains, `show` and `hide`, and to nothing when that library is a package outside your project. Before, the prefix was taken for a variable, so `http.get(…)` could link to an unrelated `Http` class's `get` method, and calls made through a prefix into your own libraries were missing from `callers` and impact. Re-index Dart projects after upgrading. diff --git a/__tests__/dart-part-directives.test.ts b/__tests__/dart-part-directives.test.ts new file mode 100644 index 0000000000..66429f7f27 --- /dev/null +++ b/__tests__/dart-part-directives.test.ts @@ -0,0 +1,216 @@ +/** + * A Dart library names each of its parts with `part '';`, and that links + * the library's file to the part's: an `imports` edge, by the URI rules an + * import or export follows. A part and its library are one library, so a + * change to the part is a change to what every importer of the library sees. + * Before, neither `part` nor `part of` left a trace, and the two files were + * joined only by whatever symbol edges happened to cross between them — + * riverpod's framework.dart, which holds nothing but its parts, by none, so a + * change to one of them reached no test that imports riverpod. `part of` + * still adds nothing: the library's edge already joins the two files. + */ +import { describe, it, expect, afterAll, beforeAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; +import { buildFile } from '../src/ui-server/api/file'; + +function writeTree(root: string, files: Record): void { + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } +} + +/** ` -> ` for every `imports` edge out of `file`: a file by its path, anything else by kind, file and name. */ +function importsFrom(cg: CodeGraph, file: string): string[] { + const ids = cg.getNodesInFile(file).map((n) => n.id); + return cg.getOutgoingEdgesFrom(ids, ['imports']) + .map((e) => { + const t = cg.getNode(e.target)!; + return `${e.line} -> ${t.kind === 'file' ? t.filePath : `${t.kind} ${t.filePath}#${t.name}`}`; + }) + .sort(); +} + +/** The URIs of `file`'s imports left unresolved. */ +function unresolvedImportsOf(cg: CodeGraph, file: string): string[] { + const fileNode = cg.getNodesInFile(file).find((n) => n.kind === 'file')!; + return cg.getUnresolvedReferencesFrom(fileNode.id) + .filter((r) => r.referenceKind === 'imports') + .map((r) => r.referenceName) + .sort(); +} + +/** ` | ` of each `import` node in `file`. */ +function importNodesIn(cg: CodeGraph, file: string): string[] { + return cg.getNodesInFile(file) + .filter((n) => n.kind === 'import') + .map((n) => `${n.name} | ${n.signature}`) + .sort(); +} + +/** Every file a change to `file` reaches through its dependents, as `codegraph affected` walks them. */ +function reachedFrom(cg: CodeGraph, file: string): string[] { + const seen = new Set([file]); + const queue = [file]; + while (queue.length > 0) { + for (const dependent of cg.getFileDependents(queue.shift()!)) { + if (seen.has(dependent)) continue; + seen.add(dependent); + queue.push(dependent); + } + } + seen.delete(file); + return [...seen].sort(); +} + +describe('Dart part directives', () => { + let root = ''; + let cg: CodeGraph; + + beforeAll(async () => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-parts-')); + writeTree(root, { + // riverpod's framework.dart: a library made of nothing but its parts, + // one in a subdirectory, one generated; a barrel exports it and a test + // imports the barrel. + 'pubspec.yaml': 'name: app\n', + 'lib/src/framework.dart': `import 'dart:async'; + +import 'package:meta/meta.dart'; + +part 'core/element.dart'; +part "core/container.dart"; +part 'framework.g.dart'; +`, + 'lib/src/core/element.dart': `part of '../framework.dart'; + +class Element {} +`, + 'lib/src/core/container.dart': `part of '../framework.dart'; + +class Container {} +`, + 'lib/src/framework.g.dart': `// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'framework.dart'; + +String _$frameworkHash() => 'abc'; +`, + 'lib/app.dart': `export 'src/framework.dart'; +`, + 'test/framework_test.dart': `import 'package:app/app.dart'; + +void main() {} +`, + // A part named by a package: URI, and a part of a library named by its library name. + 'packages/kit/pubspec.yaml': 'name: kit\n', + 'packages/kit/lib/kit.dart': `part 'package:kit/src/widgets.dart'; +`, + 'packages/kit/lib/src/widgets.dart': `part of 'package:kit/kit.dart'; + +class Widget {} +`, + 'lib/legacy/models.dart': `library app.models; + +part 'user.dart'; +`, + 'lib/legacy/user.dart': `part of app.models; + +class User {} +`, + // A generated part nobody committed, and another app's file of that name. + 'examples/a/pubspec.yaml': 'name: a\n', + 'examples/a/lib/main.dart': `part 'main.g.dart'; + +void main() {} +`, + 'examples/b/pubspec.yaml': 'name: b\n', + 'examples/b/lib/main.dart': `part 'main.g.dart'; + +void main() {} +`, + 'examples/b/lib/main.g.dart': `part of 'main.dart'; +`, + }); + cg = await CodeGraph.init(root, { index: true }); + }); + + afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + }); + + it('links a library to each part it names, as an import node and an imports edge', () => { + expect(importsFrom(cg, 'lib/src/framework.dart')).toEqual([ + '5 -> lib/src/core/element.dart', + '6 -> lib/src/core/container.dart', + '7 -> lib/src/framework.g.dart', + ]); + expect(unresolvedImportsOf(cg, 'lib/src/framework.dart')).toEqual(['dart:async', 'package:meta/meta.dart']); + expect(importNodesIn(cg, 'lib/src/framework.dart')).toEqual([ + 'core/container.dart | part "core/container.dart";', + 'core/element.dart | part \'core/element.dart\';', + 'dart:async | import \'dart:async\';', + 'framework.g.dart | part \'framework.g.dart\';', + 'package:meta/meta.dart | import \'package:meta/meta.dart\';', + ]); + }); + + it('resolves a part named by a package: URI or under a library name', () => { + expect(importsFrom(cg, 'packages/kit/lib/kit.dart')).toEqual(['1 -> packages/kit/lib/src/widgets.dart']); + expect(importsFrom(cg, 'lib/legacy/models.dart')).toEqual(['3 -> lib/legacy/user.dart']); + }); + + it('records nothing for `part of`', () => { + for (const part of ['lib/src/core/element.dart', 'lib/src/framework.g.dart', 'packages/kit/lib/src/widgets.dart', 'lib/legacy/user.dart']) { + expect(importsFrom(cg, part), part).toEqual([]); + expect(unresolvedImportsOf(cg, part), part).toEqual([]); + expect(importNodesIn(cg, part), part).toEqual([]); + } + }); + + it("leaves a part the project doesn't have unresolved, never another file of its name", () => { + expect(importsFrom(cg, 'examples/a/lib/main.dart')).toEqual([]); + expect(unresolvedImportsOf(cg, 'examples/a/lib/main.dart')).toEqual(['main.g.dart']); + expect(importsFrom(cg, 'examples/b/lib/main.dart')).toEqual(['1 -> examples/b/lib/main.g.dart']); + }); + + it('makes a change to a part reach what depends on its library', () => { + expect(cg.getFileDependents('lib/src/core/element.dart')).toEqual(['lib/src/framework.dart']); + expect(cg.getFileDependencies('lib/src/framework.dart').sort()).toEqual([ + 'lib/src/core/container.dart', + 'lib/src/core/element.dart', + 'lib/src/framework.g.dart', + ]); + expect(reachedFrom(cg, 'lib/src/core/element.dart')).toEqual([ + 'lib/app.dart', + 'lib/src/framework.dart', + 'test/framework_test.dart', + ]); + }); + + it("shows the parts on the library's import rail and the library on each part's", () => { + const library = buildFile(cg, root, 'lib/src/framework.dart') as { + imports: { items: Array<{ file: string }> }; + dependencies: string[]; + }; + expect(library.imports.items.map((row) => row.file).sort()).toEqual([ + 'lib/src/core/container.dart', + 'lib/src/core/element.dart', + 'lib/src/framework.g.dart', + ]); + const part = buildFile(cg, root, 'lib/src/framework.g.dart') as { + imports: { items: unknown[] }; + importedBy: { items: Array<{ file: string }> }; + unresolvedImports: unknown[]; + dependents: string[]; + }; + expect(part.importedBy.items.map((row) => row.file)).toEqual(['lib/src/framework.dart']); + expect(part.imports.items).toEqual([]); + expect(part.unresolvedImports).toEqual([]); + expect(part.dependents).toEqual(['lib/src/framework.dart']); + }); +}); diff --git a/__tests__/fixtures/kernel-parity/TortureDirectives.dart b/__tests__/fixtures/kernel-parity/TortureDirectives.dart new file mode 100644 index 0000000000..242a7a8986 --- /dev/null +++ b/__tests__/fixtures/kernel-parity/TortureDirectives.dart @@ -0,0 +1,43 @@ +/// A library's directives: imports and exports in every form, and its parts. +library torture.directives; + +import 'dart:async'; +import 'package:torture/other.dart' as other show OtherClass, otherFn; +import 'package:torture/hidden.dart' hide Hidden; +import 'src/conditional_stub.dart' + if (dart.library.io) 'src/conditional_io.dart' + if (dart.library.js_interop) 'src/conditional_web.dart'; +import 'src/deferred.dart' deferred as lazy; + +@Tag(viaImport) +import 'src/annotated.dart'; + +export 'src/exported.dart' show Exported; +@Tag(viaExport) +export 'src/annotated_export.dart'; + +// Parts: in a subdirectory, above this one, by package: URI, in each quote +// style, with comments inside and around, and annotated. +part 'directives.g.dart'; +part "src/directives_part.dart"; +part '../shared_part.dart'; +part 'package:torture/src/package_part.dart'; +part '''triple_part.dart'''; +part /* generated */ 'commented_part.dart'; // trailing +part + 'wrapped_part.dart'; +@Tag(viaPart) +part 'annotated_part.dart'; +@Tag([viaPartList, viaPart]) +part 'annotated_list_part.dart'; + +class Tag { + const Tag(Object value); +} + +void viaImport() {} +void viaExport() {} +void viaPart() {} +void viaPartList() {} + +String describe() => 'directives'; diff --git a/__tests__/fixtures/kernel-parity/TorturePartOfName.dart b/__tests__/fixtures/kernel-parity/TorturePartOfName.dart new file mode 100644 index 0000000000..d7de73a40b --- /dev/null +++ b/__tests__/fixtures/kernel-parity/TorturePartOfName.dart @@ -0,0 +1,10 @@ +/// A part of a library it names by library name, not by URI: the `part of` +/// directive records nothing. +@Tag(helper) +part of torture.directives; + +class PartOfName { + void run() => helper(); +} + +void helper() {} diff --git a/__tests__/kernel-dart-parity.test.ts b/__tests__/kernel-dart-parity.test.ts index 08aec13e5c..487fcfd17d 100644 --- a/__tests__/kernel-dart-parity.test.ts +++ b/__tests__/kernel-dart-parity.test.ts @@ -35,8 +35,10 @@ * by every sibling step; TortureAnnotatedDocs.dart: the dartdoc above a * member's annotations, read past them, and what still ends the walk; * TortureAnnotatedComments.dart: the comments between annotations and their - * declaration, stepped over by the decorator scan) and their CRLF variants - * (derived in-memory — #1329), plus defer and generated-file pins. + * declaration, stepped over by the decorator scan; TortureDirectives.dart / + * TorturePartOfName.dart: `part` as an import of the part's file, `part of` + * as nothing, and the arguments of annotated directives) and their CRLF + * variants (derived in-memory — #1329), plus defer and generated-file pins. * * The full-repo sweeps live in scripts/kernel-parity.mjs (shelf/bloc/flutter * with --max-deferral 0.3); this suite keeps the invariant alive in @@ -159,6 +161,12 @@ describe.skipIf(!kernelBuilt)('kernel Dart extraction parity', () => { // body — are stepped over by the decorator scan; a field, a variable, an // import or the previous member's body still ends it. ['TortureAnnotatedComments.dart', 30], + // A library's directives: imports and exports in every form, and `part` + // in every URI and quote form — each an import node and an `imports` ref + // — with the arguments of an annotated directive walked for fn-refs. + ['TortureDirectives.dart', 20], + // `part of` a library named by its library name records nothing. + ['TorturePartOfName.dart', 3], ] as const; for (const [file, minNodes] of FIXTURES) { diff --git a/codegraph-kernel/src/dart.rs b/codegraph-kernel/src/dart.rs index 4fdfcdee94..78bc8a5db9 100644 --- a/codegraph-kernel/src/dart.rs +++ b/codegraph-kernel/src/dart.rs @@ -826,9 +826,13 @@ impl<'t> Walker<'t> { return; } } - "import_or_export" => { + // importTypes (dart.ts): `import` / `export`, and `part + // 'x.g.dart';`, which links the library to the part's file. The + // TS ladder goes on into the directive's children, so this does + // too: an annotation's arguments are fn-ref capture points + // (`@Tag(bar) import 'a.dart';` captures `bar`). + "import_or_export" | "part_directive" => { self.extract_import(node); - return; } "new_expression" => { // INSTANTIATION_KINDS row — from the FILE/CLASS on the @@ -1036,7 +1040,7 @@ impl<'t> Walker<'t> { false } - // --- extractImport (:3170; hook dart.ts:261-304) ---------------------- + // --- extractImport (:3170; hook dart.ts extractImport) ----------------- fn extract_import(&mut self, node: Node<'t>) { let find_child = |parent: Node<'t>, kind: &str| -> Option> { @@ -1050,6 +1054,12 @@ impl<'t> Walker<'t> { find_child(uri, "string_literal") }; let mut module: Option = None; + // A part: `part 'x.g.dart';` holds its `uri` directly. + if node.kind() == "part_directive" { + if let Some(sl) = find_child(node, "uri").and_then(|uri| find_child(uri, "string_literal")) { + module = Some(self.text(sl).replace(['\'', '"'], "")); + } + } if let Some(li) = find_child(node, "library_import") { if let Some(spec) = find_child(li, "import_specification") { if let Some(sl) = uri_of(spec) { diff --git a/docs/design/dart-kernel-port-checklist.md b/docs/design/dart-kernel-port-checklist.md index 4e1b2e8f16..0386b419a2 100644 --- a/docs/design/dart-kernel-port-checklist.md +++ b/docs/design/dart-kernel-port-checklist.md @@ -194,8 +194,8 @@ Types: functionTypes=[`function_signature`] (:119); classTypes= `redirecting_factory_constructor_signature`] (:126 — the last two since 2026-10-06); interfaceTypes=[] ; structTypes=[]; enumTypes=[`enum_declaration`] (:129); enumMemberTypes=[`enum_constant`] -(:130); typeAliasTypes=[`type_alias`] (:131); importTypes=[`import_or_export`] -(:132); **callTypes=[] (:133 — extractCall NEVER runs for dart; all call refs +(:130); typeAliasTypes=[`type_alias`] (:131); importTypes=[`import_or_export`, +`part_directive`] (:132 — the second since 2026-10-06); **callTypes=[] (:133 — extractCall NEVER runs for dart; all call refs ride `extractBareCall` in the body walker)**; variableTypes=[] (:134 — extractVariable never runs); extraClassNodeTypes=[`mixin_declaration`, `extension_declaration`] (:135). nameField=`name` (:172), bodyField=`body` @@ -420,20 +420,26 @@ Hooks PRESENT (port each exactly — anchors into languages/dart.ts): - **extractImport (:261-304)** — importText = trimmed full node slice; moduleName = the URI string content: `library_import > import_specification > configurable_uri > uri > string_literal` (else the - same chain under `library_export`), quotes stripped via - `.replace(/['"]/g,'')`. Returns {moduleName, signature} (no handledRefs) + same chain under `library_export`; a `part_directive` holds its `uri` + directly), quotes stripped via `.replace(/['"]/g,'')` (dartUriText). + Returns {moduleName, signature} (no handledRefs) → import NODE (name = the URI, e.g. `package:torture/other.dart`, - `dart:async`, `src/reexported.dart`) + the generic `imports` ref + `dart:async`, `src/reexported.dart`, `x.g.dart`) + the generic `imports` ref (tree-sitter.ts:3183-3194) {from: file node (no namespace exists), name = - URI, line/col of the import_or_export node}. `as alias`, `show`/`hide` + URI, line/col of the directive node — at its first annotation when it has + one}. `as alias`, `show`/`hide` combinators: IGNORED (not read). **`import 'x.dart' deferred as y;` is INVISIBLE** — the deferred form's import_specification holds a bare `uri` (NO configurable_uri wrapper) → hook returns null → falls through the multi-import inline handlers (none match import_or_export) → no node, no - ref (pinned, `extract-mini.txt`). `part`/`part of`/`library` directives - are different node types (part_directive, part_of_directive, library_name) - in NO type list → invisible. None of the TS/py/rust/php/ruby binding - emitters (:3197-3234) fire for dart. + ref (pinned, `extract-mini.txt`). **`part 'x.g.dart';` is an import since + 2026-10-06** (signature `part 'x.g.dart';`): the resolver reads its URI by + the import/export rules (`dartDirectiveFile`), so the library's file links + the part's file and a change to the part reaches the library's dependents. + `part of` and `library` (part_of_directive, library_name) are in NO type + list → invisible: the library's `part` edge already joins the two files. + None of the TS/py/rust/php/ruby binding emitters (:3197-3234) fire for + dart. - **extractBareCall (:305-379)** — §Calls, the full matrix. Hooks ABSENT (the walker must NOT do these): `preParse`, `recoverMangledName`, @@ -467,12 +473,12 @@ Registration: `EXTRACTORS.dart` (languages/index.ts:56), `FN_REF_SPECS.dart` | `method_signature`, `constructor_signature` | methodTypes:1027 | **NOT class-gated at the ladder** — extractMethod:1737 runs anywhere; its own gate :1747 (not class-like, no methodsAreTopLevel, no receiver) falls back: parent `object`/`object_expression`? (never in dart) else **extractFunction** — this is how extension-TYPE members and any stray non-class method_signature become plain `function` nodes (pinned: `extension type MetersT` → function `km`, bare QN) | | `enum_declaration` | enumTypes:1064 → extractEnum:1914 | §Class family | | `type_alias` | typeAliasTypes:1071 → extractTypeAlias:2890 | plain type_alias node; `getChildByField(node,'value')` → **null** (no fields) → **NO refs from the aliased type** (`typedef MapAlias = Map` emits nothing); returns false → children re-visited (function_type/formal_parameter_list children match nothing) | -| `import_or_export` | importTypes:1209 → extractImport:3170 | §Extractor config | +| `import_or_export`, `part_directive` | importTypes:1209 → extractImport:3170 | §Extractor config. No skipChildren: the directive's children are still recursed, so an annotated directive's arguments are fn-ref capture points (`@Tag(f) import 'a.dart';` captures `f`). The kernel arm recurses too — since 2026-10-06; before, its `import_or_export` arm returned and missed those (TortureDirectives.dart pins both) | | `new_expression` | INSTANTIATION_KINDS:1255 (`new_expression` ∈ :354-361) | extractInstantiation:4610 → ctor field lookups null → namedChild(0) = type_identifier → `instantiates` ref from stack top; `<`-strip + last-`.`-segment apply (`new p.Foo()` → `Foo`). findAnonymousClassBody → always null for dart. Children still recursed | | `function_body` (sibling of a consumed signature) | **no branch** | recursed → THE DOUBLE-WALK (§below) | | `declaration` (fields, bodiless ctors) | no branch | recursed → constructor_signature, constant_constructor_signature and redirecting_factory_constructor_signature hit methodTypes; each field `initialized_identifier` hits the hook (body-walked for the class); initializers, annotations-in-place: nothing | | `getter_signature` / `setter_signature` BARE (top level) | no branch | **top-level getters/setters are INVISIBLE** (no node; their sibling function_body is visitNode-recursed where calls don't extract) — in classes they're method_signature-wrapped → methods | -| `const_object_expression`, `selector`, `cascade_section`, `assignment_expression`, `local_variable_declaration`, patterns, `extension_type_declaration`, `part_directive`, `library_name`, lambdas | no branch | recursed; calls only extract in the BODY walker (`extractBareCall` is not consulted by visitNode!) — §Calls for the consequences | +| `const_object_expression`, `selector`, `cascade_section`, `assignment_expression`, `local_variable_declaration`, patterns, `extension_type_declaration`, `part_of_directive`, `library_name`, lambdas | no branch | recursed; calls only extract in the BODY walker (`extractBareCall` is not consulted by visitNode!) — §Calls for the consequences | | `property_signature`/`method_signature` TS branch (:1282) | **shadowed** | method_signature is consumed at :1027 first; property_signature isn't a dart kind — branch unreachable | ### THE DOUBLE-WALK (sibling bodies) — reproduce it exactly @@ -671,9 +677,10 @@ chain → FIRST value child only); `static final sharedInst = WidgetT(0)` → constant under the class, sig `= WidgetT`; multi-declarations → one node each with own columns. **NO nodes ever**: instance fields (typed/untyped/ late/var), `static var`, top-level var/typed vars, top-level getters/ -setters, extension_type containers, `part`/`part of`/`library`/deferred +setters, extension_type containers, `part of`/`library`/deferred imports. (Named `const` constructors and redirecting factories mint -methods since 2026-10-06; the unnamed ones still mint nothing.) **Initializers +methods since 2026-10-06, and a `part` directive an import; the unnamed +constructors still mint nothing.) **Initializers are code:** every initializer is walked with the body walker — a constant's for the constant (riverpod's `final repoProvider = Provider((ref) => Repository(ref.watch(dioProvider)));` → calls @@ -1270,7 +1277,9 @@ NO unwrap, NO ungatedModes, NO addressOfOnly. Pins: `svy-dart/torture.dart` (231 lines, parses clean; its `extract-torture.txt` is the expected-output pin). Inventory by branch: imports (dart:, package: with `as`+`show`, export with `hide`, - **deferred → invisible**, part → invisible); doc shapes (`///` run, + **deferred → invisible**, part → invisible — an import since + 2026-10-06, pinned with every directive form in TortureDirectives.dart, + and `part of` by library name in TorturePartOfName.dart); doc shapes (`///` run, `/** */` kept, `//` kept, a `///` above an annotation); annotations (bare, with-args, stacked → reverse order, on class); top-level constants (CAPS/lowercase/multi/typed/derived, sig truncation ≥100 chars); diff --git a/src/extraction/languages/dart.ts b/src/extraction/languages/dart.ts index f5b7b8a258..6f68fb234e 100644 --- a/src/extraction/languages/dart.ts +++ b/src/extraction/languages/dart.ts @@ -434,6 +434,12 @@ function dartCallee(prev: SyntaxNode): string | undefined { return undefined; } +/** The URI a directive's `uri` node holds, quotes stripped: `x.g.dart` for `'x.g.dart'`. */ +function dartUriText(uri: SyntaxNode | undefined, source: string): string { + const literal = uri?.namedChildren.find((c: SyntaxNode) => c.type === 'string_literal'); + return literal ? getNodeText(literal, source).replace(/['"]/g, '') : ''; +} + export const dartExtractor: LanguageExtractor = { functionTypes: ['function_signature'], classTypes: ['class_definition'], @@ -452,7 +458,12 @@ export const dartExtractor: LanguageExtractor = { enumTypes: ['enum_declaration'], enumMemberTypes: ['enum_constant'], typeAliasTypes: ['type_alias'], - importTypes: ['import_or_export'], + // `part 'x.g.dart';` is a library naming one of its own files — a generated + // part, often. Its URI resolves as an import's does, so the library links + // the part's file the way it links a file it imports, and a change to the + // part reaches whatever depends on the library. `part of` adds nothing to + // that edge, and stays out. + importTypes: ['import_or_export', 'part_directive'], callTypes: [], // Dart calls use identifier+selector, handled via extractBareCall variableTypes: [], // `extension_type_declaration` is Dart 3's extension type. It sits beside the @@ -662,6 +673,11 @@ export const dartExtractor: LanguageExtractor = { const importText = source.substring(node.startIndex, node.endIndex).trim(); let moduleName = ''; + // A part: part 'x.g.dart'; + if (node.type === 'part_directive') { + moduleName = dartUriText(node.namedChildren.find((c: SyntaxNode) => c.type === 'uri'), source); + } + // Dart imports: import 'dart:async'; import 'package:foo/bar.dart' as bar; const libraryImport = node.namedChildren.find((c: SyntaxNode) => c.type === 'library_import'); if (libraryImport) { @@ -669,13 +685,7 @@ export const dartExtractor: LanguageExtractor = { if (importSpec) { const configurableUri = importSpec.namedChildren.find((c: SyntaxNode) => c.type === 'configurable_uri'); if (configurableUri) { - const uri = configurableUri.namedChildren.find((c: SyntaxNode) => c.type === 'uri'); - if (uri) { - const stringLiteral = uri.namedChildren.find((c: SyntaxNode) => c.type === 'string_literal'); - if (stringLiteral) { - moduleName = getNodeText(stringLiteral, source).replace(/['"]/g, ''); - } - } + moduleName = dartUriText(configurableUri.namedChildren.find((c: SyntaxNode) => c.type === 'uri'), source); } } } @@ -686,13 +696,7 @@ export const dartExtractor: LanguageExtractor = { if (libraryExport) { const configurableUri = libraryExport.namedChildren.find((c: SyntaxNode) => c.type === 'configurable_uri'); if (configurableUri) { - const uri = configurableUri.namedChildren.find((c: SyntaxNode) => c.type === 'uri'); - if (uri) { - const stringLiteral = uri.namedChildren.find((c: SyntaxNode) => c.type === 'string_literal'); - if (stringLiteral) { - moduleName = getNodeText(stringLiteral, source).replace(/['"]/g, ''); - } - } + moduleName = dartUriText(configurableUri.namedChildren.find((c: SyntaxNode) => c.type === 'uri'), source); } } } diff --git a/src/resolution/dart-libraries.ts b/src/resolution/dart-libraries.ts index 61b328fb65..2301899864 100644 --- a/src/resolution/dart-libraries.ts +++ b/src/resolution/dart-libraries.ts @@ -15,11 +15,11 @@ * .dart file, never above the project root. When packages share a name * (example apps), the importing file's own package wins, then the one * enclosing it, then the one its package depends on by `path:`, else all of - * them count. An `import` / `export` edge links the one file its URI names - * (`dartDirectiveFile`). + * them count. An `import`, `export` or `part` edge links the one file its URI + * names (`dartDirectiveFile`). * - * Directives are read from the head of each file at resolution time; - * extraction, and the kernel's, are unchanged. Where the library cannot be + * Directives are read from the head of each file at resolution time, not from + * what extraction recorded of them. Where the library cannot be * established — a `part of` naming no library this can find, a file it cannot * read, a file in no package — every file counts as visible, so the rule only * narrows where the library is known. @@ -542,9 +542,10 @@ function resolveDartUri(from: string, uri: string, context: ResolutionContext, m } /** - * The project file a Dart `import` or `export` in `from` names by `uri`, or - * null: a `dart:` library, a package from outside the project, a path out of - * it, or a package name the project repeats with nothing to say which. + * The project file a Dart `import`, `export` or `part` in `from` names by + * `uri`, or null: a `dart:` library, a package from outside the project, a + * path out of it, or a package name the project repeats with nothing to say + * which. */ export function dartDirectiveFile(from: string, uri: string, context: ResolutionContext): string | null { const files = resolveDartUri(from, uri, context, memoFor(context)); diff --git a/src/resolution/import-resolver.ts b/src/resolution/import-resolver.ts index b6a8e66bb7..4c3d5570dc 100644 --- a/src/resolution/import-resolver.ts +++ b/src/resolution/import-resolver.ts @@ -894,11 +894,12 @@ export function isCobolCopybookRef(ref: UnresolvedRef): boolean { } /** - * Is this a Dart `import` / `export`? Its name is the URI, which names one - * library file (see ./dart-libraries) or none — `dart:async`, a package from - * outside the project — and never a symbol: the name-matcher took the URI's - * last segment for a file name (`package:flutter/foundation.dart` went to - * riverpod's own foundation.dart) or bound it to the file's own `import` node. + * Is this a Dart `import`, `export` or `part`? Its name is the URI, which + * names one file (see ./dart-libraries) or none — `dart:async`, a package from + * outside the project, a generated part nobody committed — and never a + * symbol: the name-matcher took the URI's last segment for a file name + * (`package:flutter/foundation.dart` went to riverpod's own foundation.dart) + * or bound it to the file's own `import` node. */ export function isDartImportRef(ref: UnresolvedRef): boolean { return ref.language === 'dart' && ref.referenceKind === 'imports'; @@ -1651,8 +1652,9 @@ export function resolveViaImport( const fileNode = file && file !== ref.filePath ? context.getNodesInFile(file).find((n) => n.kind === 'file') : undefined; if (fileNode) return { original: ref, targetNodeId: fileNode.id, confidence: 0.9, resolvedBy: 'import' }; } - // A Dart `import` / `export` URI names a library file: `package:app/x.dart` - // is app's lib/x.dart, any other path is from the importing file. + // A Dart `import` / `export` URI names a library file, and a `part` URI one + // of the library's own files: `package:app/x.dart` is app's lib/x.dart, any + // other path is from the file the directive is in. if (isDartImportRef(ref)) { const file = dartDirectiveFile(ref.filePath, ref.referenceName, context); const fileNode = file && file !== ref.filePath ? context.getNodesInFile(file).find((n) => n.kind === 'file') : undefined; From 3f5a9e2e1d6b2feb51cbc23cc2a757487cbbf47a Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Tue, 6 Oct 2026 21:03:57 +0000 Subject: [PATCH 20/23] fix(sync): an import links the file it names when that file appears later (#2392) A sync retried parked failed refs by name_tail (#1240), but an import names a file, a folder or a namespace, not a symbol, so the lookup never found one: the tail of `package:app/b.dart` was `dart`, of `inc/db.php` `php`, of `./req` `/req`. Most languages never parked theirs at all: an import that named no file reached the importing file's own `import` node through matchByQualifiedName (its qualified name is the module path) and resolved there, so `./x` in TS/JS, `import pkg.mod`, `#include "a/b.h"`, ``, a C# `using` of an outside namespace, Go module paths and R, Solidity, Svelte and Vue imports were consumed by an edge to themselves. A Lua `require` bound the local it is assigned to. The import linked only once the importer changed, or on a full index. - resolveOne's target gate drops an `imports` ref's own import statement, so the ref parks as failed (#2388 did this for Dart alone). - A Lua / Luau `require` resolves to a module file or nothing. - An import written as a path is parked under its last segment's stem (`package:app/b.dart` -> `b`, `./z.js` -> `z`): src/db/reference-tail.ts. - Sync retries the failed imports an ADDED file can satisfy: by its name, stem and folder (importPathKeys), as a failed import's tail or whole name, and by the changed files' namespace / module names as a whole name (C# `using Foo.Bar`, Java `import com.z.*`). Same per-key ceiling. - Schema v12: two partial indexes over failed imports, which the planner needs to avoid reading every failed call that shares a tail; the migration rewrites the tails of path imports parked by an older version. Co-authored-by: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/sync-import-retry.test.ts | 425 ++++++++++++++++++++++++++++ docs/viewer-launch-changelog.md | 2 + src/db/migrations.ts | 24 +- src/db/queries.ts | 90 ++++-- src/db/reference-tail.ts | 57 ++++ src/db/schema.sql | 6 + src/extraction/index.ts | 5 + src/index.ts | 15 + src/resolution/import-resolver.ts | 10 + src/resolution/index.ts | 23 +- src/resolution/name-matcher.ts | 2 + 12 files changed, 630 insertions(+), 30 deletions(-) create mode 100644 __tests__/sync-import-retry.test.ts create mode 100644 src/db/reference-tail.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index d4d89d3484..9d900662d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In Dart, an annotation now links to the constant or constructor it names, read the way it is written: `@riverpod` reaches Riverpod's `const riverpod = Riverpod();`, `@Riverpod(keepAlive: true)` the `Riverpod` class, an annotation written through a class, like `@SomeClass.value` or `@SomeClass.named(…)`, that class's own constant, enum value or constructor, and `@meta.immutable` only what the `meta` import brings in. Before, an annotation was matched like a function decorator, so a method, getter or function that only shared its name won: every `@riverpod` provider in Riverpod's own repository was linked to an unrelated getter called `riverpod`, and `callers` and impact for the real annotation missed them. Re-index Dart projects after upgrading. - In Dart, an annotation is no longer lost when a comment sits between it and the declaration, like `@override` followed by `// ignore: must_call_super`, a `///` comment written below the annotations, or `@riverpod` followed by an `// expect_lint: …` line. Before, the comment hid the annotation, so a provider written that way was missing from the annotation's `callers` and impact. Re-index Dart projects after upgrading. - In Dart, a call written through an import prefix, like `http.get(…)` after `import 'package:http/http.dart' as http;`, or `utils.Listener()` and `kit.Box.create()` through a prefix of your own, now links to what the library imported with that prefix exports, following its `export` chains, `show` and `hide`, and to nothing when that library is a package outside your project. Before, the prefix was taken for a variable, so `http.get(…)` could link to an unrelated `Http` class's `get` method, and calls made through a prefix into your own libraries were missing from `callers` and impact. Re-index Dart projects after upgrading. +- `codegraph sync` and the file watcher now link an import to the file it names when that file is added after the importing file was indexed, or comes back after being deleted: `import 'package:app/b.dart';` in Dart, `import './side'` in JavaScript or TypeScript, `#include "net/socket.h"` in C and C++, `require 'inc/db.php'` in PHP, `import pkg.mod` in Python, a Lua `require`, or a C# `using` of a namespace declared later. Before, the import stayed unlinked until the importing file itself changed or the project was re-indexed, so `codegraph affected` and the files listed as using the new file missed it. Re-index after upgrading. ## [1.6.2] - 2026-10-03 diff --git a/__tests__/sync-import-retry.test.ts b/__tests__/sync-import-retry.test.ts new file mode 100644 index 0000000000..ce836ffe89 --- /dev/null +++ b/__tests__/sync-import-retry.test.ts @@ -0,0 +1,425 @@ +/** + * A sync links an import whose file appears after the importer was indexed. + * + * Sync retries parked failed refs by name tail (#1240), but an import names a + * file, a folder or a namespace, not a symbol, so the symbol-name lookup never + * found it: the tail of `package:app/b.dart` was `dart`, of `inc/db.php` + * `php`, of `./foo` `/foo`. Most languages never even parked theirs: a module + * path that named no file reached the importing file's own `import` node by + * its qualified name, and that edge was never revisited. A Lua `require` took + * the local it is assigned to. Either way the import linked only once the + * importer itself changed, or on a full index. + */ +import { describe, it, expect, afterEach, vi } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; +import { DatabaseConnection } from '../src/db'; +import { CURRENT_SCHEMA_VERSION, getCurrentVersion, runMigrations } from '../src/db/migrations'; +import { QueryBuilder } from '../src/db/queries'; +import { importPathKeys } from '../src/db/reference-tail'; +import type { Node } from '../src/types'; + +interface Case { + name: string; + initial: Record; + added: Record; + /** The importing file. */ + from: string; + /** What its imports reach once `added` exists: ` `. */ + expected: string[]; +} + +const CASES: Case[] = [ + { + name: 'Dart', + initial: { + 'pubspec.yaml': 'name: app\n', + 'lib/a.dart': "import 'package:app/b.dart';\nimport 'package:kit/kit.dart';\nimport 'c.dart';\nimport 'src/d.dart';\nexport 'src/e.dart';\npart 'a.g.dart';\n\nvoid main() {}\n", + }, + added: { + 'lib/b.dart': 'class B {}\n', + 'packages/kit/pubspec.yaml': 'name: kit\n', + 'packages/kit/lib/kit.dart': 'class Kit {}\n', + 'lib/c.dart': 'class C {}\n', + 'lib/src/d.dart': 'class D {}\n', + 'lib/src/e.dart': 'class E {}\n', + // A generated part, written by build_runner after the library was indexed. + 'lib/a.g.dart': "part of 'a.dart';\n\nclass _Generated {}\n", + }, + from: 'lib/a.dart', + expected: ['file lib/b.dart', 'file packages/kit/lib/kit.dart', 'file lib/c.dart', 'file lib/src/d.dart', 'file lib/src/e.dart', 'file lib/a.g.dart'], + }, + { + name: 'TypeScript', + initial: { + 'src/a.ts': "import { X } from './x';\nimport './side';\nimport * as NS from './ns';\nimport { Y } from './dir';\nimport { Z } from './z.js';\nimport type { T } from './types';\nexport function run() { return [X, NS, Y, Z]; }\nexport type U = T;\n", + }, + added: { + 'src/x.ts': 'export const X = 1;\n', + 'src/side.ts': 'console.log(1);\n', + 'src/ns.ts': 'export const member = 1;\n', + 'src/dir/index.ts': 'export const Y = 2;\n', + 'src/z.ts': 'export const Z = 3;\n', + 'src/types.d.ts': 'export interface T { a: number }\n', + }, + from: 'src/a.ts', + expected: ['file src/x.ts', 'file src/side.ts', 'file src/ns.ts', 'file src/dir/index.ts', 'file src/z.ts', 'file src/types.d.ts'], + }, + { + name: 'JavaScript', + initial: { + 'a.js': "import './side';\nimport def from './def.js';\nconst req = require('./req');\nconst lib = require('./lib');\nmodule.exports = { def, req, lib };\n", + }, + added: { + 'side.js': 'console.log(1);\n', + 'def.js': 'export default function def() {}\n', + 'req.js': 'module.exports = 1;\n', + 'lib/index.js': 'module.exports = 2;\n', + }, + from: 'a.js', + expected: ['file side.js', 'file def.js', 'file req.js', 'file lib/index.js'], + }, + { + name: 'C', + initial: { 'src/main.c': '#include "a/b.h"\n#include "c.h"\n#include \nint main(void) { return 0; }\n' }, + added: { 'src/a/b.h': 'int b(void);\n', 'src/c.h': 'int c(void);\n' }, + from: 'src/main.c', + expected: ['file src/a/b.h', 'file src/c.h'], + }, + { + name: 'C++', + initial: { 'src/main.cpp': '#include "util/u.hpp"\n#include "w.h"\nint main() { return 0; }\n' }, + added: { 'src/util/u.hpp': 'namespace util { int u(); }\n', 'src/w.h': 'int w();\n' }, + from: 'src/main.cpp', + expected: ['file src/util/u.hpp', 'file src/w.h'], + }, + { + name: 'Objective-C', + initial: { 'Foo.m': '#import "Bar.h"\n#import "sub/Baz.h"\n@implementation Foo\n@end\n' }, + added: { 'Bar.h': '@interface Bar\n@end\n', 'sub/Baz.h': '@interface Baz\n@end\n' }, + from: 'Foo.m', + expected: ['file Bar.h', 'file sub/Baz.h'], + }, + { + name: 'PHP', + initial: { 'index.php': " ok.\n' }, + added: { 'src/b.hrl': '-define(B, 1).\n', 'include/c.hrl': '-define(C, 1).\n' }, + from: 'src/a.erl', + expected: ['file src/b.hrl', 'file include/c.hrl'], + }, + { + name: 'COBOL', + initial: { + 'MAIN.cbl': ' IDENTIFICATION DIVISION.\n PROGRAM-ID. MAIN.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY CUSTREC.\n PROCEDURE DIVISION.\n STOP RUN.\n', + }, + added: { 'CUSTREC.cpy': ' 01 CUST-REC.\n 05 CUST-ID PIC 9(5).\n' }, + from: 'MAIN.cbl', + expected: ['file CUSTREC.cpy'], + }, + { + name: 'Java (a package wildcard)', + initial: { 'src/com/x/A.java': 'package com.x;\nimport com.z.*;\npublic class A {}\n' }, + added: { 'src/com/z/Z.java': 'package com.z;\npublic class Z {}\n' }, + from: 'src/com/x/A.java', + expected: ['namespace src/com/z/Z.java'], + }, + { + name: 'C# (a using of a namespace declared later)', + initial: { 'A.cs': 'using Foo.Bar;\nnamespace App { class A {} }\n' }, + added: { 'Baz.cs': 'namespace Foo.Bar { class Baz {} }\n' }, + from: 'A.cs', + expected: ['namespace Baz.cs'], + }, + { + name: 'Svelte', + initial: { 'src/App.svelte': "\n\n" }, + added: { 'src/Child.svelte': '

child

\n' }, + from: 'src/App.svelte', + expected: ['file src/Child.svelte'], + }, + { + name: 'Vue', + initial: { 'src/App.vue': "\n\n" }, + added: { 'src/Child.vue': '\n' }, + from: 'src/App.vue', + expected: ['file src/Child.vue'], + }, +]; + +let root = ''; +let cg: CodeGraph | undefined; + +afterEach(() => { + cg?.destroy(); + cg = undefined; + if (root) fs.rmSync(root, { recursive: true, force: true }); + root = ''; +}); + +function write(files: Record): void { + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } +} + +/** ` ` for every `imports` edge out of `file`, plus how many land on one of its own import statements. */ +function importsOf(file: string): { targets: string[]; ownStatements: number } { + const graph = cg!; + const ids = graph.getNodesInFile(file).map((n) => n.id); + const targets = new Set(); + let ownStatements = 0; + for (const edge of graph.getOutgoingEdgesFrom(ids, ['imports'])) { + const target = graph.getNode(edge.target); + if (!target) continue; + if (target.filePath === file) { + if (target.kind === 'import') ownStatements++; + continue; + } + targets.add(`${target.kind} ${target.filePath}`); + } + return { targets: [...targets].sort(), ownStatements }; +} + +describe('sync links an import of a file that appears after the importer', () => { + it.each(CASES)('$name', async (c) => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-sync-import-')); + write(c.initial); + cg = await CodeGraph.init(root, { index: true }); + + // Unresolved, the import parks as failed — not as an edge to itself. + const before = importsOf(c.from); + expect(before.ownStatements).toBe(0); + for (const target of c.expected) expect(before.targets).not.toContain(target); + + write(c.added); + const result = await cg.sync(); + expect(result.filesAdded).toBe(Object.keys(c.added).length); + + // The importer did not change: only the retry of its parked import links it. + const synced = importsOf(c.from); + expect(synced.targets).toEqual(expect.arrayContaining(c.expected)); + expect(synced.ownStatements).toBe(0); + expect(cg.getPendingReferenceCount()).toBe(0); + + await cg.indexAll(); + expect(importsOf(c.from)).toEqual(synced); + }, 60_000); +}); + +describe('a removed file', () => { + it('relinks its unchanged importers when it is restored', async () => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-sync-import-')); + write({ + 'pubspec.yaml': 'name: app\n', + 'lib/a.dart': "import 'package:app/b.dart';\n\nvoid main() {}\n", + 'lib/b.dart': 'class B {}\n', + }); + cg = await CodeGraph.init(root, { index: true }); + expect(importsOf('lib/a.dart').targets).toEqual(['file lib/b.dart']); + + fs.rmSync(path.join(root, 'lib/b.dart')); + expect((await cg.sync()).filesRemoved).toBe(1); + expect(importsOf('lib/a.dart')).toEqual({ targets: [], ownStatements: 0 }); + expect(cg.getPendingReferenceCount()).toBe(0); + + write({ 'lib/b.dart': 'class B {}\n' }); + expect((await cg.sync()).filesAdded).toBe(1); + expect(importsOf('lib/a.dart').targets).toEqual(['file lib/b.dart']); + }, 60_000); +}); + +describe('importPathKeys', () => { + it('names a file and its folder, whole and up to the first dot', () => { + expect(importPathKeys('lib/src/d.dart')).toEqual(['src', 'd.dart', 'd']); + expect(importPathKeys('src/types.d.ts')).toEqual(['src', 'types.d.ts', 'types']); + expect(importPathKeys('pkg/sub/__init__.py')).toEqual(['sub', '__init__.py', '__init__']); + expect(importPathKeys('vendor/gopkg.in/yaml.v3/yaml.go')).toEqual(['yaml.v3', 'yaml', 'yaml.go']); + expect(importPathKeys('main.c')).toEqual(['main.c', 'main']); + expect(importPathKeys('.github/.eslintrc.js')).toEqual(['.github', '.eslintrc.js', '.eslintrc']); + }); +}); + +describe('getRetryableFailedImports', () => { + let db: DatabaseConnection | undefined; + + afterEach(() => { + db?.close(); + db = undefined; + }); + + function setup(): QueryBuilder { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-sync-import-')); + db = DatabaseConnection.initialize(path.join(root, 'test.db')); + const queries = new QueryBuilder(db.getDb()); + const failed = (id: string, referenceName: string, referenceKind: 'imports' | 'calls' = 'imports') => { + const node: Node = { id, kind: 'file', name: id, qualifiedName: id, filePath: id, language: 'dart', + startLine: 1, endLine: 1, startColumn: 0, endColumn: 0, updatedAt: Date.now() }; + queries.insertNode(node); + queries.insertUnresolvedRef({ fromNodeId: id, referenceName, referenceKind, line: 1, column: 0, filePath: id, language: 'dart' }); + queries.markReferencesFailed([{ fromNodeId: id, referenceName, referenceKind }]); + }; + failed('a.dart', 'package:app/b.dart'); + failed('c.dart', '../b.dart'); + failed('d.dart', 'src/b.dart'); + failed('e.dart', 'b.dart'); + failed('f.dart', 'x.b', 'calls'); + failed('g.cs', 'Foo.Bar'); + failed('h.ts', 'useState'); + return queries; + } + + const names = (refs: Array<{ referenceName: string }>) => refs.map((r) => r.referenceName).sort(); + + it('finds an import by the stem of its path or by its whole name, and nothing else', () => { + const queries = setup(); + expect(names(queries.getRetryableFailedImports(['b']))).toEqual(['../b.dart', 'package:app/b.dart', 'src/b.dart']); + expect(names(queries.getRetryableFailedImports(['b.dart']))).toEqual(['b.dart']); + expect(queries.getRetryableFailedImports(['b', 'b.dart', 'b'])).toHaveLength(4); + }); + + it('finds an import by a node name only when the name is not also its tail', () => { + const queries = setup(); + // `using Foo.Bar` waits for the namespace node of that name. + expect(names(queries.getRetryableFailedImports([], ['Foo.Bar', 'useState', 'b']))).toEqual(['Foo.Bar']); + // A path key still reaches a plain name. + expect(names(queries.getRetryableFailedImports(['useState']))).toEqual(['useState']); + }); + + it('skips a key that more failed imports share than the ceiling', () => { + const queries = setup(); + expect(queries.getRetryableFailedImports(['b'], [], 2)).toEqual([]); + expect(names(queries.getRetryableFailedImports(['b', 'b.dart'], [], 2))).toEqual(['b.dart']); + expect(queries.getRetryableFailedImports(['b'], [], 3)).toHaveLength(3); + }); +}); + +describe('schema v12', () => { + let db: DatabaseConnection | undefined; + + afterEach(() => { + vi.restoreAllMocks(); + db?.close(); + db = undefined; + }); + + function fixture(): QueryBuilder { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-sync-import-')); + db = DatabaseConnection.initialize(path.join(root, 'test.db')); + const queries = new QueryBuilder(db.getDb()); + queries.insertNode({ id: 'a', kind: 'file', name: 'a.dart', qualifiedName: 'lib/a.dart', filePath: 'lib/a.dart', + language: 'dart', startLine: 1, endLine: 1, startColumn: 0, endColumn: 0, updatedAt: 0 }); + for (const [referenceName, referenceKind, tail] of [ + ['package:app/b.dart', 'imports', 'dart'], + ['c.h', 'imports', 'h'], + ['lists::map/2', 'calls', 'map'], + ] as const) { + queries.insertUnresolvedRef({ fromNodeId: 'a', referenceName, referenceKind, line: 1, column: 0, filePath: 'lib/a.dart', language: 'dart' }); + db.getDb().prepare("UPDATE unresolved_refs SET status = 'failed', name_tail = ? WHERE reference_name = ?").run(tail, referenceName); + } + return queries; + } + + const tails = () => db!.getDb().prepare('SELECT reference_name AS name, name_tail AS tail FROM unresolved_refs ORDER BY id').all(); + + it('rewrites the tail of a path import parked by an older version, and replays cleanly', () => { + fixture(); + db!.getDb().exec(`DROP INDEX idx_unresolved_failed_import_tail; + DROP INDEX idx_unresolved_failed_import_name; + DELETE FROM schema_versions WHERE version >= 12; + INSERT OR IGNORE INTO schema_versions(version, applied_at, description) VALUES (11, 0, 'legacy fixture');`); + db!.close(); + db = DatabaseConnection.open(path.join(root, 'test.db')); + expect(getCurrentVersion(db.getDb())).toBe(CURRENT_SCHEMA_VERSION); + const indexes = db.getDb().prepare("SELECT name FROM sqlite_master WHERE type = 'index' AND name LIKE 'idx_unresolved_failed_import_%' ORDER BY name").all(); + expect(indexes).toEqual([{ name: 'idx_unresolved_failed_import_name' }, { name: 'idx_unresolved_failed_import_tail' }]); + const migrated = tails(); + expect(migrated).toEqual([ + { name: 'package:app/b.dart', tail: 'b' }, + { name: 'c.h', tail: 'h' }, + { name: 'lists::map/2', tail: 'map' }, + ]); + + db.getDb().exec('DELETE FROM schema_versions WHERE version >= 12'); + runMigrations(db.getDb(), 11); + expect(tails()).toEqual(migrated); + }); + + it('looks failed imports up through their own indexes', () => { + const queries = fixture(); + const prepare = vi.spyOn(db!.getDb(), 'prepare'); + // The fixture's tails are old ones: `dart` finds a row by tail, `c.h` by name. + expect(queries.getRetryableFailedImports(['dart', 'c.h'], ['Foo.Bar'])).toHaveLength(2); + const lookups = prepare.mock.calls.map(([sql]) => sql as string).filter((sql) => sql.includes("reference_kind = 'imports'")); + prepare.mockRestore(); + expect(lookups.length).toBeGreaterThan(0); + for (const sql of lookups) { + const plan = db!.getDb().prepare(`EXPLAIN QUERY PLAN ${sql}`).all('k').map((row) => (row as { detail: string }).detail).join('; '); + expect(plan).toMatch(/USING (COVERING )?INDEX idx_unresolved_failed_import_(tail|name)/); + } + }); +}); diff --git a/docs/viewer-launch-changelog.md b/docs/viewer-launch-changelog.md index 84ed815051..0342462797 100644 --- a/docs/viewer-launch-changelog.md +++ b/docs/viewer-launch-changelog.md @@ -207,6 +207,8 @@ These describe `codegraph ui` and its screens. They were taken out of `## [Unrel - **`codegraph ui` on Windows moves on from a port another program holds.** Windows refuses a port that another program keeps for itself, or one inside a range it reserves, with a different error than a port that is simply in use, so the viewer gave up at the first such port instead of trying the next one, and blamed ports below 1024 needing elevated privileges — a rule Windows doesn't have. It now moves on to the next free port, and when none is left, or the port you pinned with `--port` is refused, it says what Windows did and how to list the reserved ranges. Thanks @ijbranch for the report and @sx4im. (#2299) +- **A file's outside imports are listed in more languages.** The file screen lists the imports that name nothing in your project, like a third-party package or a system header. In C and C++, Objective-C, JavaScript and TypeScript, Python, C#, Lua, R, Solidity, Svelte and Vue, an import that named no file had been linked to its own import statement, so it was listed nowhere. Re-index after upgrading. + ## Entries whose graph and `codegraph_explore` half already shipped The release notes carry a reworded version of each of these. Keep only the viewer half at launch. diff --git a/src/db/migrations.ts b/src/db/migrations.ts index bb7b84bf53..5191519b59 100644 --- a/src/db/migrations.ts +++ b/src/db/migrations.ts @@ -5,11 +5,12 @@ */ import { SqliteDatabase } from './sqlite-adapter'; +import { referenceNameTail } from './reference-tail'; /** * Current schema version */ -export const CURRENT_SCHEMA_VERSION = 11; +export const CURRENT_SCHEMA_VERSION = 12; /** * Migration definition @@ -216,6 +217,27 @@ const migrations: Migration[] = [ `); }, }, + { + version: 12, + description: 'Retry a failed import when sync adds the file it names: path tails and failed-import indexes', + up: (db) => { + // Partial over failed imports, so both stay small. Keep the definitions + // in lockstep with schema.sql. + db.exec(` + CREATE INDEX IF NOT EXISTS idx_unresolved_failed_import_tail ON unresolved_refs(reference_kind, name_tail) WHERE status = 'failed' AND reference_kind = 'imports'; + CREATE INDEX IF NOT EXISTS idx_unresolved_failed_import_name ON unresolved_refs(reference_kind, reference_name) WHERE status = 'failed' AND reference_kind = 'imports'; + `); + // A path import parked before this version carries its dotted tail — + // the extension or a path fragment — which no file's keys match. + // Rewrite it to the path tail a failed import is parked under now. + // Idempotent: a rewritten tail rewrites to itself. + const update = db.prepare('UPDATE unresolved_refs SET name_tail = ? WHERE id = ?'); + const rows = db + .prepare("SELECT id, reference_name FROM unresolved_refs WHERE status = 'failed' AND reference_kind = 'imports' AND reference_name LIKE '%/%'") + .all() as Array<{ id: number; reference_name: string }>; + for (const row of rows) update.run(referenceNameTail(row.reference_name, 'imports'), row.id); + }, + }, ]; /** diff --git a/src/db/queries.ts b/src/db/queries.ts index dd0160319b..b51034dfdc 100644 --- a/src/db/queries.ts +++ b/src/db/queries.ts @@ -22,6 +22,7 @@ import { kindBonus, nameMatchBonus, scorePathRelevance } from '../search/query-u import { parseQuery, boundedEditDistance } from '../search/query-parser'; import { isGeneratedFile } from '../extraction/generated-detection'; import { splitIdentifierSegments } from '../search/identifier-segments'; +import { referenceNameTail } from './reference-tail'; /** * Files that should not be candidates for "dominant file" detection: test/spec @@ -164,21 +165,6 @@ interface UnresolvedRefRow { name_tail: string; } -/** - * Last segment of a (possibly dotted/qualified) reference name — the part a - * new symbol's plain node name could match: 'util.greet' → 'greet', - * 'mod::fn' → 'fn', 'greet' → 'greet'. Written to unresolved_refs.name_tail - * when a ref is marked failed, so the #1240 retry lookup can match dotted - * refs against newly-added node names. - */ -function referenceNameTail(referenceName: string): string { - // Erlang refs carry a written arity (`f/1`, `mod::fn/2` — #1610); the tail a - // new symbol's plain name could match is the arity-less function name. - const base = referenceName.replace(/\/\d{1,3}$/, '') || referenceName; - const idx = Math.max(base.lastIndexOf('.'), base.lastIndexOf(':')); - return idx >= 0 ? base.slice(idx + 1) : base; -} - /** * Convert database row to Node object */ @@ -3739,7 +3725,7 @@ export class QueryBuilder { let changed = 0; const markMany = this.db.transaction((items: typeof refs) => { for (const ref of items) { - changed += stmt.run(referenceNameTail(ref.referenceName), ref.fromNodeId, ref.referenceName, ref.referenceKind).changes; + changed += stmt.run(referenceNameTail(ref.referenceName, ref.referenceKind), ref.fromNodeId, ref.referenceName, ref.referenceKind).changes; } }); markMany(refs); @@ -3754,7 +3740,7 @@ export class QueryBuilder { * can differ per call site (receiver-type inference reads the ref's line), * so a sibling must not inherit this row's failure. */ - markReferencesFailedByRowIds(refs: Array<{ rowId: number; referenceName: string }>): number { + markReferencesFailedByRowIds(refs: Array<{ rowId: number; referenceName: string; referenceKind: string }>): number { if (refs.length === 0) return 0; const stmt = this.db.prepare( "UPDATE unresolved_refs SET status = 'failed', name_tail = ? WHERE id = ?" @@ -3762,7 +3748,7 @@ export class QueryBuilder { let changed = 0; const markMany = this.db.transaction((items: typeof refs) => { for (const ref of items) { - changed += stmt.run(referenceNameTail(ref.referenceName), ref.rowId).changes; + changed += stmt.run(referenceNameTail(ref.referenceName, ref.referenceKind), ref.rowId).changes; } }); markMany(refs); @@ -3824,6 +3810,66 @@ export class QueryBuilder { })); } + /** + * Failed `imports` refs a sync should retry once files appear. An import + * names a file, a folder or a namespace, which the symbol lookup above + * cannot match, so it is found two ways: + * - by `pathKeys` (`importPathKeys` of each added file), as its tail or its + * whole name: `package:app/b.dart` waits for a file named `b.dart`, a + * bare `#include "b.h"` or `require 'db.php'` is the file's whole name; + * - by `names` (the changed files' namespaces and modules), as its whole + * name when its tail is something else: a C# `using Foo.Bar` waits for + * the namespace node `Foo.Bar`. An import whose tail is the name is the + * symbol lookup's, under that lookup's ceiling. + * Same per-name ceiling as {@link getRetryableFailedReferences}, counted + * per key. + */ + getRetryableFailedImports(pathKeys: string[], names: string[] = [], perNameCeiling: number = 500): UnresolvedReference[] { + const failedImports = "status = 'failed' AND reference_kind = 'imports'"; + const lookups = [ + { keys: pathKeys, column: 'name_tail', where: failedImports }, + { keys: pathKeys, column: 'reference_name', where: failedImports }, + { keys: names, column: 'reference_name', where: `${failedImports} AND name_tail != reference_name` }, + ]; + const rows = new Map(); + for (const { keys, column, where } of lookups) { + const unique = [...new Set(keys)].filter((key) => key.length > 0); + // Pass 1: per-key counts, chunked under the SQLite parameter limit. + const retryKeys: string[] = []; + for (let i = 0; i < unique.length; i += SQLITE_PARAM_CHUNK_SIZE) { + const chunk = unique.slice(i, i + SQLITE_PARAM_CHUNK_SIZE); + const placeholders = chunk.map(() => '?').join(','); + const counts = this.db + .prepare(`SELECT ${column} AS key, COUNT(*) AS count FROM unresolved_refs WHERE ${where} AND ${column} IN (${placeholders}) GROUP BY ${column}`) + .all(...chunk) as Array<{ key: string; count: number }>; + for (const row of counts) { + if (row.count <= perNameCeiling) retryKeys.push(row.key); + } + } + // Pass 2: load the surviving rows; a row two lookups find is kept once. + for (let i = 0; i < retryKeys.length; i += SQLITE_PARAM_CHUNK_SIZE) { + const chunk = retryKeys.slice(i, i + SQLITE_PARAM_CHUNK_SIZE); + const placeholders = chunk.map(() => '?').join(','); + const chunkRows = this.db + .prepare(`SELECT * FROM unresolved_refs WHERE ${where} AND ${column} IN (${placeholders})`) + .all(...chunk) as UnresolvedRefRow[]; + for (const row of chunkRows) rows.set(row.id, row); + } + } + + return [...rows.values()].map((row) => ({ + fromNodeId: row.from_node_id, + referenceName: row.reference_name, + referenceKind: row.reference_kind as EdgeKind, + line: row.line, + column: row.col, + candidates: row.candidates ? safeJsonParse(row.candidates, undefined) : undefined, + filePath: row.file_path, + language: row.language as Language, + rowId: row.id, + })); + } + /** * Resolution edges whose TARGET symbol is named one of `names` — the edges a * sync must re-resolve after `names` gained or lost a definition (CG-33). @@ -3935,16 +3981,18 @@ export class QueryBuilder { /** * Distinct node names present in the given files — the symbol names a sync * pass uses to look up retryable failed refs after those files changed. + * `kinds` narrows them to nodes of those kinds. */ - getNodeNamesByFiles(filePaths: string[]): string[] { + getNodeNamesByFiles(filePaths: string[], kinds?: readonly NodeKind[]): string[] { if (filePaths.length === 0) return []; + const kindFilter = kinds ? ` AND kind IN (${kinds.map(() => '?').join(',')})` : ''; const names = new Set(); for (let i = 0; i < filePaths.length; i += SQLITE_PARAM_CHUNK_SIZE) { const chunk = filePaths.slice(i, i + SQLITE_PARAM_CHUNK_SIZE); const placeholders = chunk.map(() => '?').join(','); const rows = this.db - .prepare(`SELECT DISTINCT name FROM nodes WHERE file_path IN (${placeholders})`) - .all(...chunk) as Array<{ name: string }>; + .prepare(`SELECT DISTINCT name FROM nodes WHERE file_path IN (${placeholders})${kindFilter}`) + .all(...chunk, ...(kinds ?? [])) as Array<{ name: string }>; for (const row of rows) names.add(row.name); } return [...names]; diff --git a/src/db/reference-tail.ts b/src/db/reference-tail.ts new file mode 100644 index 0000000000..4c7ed319b0 --- /dev/null +++ b/src/db/reference-tail.ts @@ -0,0 +1,57 @@ +/** + * The keys sync's failed-ref retry (#1240) matches on: the tail a failed ref + * is parked under, and the names a newly added file can be imported as. + * Shared by the query layer, which writes and reads them, and the migration + * that rewrote the tails parked before path imports had one of their own. + */ + +/** + * Last segment of a (possibly dotted/qualified) reference name — the part a + * new symbol's plain node name could match: 'util.greet' → 'greet', + * 'mod::fn' → 'fn', 'greet' → 'greet'. Written to unresolved_refs.name_tail + * when a ref is marked failed, so the #1240 retry lookup can match dotted + * refs against newly-added node names. + * + * An import written as a path names a FILE, so its tail is the path's last + * segment cut at its first dot — `package:app/b.dart` → 'b', `./foo` → 'foo', + * `inc/db.php` → 'db' — the stem {@link importPathKeys} takes from a file + * that could satisfy it. The dotted tail was the extension ('dart', 'php') or + * a path fragment ('/foo'), which no file ever matched. + */ +export function referenceNameTail(referenceName: string, referenceKind?: string): string { + if (referenceKind === 'imports') { + const path = referenceName.replace(/\/+$/, ''); + const slash = path.lastIndexOf('/'); + const stem = slash >= 0 ? fileNameStem(path.slice(slash + 1)) : ''; + // `..` and `.` name a folder only through the importing file's location. + if (!/^\.*$/.test(stem)) return stem; + } + // Erlang refs carry a written arity (`f/1`, `mod::fn/2` — #1610); the tail a + // new symbol's plain name could match is the arity-less function name. + const base = referenceName.replace(/\/\d{1,3}$/, '') || referenceName; + const idx = Math.max(base.lastIndexOf('.'), base.lastIndexOf(':')); + return idx >= 0 ? base.slice(idx + 1) : base; +} + +/** A file or folder name up to its first dot: 'b.dart' → 'b', 'types.d.ts' → 'types', '.eslintrc.js' → '.eslintrc'. */ +function fileNameStem(name: string): string { + const dot = name.indexOf('.', 1); + return dot > 0 ? name.slice(0, dot) : name; +} + +/** + * What an import of the file at `filePath` can be written as, for the failed + * imports a sync that adds the file retries: its name (`b.h`, a bare include) + * and stem (`b`, the tail of `a/b.h`, `./b`, `pkg.b`), and the same two for + * its folder, which an import names for its index file (`./ui` → + * `ui/index.ts`, `pkg` → `pkg/__init__.py`) or as a Go package. + */ +export function importPathKeys(filePath: string): string[] { + const parts = filePath.split('/'); + const keys = new Set(); + for (const name of parts.slice(-2)) { + keys.add(name); + keys.add(fileNameStem(name)); + } + return [...keys]; +} diff --git a/src/db/schema.sql b/src/db/schema.sql index 91ae4805ba..6aff9163c1 100644 --- a/src/db/schema.sql +++ b/src/db/schema.sql @@ -197,6 +197,12 @@ CREATE INDEX IF NOT EXISTS idx_unresolved_file_path ON unresolved_refs(file_path CREATE INDEX IF NOT EXISTS idx_unresolved_from_name ON unresolved_refs(from_node_id, reference_name); CREATE INDEX IF NOT EXISTS idx_unresolved_status ON unresolved_refs(status); CREATE INDEX IF NOT EXISTS idx_unresolved_failed_tail ON unresolved_refs(name_tail) WHERE status = 'failed'; +-- Sync's failed-import retry looks failed imports up by tail and by whole +-- name. The leading reference_kind is what makes the planner pick these over +-- idx_unresolved_failed_tail / idx_unresolved_name, whose per-key averages +-- hide how many failed calls a common tail (`index`, `types`) has. +CREATE INDEX IF NOT EXISTS idx_unresolved_failed_import_tail ON unresolved_refs(reference_kind, name_tail) WHERE status = 'failed' AND reference_kind = 'imports'; +CREATE INDEX IF NOT EXISTS idx_unresolved_failed_import_name ON unresolved_refs(reference_kind, reference_name) WHERE status = 'failed' AND reference_kind = 'imports'; CREATE INDEX IF NOT EXISTS idx_edges_provenance ON edges(provenance); -- Sync's third-file wiring lookup must not scan every synthesized edge. -- CASE short-circuits malformed metadata; keep these expressions identical diff --git a/src/extraction/index.ts b/src/extraction/index.ts index 8b7da4c2cf..4d768ddda9 100644 --- a/src/extraction/index.ts +++ b/src/extraction/index.ts @@ -145,6 +145,8 @@ export interface SyncResult { */ durationMs: number; changedFilePaths?: string[]; + /** The part of `changedFilePaths` that was not indexed before this sync. */ + addedFilePaths?: string[]; /** Paths not absorbed because reading or extraction failed; retain for status/retry. */ failedFilePaths?: string[]; /** @@ -3302,6 +3304,7 @@ export class ExtractionOrchestrator { let filesRemoved = 0; let nodesUpdated = 0; const changedFilePaths: string[] = []; + const addedFilePaths: string[] = []; // `file\0name` definition pairs for the files this sync touches, sampled // BEFORE their nodes are replaced/deleted. Compared against the post-store // pairs below to derive `definitionDelta` (CG-33). @@ -3476,6 +3479,7 @@ export class ExtractionOrchestrator { onFileChange?.(filePath, content); filesToIndex.push(filePath); changedFilePaths.push(filePath); + addedFilePaths.push(filePath); filesAdded++; } else if (tracked.contentHash !== contentHash || neverParsed) { onFileChange?.(filePath, content); @@ -3545,6 +3549,7 @@ export class ExtractionOrchestrator { nodesUpdated, durationMs: Date.now() - startTime, changedFilePaths: changedFilePaths.length > 0 ? changedFilePaths : undefined, + ...(addedFilePaths.length > 0 ? { addedFilePaths } : {}), ...(failedFilePaths.length > 0 ? { failedFilePaths } : {}), definitionDelta: definitionDelta.length > 0 ? definitionDelta : undefined, }; diff --git a/src/index.ts b/src/index.ts index 7e7a1dbf9d..4d852af522 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,6 +30,7 @@ import { import { DatabaseConnection, getDatabasePath, removeDatabaseFiles } from './db'; import { WalCheckpointValve, resolveWalValveMb } from './db/wal-valve'; import { QueryBuilder } from './db/queries'; +import { importPathKeys } from './db/reference-tail'; import { isInitialized, createDirectory, @@ -989,6 +990,20 @@ export class CodeGraph { const retryable = this.queries.getRetryableFailedReferences( this.queries.getNodeNamesByFiles(result.changedFilePaths) ); + // A failed import waits for a file, a folder or a namespace, not a + // symbol: `package:app/b.dart` for a file named `b.dart`, `./ui` + // for `ui/index.ts`, `using Foo.Bar` for that namespace's node. + // Look those up by what the ADDED files can be imported as (a + // modified file was already there for any import of it), and by + // the namespaces and modules the changed files declare. + const retryRows = new Set(retryable.map((ref) => ref.rowId)); + const importRetry = this.queries.getRetryableFailedImports( + (result.addedFilePaths ?? []).flatMap(importPathKeys), + this.queries.getNodeNamesByFiles(result.changedFilePaths, ['namespace', 'module']) + ); + for (const ref of importRetry) { + if (!retryRows.has(ref.rowId)) retryable.push(ref); + } if (retryable.length > 0) { options.onProgress?.({ phase: 'resolving', diff --git a/src/resolution/import-resolver.ts b/src/resolution/import-resolver.ts index 4c3d5570dc..bf5dab41b0 100644 --- a/src/resolution/import-resolver.ts +++ b/src/resolution/import-resolver.ts @@ -905,6 +905,16 @@ export function isDartImportRef(ref: UnresolvedRef): boolean { return ref.language === 'dart' && ref.referenceKind === 'imports'; } +/** + * Is this a Lua / Luau `require`? It names a module file (see + * resolveLuaRequire) or a module from outside the project, never a symbol: + * the name-matcher bound `local lfs = require "lfs"` and `local Signal = + * require(script.Parent.Signal)` to the local each is assigned to. + */ +export function isLuaRequireRef(ref: UnresolvedRef): boolean { + return (ref.language === 'lua' || ref.language === 'luau') && ref.referenceKind === 'imports'; +} + /** * Resolve a PHP include/require path to a project-relative file path. * diff --git a/src/resolution/index.ts b/src/resolution/index.ts index 88451f6193..41a15843ec 100644 --- a/src/resolution/index.ts +++ b/src/resolution/index.ts @@ -29,7 +29,7 @@ import { clearDartLibraryMemos } from './dart-libraries'; import { clearVbnetReceiverMemos, isVbMemberRead, isVbPathCall, matchVbMemberRead, matchVbPathCall } from './vbnet-receivers'; import { gateTypeParameter, clearTypeParameterMemos } from './type-parameters'; import { gateDartLocal, clearDartLocalScopeMemos } from './dart-local-scope'; -import { resolveViaImport, resolvePhpImportedStaticCall, resolvePhpQualifiedClassRef, resolveJvmImport, extractImportMappings, extractReExports, loadCppIncludeDirs, isPhpIncludePathRef, isCobolCopybookRef, isNixPathImportRef, isDartImportRef, isJsPathImportRef, isBoundToOutOfRepoImport, clearImportResolverMemos, resolveImportPath, isExternalImport } from './import-resolver'; +import { resolveViaImport, resolvePhpImportedStaticCall, resolvePhpQualifiedClassRef, resolveJvmImport, extractImportMappings, extractReExports, loadCppIncludeDirs, isPhpIncludePathRef, isCobolCopybookRef, isNixPathImportRef, isDartImportRef, isLuaRequireRef, isJsPathImportRef, isBoundToOutOfRepoImport, clearImportResolverMemos, resolveImportPath, isExternalImport } from './import-resolver'; import { ResolverPool, minRefsForPool, shouldEngageAdaptively } from './resolver-pool'; import { resolveAliasBinding } from './alias-binding'; import { detectFrameworks } from './frameworks'; @@ -1359,8 +1359,9 @@ export class ReferenceResolver { // Nix static path imports are file references for the same reason — // falling through would let "./x.nix" name-match an unrelated node. So // is a Dart import's URI: `package:flutter/foundation.dart` matched by - // its last segment went to riverpod's own foundation.dart. - if (isPhpIncludePathRef(ref) || isCobolCopybookRef(ref) || isNixPathImportRef(ref) || isDartImportRef(ref) || ref.language === 'terraform') { + // its last segment went to riverpod's own foundation.dart. And a Lua + // `require`, whose leaf matched the local it is assigned to. + if (isPhpIncludePathRef(ref) || isCobolCopybookRef(ref) || isNixPathImportRef(ref) || isDartImportRef(ref) || isLuaRequireRef(ref) || ref.language === 'terraform') { return candidates.length > 0 ? candidates.reduce((best, curr) => curr.confidence > best.confidence ? curr : best @@ -1544,13 +1545,13 @@ export class ReferenceResolver { * ref's line), so a sibling must not inherit this row's failure (#1269). */ private static partitionFailedCleanup(unresolved: UnresolvedRef[]): { - byRowId: Array<{ rowId: number; referenceName: string }>; + byRowId: Array<{ rowId: number; referenceName: string; referenceKind: string }>; legacyKeys: Array<{ fromNodeId: string; referenceName: string; referenceKind: string }>; } { - const byRowId: Array<{ rowId: number; referenceName: string }> = []; + const byRowId: Array<{ rowId: number; referenceName: string; referenceKind: string }> = []; const legacyKeys: Array<{ fromNodeId: string; referenceName: string; referenceKind: string }> = []; for (const r of unresolved) { - if (r.rowId != null) byRowId.push({ rowId: r.rowId, referenceName: r.referenceName }); + if (r.rowId != null) byRowId.push({ rowId: r.rowId, referenceName: r.referenceName, referenceKind: r.referenceKind }); else legacyKeys.push({ fromNodeId: r.fromNodeId, referenceName: r.referenceName, @@ -2993,7 +2994,8 @@ export class ReferenceResolver { * framework, import, name-match, chain, CFML component path. * * For `imports`: the target must be importable. A member that only exists - * inside a type never is. + * inside a type never is, and neither is the import statement the reference + * was written in. * * For `extends`/`implements`, it cannot be describing a real supertype when: * @@ -3029,9 +3031,14 @@ export class ReferenceResolver { } // An `imports` reference names something importable — never a member that - // only exists inside a type. + // only exists inside a type, nor its own import statement. A module path + // that names no file (`./missing`, `stdio.h`, `pkg.mod`, a C# `using` of + // an outside namespace) reaches the statement by its qualified name; as an + // edge to itself it is never retried, while a failed ref is retried by the + // sync that adds the file it names. if (ref.referenceKind === 'imports') { const target = this.nodeById(result.targetNodeId); + if (target?.kind === 'import' && target.filePath === ref.filePath) return null; return target && !isImportableKind(target.kind) ? null : result; } diff --git a/src/resolution/name-matcher.ts b/src/resolution/name-matcher.ts index d2f07797e7..d86047ebd3 100644 --- a/src/resolution/name-matcher.ts +++ b/src/resolution/name-matcher.ts @@ -7206,6 +7206,8 @@ export function matchByQualifiedName( let candidates = keepForRef(context.getNodesByQualifiedName(ref.referenceName)); // A C# `using X.Y;` names a namespace: one the project declares, else it is // the file's own (external) using — never another file's using of that name. + // That own using ends the lookup here, and resolveOne drops it (an import + // never names its own statement), so the ref parks as failed. if (ref.language === 'csharp' && ref.referenceKind === 'imports') { const namespaces = candidates.filter((n) => n.kind === 'namespace'); candidates = namespaces.length > 0 ? preferCallSiteFile(namespaces, ref.filePath).slice(0, 1) From 460f6b8a1a550555572a32e604186da2dc16ec31 Mon Sep 17 00:00:00 2001 From: Aaron Queen Date: Tue, 6 Oct 2026 18:45:28 -0600 Subject: [PATCH 21/23] fix(dart): locate multiline receivers at their token position --- __tests__/kernel-import-dart-identity.test.ts | 16 +++++++++ __tests__/receiver-diagnostics.test.ts | 4 +-- codegraph-kernel/src/resolve/dart_calls.rs | 33 ++++++++++++++++++- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/__tests__/kernel-import-dart-identity.test.ts b/__tests__/kernel-import-dart-identity.test.ts index 8d0519d5b7..9064191f7f 100644 --- a/__tests__/kernel-import-dart-identity.test.ts +++ b/__tests__/kernel-import-dart-identity.test.ts @@ -34,6 +34,22 @@ it('parks matching missing includes in both files, then retries both when the he }); const cases = [ + { + name: 'a multiline imported receiver resolves on its own source line', + files: { + 'lib/main.dart': "import 'helper.dart' as kit;\nvoid run() { /* 🦊 */ kit\n .helper(); }\n", + 'lib/helper.dart': 'void helper() {}\n', + }, + from: 'run', kind: 'calls', target: 'helper', targetFile: 'lib/helper.dart', + }, + { + name: 'a multiline local receiver shadows the imported prefix', + files: { + 'lib/main.dart': "import 'helper.dart' as kit;\nvoid run(Object kit) { /* 🦊 */ kit\n .helper(); }\n", + 'lib/helper.dart': 'void helper() {}\n', + }, + from: 'run', kind: 'calls', target: 'helper', targetFile: 'lib/helper.dart', absent: true, + }, { name: 'prefixed instance chain preserves the constructor library', files: { diff --git a/__tests__/receiver-diagnostics.test.ts b/__tests__/receiver-diagnostics.test.ts index 251ed5f442..6d2e111f74 100644 --- a/__tests__/receiver-diagnostics.test.ts +++ b/__tests__/receiver-diagnostics.test.ts @@ -16,12 +16,12 @@ function setup() { const raw = db.getDb(); const queries = new QueryBuilder(raw); queries.insertNodes([{ id: 'caller', name: 'caller', qualifiedName: 'caller', kind: 'function', language: 'typescript', filePath: 'app.ts', startLine: 1, endLine: 5, startColumn: 0, endColumn: 0, updatedAt: 0 }]); - queries.insertUnresolvedRefsBatch([1, 2].map(line => ({ fromNodeId: 'caller', referenceName: 'unknown.run', referenceKind: 'calls', referenceKind: 'calls', filePath: 'app.ts', language: 'typescript', line, column: 0 }))); + queries.insertUnresolvedRefsBatch([1, 2].map(line => ({ fromNodeId: 'caller', referenceName: 'unknown.run', referenceKind: 'calls', filePath: 'app.ts', language: 'typescript', line, column: 0 }))); return { raw, queries }; } it('migrates existing unresolved rows without changing their retry state', () => { const { raw, queries } = setup(); - queries.markReferencesFailed([{ fromNodeId: 'caller', referenceName: 'unknown.run', referenceKind: 'calls', referenceKind: 'calls' }]); + queries.markReferencesFailed([{ fromNodeId: 'caller', referenceName: 'unknown.run', referenceKind: 'calls' }]); raw.exec('ALTER TABLE unresolved_refs DROP COLUMN failure_reason'); raw.exec('DELETE FROM schema_versions WHERE version > 11'); runMigrations(raw, 11); diff --git a/codegraph-kernel/src/resolve/dart_calls.rs b/codegraph-kernel/src/resolve/dart_calls.rs index 8897edd479..b6f71f96a3 100644 --- a/codegraph-kernel/src/resolve/dart_calls.rs +++ b/codegraph-kernel/src/resolve/dart_calls.rs @@ -689,9 +689,13 @@ impl KernelResolver { }; before = i; } + let Some((line, column)) = token_position(&source, t[before].start) else { + return Ok(Some(ResolveOutcome::unresolved())); + }; let site = ResolveRefIn { reference_name: t[before].text.clone(), - column: (t[before].start - start) as i64, + line, + column, ..r.clone() }; if let Some((prefix, tail)) = r.reference_name.split_once('.') { @@ -925,3 +929,30 @@ fn dart_expr_end(t: &[DartToken]) -> usize { } t.len() } + +// Token offsets refer to the normalized whole file; reference columns use UTF-16. +fn token_position(source: &SourceFile, byte: usize) -> Option<(i64, i64)> { + let mut start = 0; + for (row, line) in source.iter().enumerate() { + if byte <= start + line.len() { + let prefix = line.get(..byte - start)?; + return Some((row as i64 + 1, names::utf16_len(prefix) as i64)); + } + start += line.len() + 1; + } + None +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn receiver_position_uses_its_line_and_utf16_column() { + let source = SourceFile::new(vec!["// header".into(), "/* 🦊 */ kit".into(), " .helper();".into()]); + let byte = source.text().find("kit").unwrap(); + assert_eq!(token_position(&source, byte), Some((2, 9))); + assert_eq!(token_position(&source, source.text().find("helper").unwrap()), Some((3, 3))); + assert_eq!(token_position(&source, source.text().len() + 1), None); + } +} From 2a3b0912309d001172fad4ce6cfccc6f78070942 Mon Sep 17 00:00:00 2001 From: Aaron Queen Date: Tue, 6 Oct 2026 18:50:19 -0600 Subject: [PATCH 22/23] fix(dart): contain library directive reads within the project --- README.md | 2 +- __tests__/kernel-import-dart-identity.test.ts | 18 ++++++++++++++++++ codegraph-kernel/src/resolve/dart_libraries.rs | 13 ++++++++++++- site/src/content/docs/reference/languages.md | 2 +- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 704aaaae99..b2c7fd9c14 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ C# property accessors and expression-bodied properties contribute calls and refe C# field and property initializers retain their calls and references under the member that owns them. Target-typed `new()` resolves relative declared types through enclosing namespaces and honors `global::` qualification without requiring a redundant `using`. VB.NET resolves typed receivers, enclosing and inherited members, and field or property reads through values and Shared types without choosing unrelated project declarations. Names beginning with keywords, such as `SharedCache`, `Dimension` and `NewItem`, retain their declarations. -Go imports follow the nearest indexed module and the longest matching module path, including module changes during incremental sync. Unexported receivers and embedded methods stay in their declaring package. Dart imports, exports and part directives follow their library URIs and visibility rules. Calls through import prefixes, annotations and member chains follow the visible declaration and written receiver types, including explicit generic lookup types. Parameters and locals shadow bare calls. Top-level and field initializers contribute calls; const constructors, redirecting factories and annotated members retain their declarations and dartdoc. Getter reads become calls only when the receiver type reaches that getter and no nearer field in the visible class hierarchy overrides it; enum extensions and type-position references participate in resolution. Rust enum-variant values retain their enum references. +Go imports follow the nearest indexed module and the longest matching module path, including module changes during incremental sync. Unexported receivers and embedded methods stay in their declaring package. Dart imports, exports and part directives follow their library URIs and visibility rules. Library directive reads stay inside the indexed project, including resolved symlink targets. Calls through import prefixes, annotations and member chains follow the visible declaration and written receiver types, including explicit generic lookup types. Parameters and locals shadow bare calls. Top-level and field initializers contribute calls; const constructors, redirecting factories and annotated members retain their declarations and dartdoc. Getter reads become calls only when the receiver type reaches that getter and no nearer field in the visible class hierarchy overrides it; enum extensions and type-position references participate in resolution. Rust enum-variant values retain their enum references. Named JavaScript and TypeScript object literals own their function members, including local objects and classic-script global assignments. Member calls follow the visible object; loop-local objects stay within their scope. Destructured member calls resolve across lines while preserving the source binding at the destructure declaration; unrelated bare names stay unresolved. Vue template expressions contribute calls to script bindings while preserving component ownership. Encoded attribute expressions retain their original source positions, and template-local bindings stay within their scope. diff --git a/__tests__/kernel-import-dart-identity.test.ts b/__tests__/kernel-import-dart-identity.test.ts index 9064191f7f..e09edf7e13 100644 --- a/__tests__/kernel-import-dart-identity.test.ts +++ b/__tests__/kernel-import-dart-identity.test.ts @@ -115,3 +115,21 @@ describe('native Dart declaration identity and source boundaries', () => { } }); }); + +// Keep the external fixture in the test's own parent directory. +async function checkExternalDirective(mode: 'parent-path' | 'symlink'): Promise { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-dart-uri-boundary-')); + write({ + 'project/pubspec.yaml': 'name: app\n', + 'project/lib/secret.dart': 'void secret() {}\n', + 'project/lib/main.dart': `import 'package:app/${mode === 'parent-path' ? '../../escape.dart' : 'escape.dart'}';\nvoid run() { secret(); }\n`, + 'escape.dart': "export 'package:app/secret.dart';\n", + }); + if (mode === 'symlink') fs.symlinkSync(path.join(root, 'escape.dart'), path.join(root, 'project/lib/escape.dart')); + cg = await CodeGraph.init(path.join(root, 'project'), { index: true }); + const source = cg.getNodesInFile('lib/main.dart').find(n => n.name === 'run')!; + const targets = cg.getOutgoingEdgesFrom([source.id], ['calls']).map(e => cg!.getNode(e.target)!); + expect(targets.map(n => `${n.filePath}:${n.name}`)).not.toContain('lib/secret.dart:secret'); +} +it('refuses Dart package directives outside the indexed root through parent paths', () => checkExternalDirective('parent-path')); +it.runIf(process.platform !== 'win32')('refuses Dart package directives outside the indexed root through symlinks', () => checkExternalDirective('symlink')); diff --git a/codegraph-kernel/src/resolve/dart_libraries.rs b/codegraph-kernel/src/resolve/dart_libraries.rs index e675185ec3..3c0c89c0cb 100644 --- a/codegraph-kernel/src/resolve/dart_libraries.rs +++ b/codegraph-kernel/src/resolve/dart_libraries.rs @@ -265,7 +265,17 @@ impl KernelResolver { if let Some(d) = self.dart_libraries.directives.get(file) { return d.clone(); } - let d = self.read_file(file).map(|s| directives(s.text())); + let d = (|| { + if !lexical_path_within_root(&self.root_abs, file) { + return None; + } + let root = std::fs::canonicalize(&self.root_abs).ok()?; + let path = std::fs::canonicalize(pos_resolve(&self.root_abs, file)).ok()?; + if !path.starts_with(root) { + return None; + } + self.read_file(file).map(|s| directives(s.text())) + })(); self.dart_libraries .directives .insert(file.into(), d.clone()); @@ -435,6 +445,7 @@ impl KernelResolver { return chosen .iter() .map(|p| pos_normalize(&pos_join(&pos_join(&p.1, "lib"), rest))) + .filter(|path| lexical_path_within_root(&self.root_abs, path)) .collect(); } if re!(r"^[A-Za-z][\w+.-]*:").is_match(uri) { diff --git a/site/src/content/docs/reference/languages.md b/site/src/content/docs/reference/languages.md index 2ee0e4091b..43d25cda1e 100644 --- a/site/src/content/docs/reference/languages.md +++ b/site/src/content/docs/reference/languages.md @@ -9,7 +9,7 @@ C# property accessors and expression-bodied properties contribute calls and refe C# field and property initializers retain their calls and references under the member that owns them. Target-typed `new()` resolves relative declared types through enclosing namespaces and honors `global::` qualification without requiring a redundant `using`. VB.NET resolves typed receivers, enclosing and inherited members, and field or property reads through values and Shared types without choosing unrelated project declarations. Names beginning with keywords, such as `SharedCache`, `Dimension` and `NewItem`, retain their declarations. -Go imports follow the nearest indexed module and the longest matching module path, including module changes during incremental sync. Unexported receivers and embedded methods stay in their declaring package. Dart imports, exports and part directives follow their library URIs and visibility rules. Calls through import prefixes, annotations and member chains follow the visible declaration and written receiver types, including explicit generic lookup types. Parameters and locals shadow bare calls. Top-level and field initializers contribute calls; const constructors, redirecting factories and annotated members retain their declarations and dartdoc. Getter reads become calls only when the receiver type reaches that getter and no nearer field in the visible class hierarchy overrides it; enum extensions and type-position references participate in resolution. Rust enum-variant values retain their enum references. +Go imports follow the nearest indexed module and the longest matching module path, including module changes during incremental sync. Unexported receivers and embedded methods stay in their declaring package. Dart imports, exports and part directives follow their library URIs and visibility rules. Library directive reads stay inside the indexed project, including resolved symlink targets. Calls through import prefixes, annotations and member chains follow the visible declaration and written receiver types, including explicit generic lookup types. Parameters and locals shadow bare calls. Top-level and field initializers contribute calls; const constructors, redirecting factories and annotated members retain their declarations and dartdoc. Getter reads become calls only when the receiver type reaches that getter and no nearer field in the visible class hierarchy overrides it; enum extensions and type-position references participate in resolution. Rust enum-variant values retain their enum references. Named JavaScript and TypeScript object literals own their function members, including local objects and classic-script global assignments. Member calls follow the visible object; loop-local objects stay within their scope. Destructured member calls resolve across lines while preserving the source binding at the destructure declaration; unrelated bare names stay unresolved. Vue template expressions contribute calls to script bindings while preserving component ownership. Encoded attribute expressions retain their original source positions, and template-local bindings stay within their scope. From 81229ef0443e591c3bb9d966cf1fe2edd3b82433 Mon Sep 17 00:00:00 2001 From: Aaron Queen Date: Tue, 6 Oct 2026 19:39:03 -0600 Subject: [PATCH 23/23] fix(dart): bound local scopes across bracket strings --- CHANGELOG.md | 6 +----- __tests__/fixtures/golden/torture-multilang.dump | 8 ++++---- .../kernel-parity/TortureAnnotatedComments.dart | 6 +++--- .../kernel-parity/TortureAnnotatedDocs.dart | 6 +++--- __tests__/kernel-import-dart-identity.test.ts | 15 +++++++++++++++ codegraph-kernel/src/resolve/dart_local.rs | 2 +- 6 files changed, 27 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0a2c448c0..5e83067244 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -102,7 +102,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Python closures no longer link calls or method values to a captured receiver type when later replacement makes that type uncertain. - Python receiver calls no longer link to a stale type after same-line replacement when statement order cannot establish a reliable type. -- JavaScript and TypeScript store actions exported on a later line remain indexed with LF, CRLF or CR line endings. +- JavaScript and TypeScript store actions exported on a later line remain indexed with LF, CRLF or CR line endings. Re-index JavaScript and TypeScript projects after upgrading. - Incremental Go sync invalidates nearest-module caches after a module is renamed, removed or added. - JavaScript loop-local object paths stay local, and scoped destructured member calls resolve across source lines while preserving their declaration-site source binding in scripts and single-file components. @@ -367,14 +367,10 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In JavaScript and TypeScript, the functions written inside a named object literal are now symbols of their own even when the object isn't exported: a plain `const api = { load() {…} }`, an object declared inside an IIFE or a function, and a namespace hung on the page or on another object, like `window.App = { init() {…} }`, `App.utils = {…}` or `dw_page = {…}`. Calls such as `api.load()`, `window.App.init()`, `App.utils.pad()`, a sibling's `this.render()`, and `App.init()` from another script on the page now reach them, the calls made inside a member belong to that member instead of the object, and a bare `init()` is no longer taken for `App.init`, so script-tag apps no longer lose most of their code from `callers` and impact. A member's qualified name now carries its object, exported or not (`api::load`, `window.App::init`), so asking for `App.init` finds it. Re-index JavaScript and TypeScript projects after upgrading. Thanks @tkhoaaa for the report and @danusha2345. (#2300) -- In VB.NET, a type name is looked up the way VB.NET does it — through the namespaces around it, the file's and project's `Imports` (aliases included), and the caller's own project — so a class declared in several namespaces or projects no longer draws every call to whichever copy was indexed first, and two candidates nothing tells apart get no link at all. - - Indexing large Python projects is much faster again and needs less memory: since 1.6.2, resolving Python references re-read source files over and over, so a project the size of CPython took several times as long to index. The graph it builds is unchanged. Thanks @bompus for the report. (#2332) - Indexing a project that includes large bundled JavaScript files, such as a copy of pdf.js or d3, is fast again: since 1.6.2, resolving the calls in a JavaScript or TypeScript file re-read the file's text above each call, so a single bundled library could add many seconds to an index. The graph it builds is unchanged. Thanks @bompus for the report. (#2334) -- In JavaScript and TypeScript files with Windows (CRLF) line endings, as a Windows checkout usually has them, a store exported on a later line, like `const useStore = create(…)` followed by `export default useStore;`, now has its actions indexed, as it already did with Unix line endings. Before, those actions were missing from the graph on Windows, so their callers and impact came back empty. Re-index JavaScript and TypeScript projects after upgrading. - - In VB.NET, a name that begins with a keyword, like `SharedCache`, `Dimension`, `PublicKey` or `FriendlyName`, is now indexed whole, and a method like `Sub NewItem()` is no longer taken for a constructor. Before, the keyword was cut off (`Cache`, `ension`, `Key`) or the declaration was lost, and a line in a method that starts with such a name, like `Constants.Reload()` or `ConstVBV.Value = False`, was misread as a declaration, so reads of and calls to these names didn't link. A `Private Protected` member now counts as private instead of public. Re-index VB.NET projects after upgrading. - In JavaScript and TypeScript, a store whose name contains a `$`, like `const items$ = create(…)` exported on a later line with `export default items$;`, now has its actions indexed. Before, they could be missing from the graph, for example in a file that also had a syntax error. Re-index JavaScript and TypeScript projects after upgrading. diff --git a/__tests__/fixtures/golden/torture-multilang.dump b/__tests__/fixtures/golden/torture-multilang.dump index d66bf9e07c..30f41ddf8c 100644 --- a/__tests__/fixtures/golden/torture-multilang.dump +++ b/__tests__/fixtures/golden/torture-multilang.dump @@ -841,7 +841,7 @@ {"id":"function:a946d3f4be94fcb7a892061e107ac66a","kind":"function","name":"annotated","qualified_name":"annotated","file_path":"torture.dart","language":"dart","start_line":21,"end_line":21,"start_column":0,"end_column":16,"docstring":"Kept past the annotation.","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:aa19335691696f0f1d72ddc2c8dec6cb","kind":"function","name":"braced_fn","qualified_name":"braced_fn","file_path":"torture.R","language":"r","start_line":47,"end_line":47,"start_column":2,"end_column":27,"docstring":null,"signature":"()","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:aa3f62fd230842e75396597772ab06aa","kind":"function","name":"varargFn","qualified_name":"com.example.torture::varargFn","file_path":"torture.kt","language":"kotlin","start_line":249,"end_line":249,"start_column":0,"end_column":31,"docstring":null,"signature":"(vararg xs: Int)","visibility":"public","is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"function:ab1059e06181b06b9c3ef776dfa5b44c","kind":"function","name":"lineBelow","qualified_name":"lineBelow","file_path":"TortureAnnotatedComments.dart","language":"dart","start_line":16,"end_line":16,"start_column":0,"end_column":16,"docstring":"ignore: must_call_super","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"function:ab1059e06181b06b9c3ef776dfa5b44c","kind":"function","name":"lineBelow","qualified_name":"lineBelow","file_path":"TortureAnnotatedComments.dart","language":"dart","start_line":16,"end_line":16,"start_column":0,"end_column":16,"docstring":"ignore: must_call_super // Parser fixture for annotation/comment scanning; no analyzer runs.","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:ab6308c2c4505606bd271827551f5081","kind":"function","name":"topFn","qualified_name":"topFn","file_path":"TortureMini.dart","language":"dart","start_line":9,"end_line":28,"start_column":0,"end_column":27,"docstring":"Doc line one.\nDoc line two.","signature":"void (int a, String b)","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:abfca256cd004da15d4b8a5afe1c4aa5","kind":"function","name":"build","qualified_name":"build","file_path":"TortureInitializers.dart","language":"dart","start_line":8,"end_line":8,"start_column":0,"end_column":14,"docstring":null,"signature":"Widget ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Widget"} {"id":"function:ac149a211bcc98a9a2da7a30d6dc54e4","kind":"function","name":"assigned","qualified_name":"assigned","file_path":"TortureFnrefDart.dart","language":"dart","start_line":1,"end_line":1,"start_column":0,"end_column":15,"docstring":null,"signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1148,7 +1148,7 @@ {"id":"method:1ef9b6f1c835a12c47628cd82674efc7","kind":"method","name":"fast","qualified_name":"WidgetS::fast","file_path":"torture.scala","language":"scala","start_line":60,"end_line":60,"start_column":2,"end_column":29,"docstring":null,"signature":"(): Int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} {"id":"method:1ffd0a19e129180328c64d31cef01754","kind":"method","name":"create","qualified_name":"M::create","file_path":"torture.lua","language":"lua","start_line":35,"end_line":38,"start_column":0,"end_column":3,"docstring":null,"signature":"(n)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:208f69704420985d481e2924b01f1c33","kind":"method","name":"setActive","qualified_name":"com.example.torture::LombokBean::setActive","file_path":"Torture.java","language":"java","start_line":111,"end_line":111,"start_column":18,"end_column":26,"docstring":"Lombok-generated (@Data)","signature":"void setActive(boolean isActive)","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":"[\"lombok\"]","type_parameters":null,"return_type":null} -{"id":"method:20afc89b2067be372d79afa78275ba60","kind":"method","name":"method","qualified_name":"C::method","file_path":"TortureAnnotatedComments.dart","language":"dart","start_line":68,"end_line":68,"start_column":2,"end_column":15,"docstring":"ignore: must_call_super","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"method:20afc89b2067be372d79afa78275ba60","kind":"method","name":"method","qualified_name":"C::method","file_path":"TortureAnnotatedComments.dart","language":"dart","start_line":68,"end_line":68,"start_column":2,"end_column":15,"docstring":"ignore: must_call_super // Parser fixture for annotation/comment scanning; no analyzer runs.","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:212bbb3d2db529e2eb6e8fdd590a7e89","kind":"method","name":"extMethod","qualified_name":"WidgetExt::extMethod","file_path":"TortureMini.dart","language":"dart","start_line":59,"end_line":59,"start_column":2,"end_column":18,"docstring":null,"signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:21bccd402845e4d14582f7b3f06c7f98","kind":"method","name":"handler","qualified_name":"CallSites::handler","file_path":"torture.scala","language":"scala","start_line":153,"end_line":153,"start_column":2,"end_column":26,"docstring":null,"signature":"(): Unit","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Unit"} {"id":"method:2328804ffd8c133163e907a0d7dac30c","kind":"method","name":"~Session","qualified_name":"app::net::Session::~Session","file_path":"torture.cpp","language":"cpp","start_line":41,"end_line":41,"start_column":2,"end_column":23,"docstring":null,"signature":"()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1304,7 +1304,7 @@ {"id":"method:773629ccbc9f2957a2e43a4c6e776929","kind":"method","name":"flow_control","qualified_name":"Documented::flow_control","file_path":"torture.rb","language":"ruby","start_line":162,"end_line":182,"start_column":2,"end_column":5,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:77e06442f583b8a728ecb572f6730060","kind":"method","name":"hook","qualified_name":"WidgetS::hook","file_path":"torture.scala","language":"scala","start_line":62,"end_line":62,"start_column":2,"end_column":33,"docstring":null,"signature":"(): Unit","visibility":"protected","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Unit"} {"id":"method:77f181371bcfbbcf69325e830e407276","kind":"method","name":"beta","qualified_name":"H2::beta","file_path":"TortureFnref.scala","language":"scala","start_line":17,"end_line":17,"start_column":2,"end_column":23,"docstring":null,"signature":"(): Unit","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Unit"} -{"id":"method:784ceb2822a9f05f7ae8b4d54cd8ed5b","kind":"method","name":"trailingComment","qualified_name":"C::trailingComment","file_path":"TortureAnnotatedDocs.dart","language":"dart","start_line":107,"end_line":107,"start_column":2,"end_column":24,"docstring":"ignore: must_call_super","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"method:784ceb2822a9f05f7ae8b4d54cd8ed5b","kind":"method","name":"trailingComment","qualified_name":"C::trailingComment","file_path":"TortureAnnotatedDocs.dart","language":"dart","start_line":107,"end_line":107,"start_column":2,"end_column":24,"docstring":"ignore: must_call_super // Parser fixture for annotation/comment scanning; no analyzer runs.","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:78be4d08fb33c0be65e429ee23a0d708","kind":"method","name":"_","qualified_name":"ProviderT::_","file_path":"TortureConstCtors.dart","language":"dart","start_line":16,"end_line":16,"start_column":2,"end_column":31,"docstring":null,"signature":"({T? value})","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"ProviderT"} {"id":"method:7a8afa1e8551b1d529469ec5c6dd2d56","kind":"method","name":"add","qualified_name":"PrivateDelegator::add","file_path":"torture.tsx","language":"tsx","start_line":241,"end_line":241,"start_column":2,"end_column":46,"docstring":null,"signature":"(x: string): void","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:7ab2515c60162c14f11915cbd4312d56","kind":"method","name":"local","qualified_name":"Boot::local","file_path":"TortureGiven.scala","language":"scala","start_line":19,"end_line":19,"start_column":2,"end_column":24,"docstring":null,"signature":"(): Unit","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Unit"} @@ -1495,7 +1495,7 @@ {"id":"method:e947ab8444253c3743504176397bb986","kind":"method","name":"create","qualified_name":"com.example.torture::WidgetK::create","file_path":"torture.kt","language":"kotlin","start_line":85,"end_line":85,"start_column":8,"end_column":42,"docstring":null,"signature":"(): WidgetK","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"WidgetK"} {"id":"method:e9e838e0226a45eac1e61f723fb346d1","kind":"method","name":"sink","qualified_name":"NamedArgs::sink","file_path":"TortureGiven.scala","language":"scala","start_line":23,"end_line":26,"start_column":2,"end_column":3,"docstring":null,"signature":"(): Unit","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Unit"} {"id":"method:ea9d3d2b24e0b1e6559d12766186eb52","kind":"method","name":"run","qualified_name":"Service::run","file_path":"torture.py","language":"python","start_line":25,"end_line":30,"start_column":4,"end_column":36,"docstring":null,"signature":"(self)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"method:ead242834b3f0cee45d34190ccbac3ce","kind":"method","name":"ignoreBelow","qualified_name":"C::ignoreBelow","file_path":"TortureAnnotatedDocs.dart","language":"dart","start_line":112,"end_line":112,"start_column":2,"end_column":20,"docstring":"Doc above, ignore below.\nignore: invalid_use_of_protected_member","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"method:ead242834b3f0cee45d34190ccbac3ce","kind":"method","name":"ignoreBelow","qualified_name":"C::ignoreBelow","file_path":"TortureAnnotatedDocs.dart","language":"dart","start_line":112,"end_line":112,"start_column":2,"end_column":20,"docstring":"Doc above, ignore below.\nignore: invalid_use_of_protected_member // Parser fixture for annotation/comment scanning; no analyzer runs.","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:ebf2f082376e23dff7ba2531c9a9d71f","kind":"method","name":"read","qualified_name":"BufSource::read","file_path":"torture.rs","language":"rust","start_line":141,"end_line":143,"start_column":4,"end_column":5,"docstring":null,"signature":"(&mut self) -> usize","visibility":"private","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:ec3b82565a2eb916f10a964766960a86","kind":"method","name":"dispose","qualified_name":"BaseService::dispose","file_path":"torture.tsx","language":"tsx","start_line":52,"end_line":54,"start_column":2,"end_column":3,"docstring":null,"signature":"(): void","visibility":"protected","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:ec47a62d06708c1f02fc28a967649234","kind":"method","name":"reads","qualified_name":"Table::reads","file_path":"TortureVrefDart.dart","language":"dart","start_line":11,"end_line":15,"start_column":2,"end_column":14,"docstring":null,"signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} diff --git a/__tests__/fixtures/kernel-parity/TortureAnnotatedComments.dart b/__tests__/fixtures/kernel-parity/TortureAnnotatedComments.dart index 87d32a23da..6037644480 100644 --- a/__tests__/fixtures/kernel-parity/TortureAnnotatedComments.dart +++ b/__tests__/fixtures/kernel-parity/TortureAnnotatedComments.dart @@ -12,7 +12,7 @@ void afterImport() {} void trailing() {} @override -// ignore: must_call_super +// ignore: must_call_super // Parser fixture for annotation/comment scanning; no analyzer runs. void lineBelow() {} @x @@ -64,7 +64,7 @@ void afterBody() {} class C { @override - // ignore: must_call_super + // ignore: must_call_super // Parser fixture for annotation/comment scanning; no analyzer runs. void method() {} @x /* inline */ void inline() {} @@ -129,7 +129,7 @@ class C { } @immutable -// ignore: something +// ignore: something // Parser fixture for annotation/comment scanning; no analyzer runs. class D {} @internal diff --git a/__tests__/fixtures/kernel-parity/TortureAnnotatedDocs.dart b/__tests__/fixtures/kernel-parity/TortureAnnotatedDocs.dart index efd5b95621..f79ccff029 100644 --- a/__tests__/fixtures/kernel-parity/TortureAnnotatedDocs.dart +++ b/__tests__/fixtures/kernel-parity/TortureAnnotatedDocs.dart @@ -103,12 +103,12 @@ class C { ) void multi() {} - @override // ignore: must_call_super + @override // ignore: must_call_super // Parser fixture for annotation/comment scanning; no analyzer runs. void trailingComment() {} /// Doc above, ignore below. @override - // ignore: invalid_use_of_protected_member + // ignore: invalid_use_of_protected_member // Parser fixture for annotation/comment scanning; no analyzer runs. void ignoreBelow() {} @x @@ -138,7 +138,7 @@ class C { /// Class doc above a comment. @immutable -// ignore: something +// ignore: something // Parser fixture for annotation/comment scanning; no analyzer runs. class D {} @immutable diff --git a/__tests__/kernel-import-dart-identity.test.ts b/__tests__/kernel-import-dart-identity.test.ts index e09edf7e13..6e085aaf89 100644 --- a/__tests__/kernel-import-dart-identity.test.ts +++ b/__tests__/kernel-import-dart-identity.test.ts @@ -34,6 +34,21 @@ it('parks matching missing includes in both files, then retries both when the he }); const cases = [ + { + name: 'an arrow body string opener does not extend parameter scope', + files: { 'lib/main.dart': "void text() {}\nString wrap(String text) => '(' + text + ')';\nvoid run() { text(); }\n" }, + from: 'run', kind: 'calls', target: 'text', targetFile: 'lib/main.dart', + }, + { + name: 'a loop body string opener does not extend loop-local scope', + files: { 'lib/main.dart': "void item() {}\nvoid run(List items) { for (final item in items) print('['); item(); }\n" }, + from: 'run', kind: 'calls', target: 'item', targetFile: 'lib/main.dart', + }, + { + name: 'an initializer string opener does not extend constructor parameter scope', + files: { 'lib/main.dart': "void text() {}\nclass Box { final String value; Box(String text): value = '{' + text + '}'; }\nvoid run() { text(); }\n" }, + from: 'run', kind: 'calls', target: 'text', targetFile: 'lib/main.dart', + }, { name: 'a multiline imported receiver resolves on its own source line', files: { diff --git a/codegraph-kernel/src/resolve/dart_local.rs b/codegraph-kernel/src/resolve/dart_local.rs index fc7d597d5e..28f43c779c 100644 --- a/codegraph-kernel/src/resolve/dart_local.rs +++ b/codegraph-kernel/src/resolve/dart_local.rs @@ -114,7 +114,7 @@ fn statement_end( if !t[i].string && (matches!(text, ";" | ")" | "]" | "}") || expression && text == ",") { return t[i].start; } - if matches!(text, "(" | "[" | "{") { + if !t[i].string && matches!(text, "(" | "[" | "{") { if let Some(end) = pairs[i] { i = end + 1; continue;