gitnexus 1.6.4 → 1.6.5-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli/ai-context.d.ts +1 -0
- package/dist/cli/ai-context.js +30 -12
- package/dist/cli/analyze.d.ts +18 -0
- package/dist/cli/analyze.js +33 -4
- package/dist/cli/augment.d.ts +1 -1
- package/dist/cli/augment.js +1 -1
- package/dist/cli/index.js +6 -1
- package/dist/core/augmentation/engine.d.ts +2 -2
- package/dist/core/augmentation/engine.js +2 -2
- package/dist/core/embeddings/ast-utils.js +2 -1
- package/dist/core/embeddings/http-client.js +22 -6
- package/dist/core/group/extractors/grpc-extractor.js +2 -1
- package/dist/core/group/extractors/http-patterns/python.js +175 -0
- package/dist/core/group/extractors/http-route-extractor.js +2 -1
- package/dist/core/group/extractors/include-extractor.js +2 -1
- package/dist/core/group/extractors/thrift-extractor.js +2 -1
- package/dist/core/group/extractors/tree-sitter-scanner.js +2 -1
- package/dist/core/ingestion/call-processor.js +3 -2
- package/dist/core/ingestion/heritage-processor.js +3 -2
- package/dist/core/ingestion/import-processor.js +2 -1
- package/dist/core/ingestion/languages/c/arity-metadata.d.ts +14 -0
- package/dist/core/ingestion/languages/c/arity-metadata.js +94 -0
- package/dist/core/ingestion/languages/c/arity.d.ts +6 -0
- package/dist/core/ingestion/languages/c/arity.js +18 -0
- package/dist/core/ingestion/languages/c/captures.d.ts +2 -0
- package/dist/core/ingestion/languages/c/captures.js +105 -0
- package/dist/core/ingestion/languages/c/header-scan.d.ts +7 -0
- package/dist/core/ingestion/languages/c/header-scan.js +55 -0
- package/dist/core/ingestion/languages/c/import-decomposer.d.ts +8 -0
- package/dist/core/ingestion/languages/c/import-decomposer.js +50 -0
- package/dist/core/ingestion/languages/c/import-target.d.ts +14 -0
- package/dist/core/ingestion/languages/c/import-target.js +57 -0
- package/dist/core/ingestion/languages/c/index.d.ts +11 -0
- package/dist/core/ingestion/languages/c/index.js +11 -0
- package/dist/core/ingestion/languages/c/interpret.d.ts +14 -0
- package/dist/core/ingestion/languages/c/interpret.js +48 -0
- package/dist/core/ingestion/languages/c/merge-bindings.d.ts +7 -0
- package/dist/core/ingestion/languages/c/merge-bindings.js +23 -0
- package/dist/core/ingestion/languages/c/query.d.ts +3 -0
- package/dist/core/ingestion/languages/c/query.js +161 -0
- package/dist/core/ingestion/languages/c/scope-resolver.d.ts +13 -0
- package/dist/core/ingestion/languages/c/scope-resolver.js +60 -0
- package/dist/core/ingestion/languages/c/simple-hooks.d.ts +14 -0
- package/dist/core/ingestion/languages/c/simple-hooks.js +19 -0
- package/dist/core/ingestion/languages/c/static-linkage.d.ts +13 -0
- package/dist/core/ingestion/languages/c/static-linkage.js +57 -0
- package/dist/core/ingestion/languages/c-cpp.js +10 -0
- package/dist/core/ingestion/languages/csharp/captures.js +2 -1
- package/dist/core/ingestion/languages/csharp/namespace-siblings.js +3 -2
- package/dist/core/ingestion/languages/go/captures.js +2 -1
- package/dist/core/ingestion/languages/go/range-binding.js +2 -1
- package/dist/core/ingestion/languages/python/captures.js +2 -1
- package/dist/core/ingestion/languages/typescript/captures.js +2 -1
- package/dist/core/ingestion/parsing-processor.js +2 -1
- package/dist/core/ingestion/registry-primary-flag.js +1 -0
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +11 -0
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +2 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +13 -2
- package/dist/core/ingestion/scope-resolution/pipeline/registry.js +2 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +4 -1
- package/dist/core/ingestion/workers/parse-worker.js +2 -1
- package/dist/core/lbug/lbug-adapter.js +8 -0
- package/dist/core/lbug/pool-adapter.js +19 -2
- package/dist/core/run-analyze.d.ts +2 -0
- package/dist/core/run-analyze.js +5 -1
- package/dist/core/tree-sitter/safe-parse.d.ts +6 -0
- package/dist/core/tree-sitter/safe-parse.js +32 -0
- package/dist/server/git-clone.js +10 -13
- package/dist/storage/git.d.ts +17 -6
- package/dist/storage/git.js +46 -12
- package/package.json +1 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import Parser from 'tree-sitter';
|
|
2
|
+
import C from 'tree-sitter-c';
|
|
3
|
+
const C_SCOPE_QUERY = `
|
|
4
|
+
;; Scopes
|
|
5
|
+
(translation_unit) @scope.module
|
|
6
|
+
(struct_specifier) @scope.class
|
|
7
|
+
(union_specifier) @scope.class
|
|
8
|
+
(function_definition) @scope.function
|
|
9
|
+
(compound_statement) @scope.block
|
|
10
|
+
(if_statement) @scope.block
|
|
11
|
+
(for_statement) @scope.block
|
|
12
|
+
(while_statement) @scope.block
|
|
13
|
+
(do_statement) @scope.block
|
|
14
|
+
(switch_statement) @scope.block
|
|
15
|
+
(case_statement) @scope.block
|
|
16
|
+
|
|
17
|
+
;; Declarations — struct (named)
|
|
18
|
+
(struct_specifier
|
|
19
|
+
name: (type_identifier) @declaration.name
|
|
20
|
+
body: (field_declaration_list)) @declaration.struct
|
|
21
|
+
|
|
22
|
+
;; Declarations — struct (typedef struct { ... } Name)
|
|
23
|
+
(type_definition
|
|
24
|
+
type: (struct_specifier
|
|
25
|
+
body: (field_declaration_list))
|
|
26
|
+
declarator: (type_identifier) @declaration.name) @declaration.struct
|
|
27
|
+
|
|
28
|
+
;; Declarations — union (named)
|
|
29
|
+
(union_specifier
|
|
30
|
+
name: (type_identifier) @declaration.name
|
|
31
|
+
body: (field_declaration_list)) @declaration.union
|
|
32
|
+
|
|
33
|
+
;; Declarations — union (typedef union { ... } Name)
|
|
34
|
+
(type_definition
|
|
35
|
+
type: (union_specifier
|
|
36
|
+
body: (field_declaration_list))
|
|
37
|
+
declarator: (type_identifier) @declaration.name) @declaration.union
|
|
38
|
+
|
|
39
|
+
;; Declarations — enum
|
|
40
|
+
(enum_specifier
|
|
41
|
+
name: (type_identifier) @declaration.name) @declaration.enum
|
|
42
|
+
|
|
43
|
+
;; Declarations — function definition
|
|
44
|
+
(function_definition
|
|
45
|
+
declarator: (function_declarator
|
|
46
|
+
declarator: (identifier) @declaration.name)) @declaration.function
|
|
47
|
+
|
|
48
|
+
;; Declarations — function definition with pointer return
|
|
49
|
+
(function_definition
|
|
50
|
+
declarator: (pointer_declarator
|
|
51
|
+
declarator: (function_declarator
|
|
52
|
+
declarator: (identifier) @declaration.name))) @declaration.function
|
|
53
|
+
|
|
54
|
+
;; Declarations — function declaration (prototype)
|
|
55
|
+
;; Note: Both prototypes and definitions are captured as @declaration.function.
|
|
56
|
+
;; This may produce duplicate Function nodes in the knowledge graph when a
|
|
57
|
+
;; function is declared in a header and defined in a .c file. CALLS edges
|
|
58
|
+
;; resolve correctly through scope-based wildcard import chains; the
|
|
59
|
+
;; duplication is a graph-quality concern only (no false edges).
|
|
60
|
+
(declaration
|
|
61
|
+
declarator: (function_declarator
|
|
62
|
+
declarator: (identifier) @declaration.name)) @declaration.function
|
|
63
|
+
|
|
64
|
+
;; Declarations — function declaration with pointer return (prototype)
|
|
65
|
+
(declaration
|
|
66
|
+
declarator: (pointer_declarator
|
|
67
|
+
declarator: (function_declarator
|
|
68
|
+
declarator: (identifier) @declaration.name))) @declaration.function
|
|
69
|
+
|
|
70
|
+
;; Declarations — typedef
|
|
71
|
+
(type_definition
|
|
72
|
+
declarator: (type_identifier) @declaration.name) @declaration.typedef
|
|
73
|
+
|
|
74
|
+
;; Declarations — typedef for function pointers: typedef void (*callback)(int, int)
|
|
75
|
+
(type_definition
|
|
76
|
+
declarator: (function_declarator
|
|
77
|
+
declarator: (parenthesized_declarator
|
|
78
|
+
(pointer_declarator
|
|
79
|
+
declarator: (type_identifier) @declaration.name)))) @declaration.typedef
|
|
80
|
+
|
|
81
|
+
;; Declarations — struct fields
|
|
82
|
+
(field_declaration
|
|
83
|
+
declarator: (field_identifier) @declaration.name) @declaration.field
|
|
84
|
+
|
|
85
|
+
;; Declarations — struct fields (pointer)
|
|
86
|
+
(field_declaration
|
|
87
|
+
declarator: (pointer_declarator
|
|
88
|
+
declarator: (field_identifier) @declaration.name)) @declaration.field
|
|
89
|
+
|
|
90
|
+
;; Declarations — variables (with initializer)
|
|
91
|
+
(declaration
|
|
92
|
+
declarator: (init_declarator
|
|
93
|
+
declarator: (identifier) @declaration.name)) @declaration.variable
|
|
94
|
+
|
|
95
|
+
;; Declarations — macro definitions
|
|
96
|
+
(preproc_def
|
|
97
|
+
name: (identifier) @declaration.name) @declaration.macro
|
|
98
|
+
|
|
99
|
+
(preproc_function_def
|
|
100
|
+
name: (identifier) @declaration.name) @declaration.macro
|
|
101
|
+
|
|
102
|
+
;; Declarations — enum constants
|
|
103
|
+
(enumerator
|
|
104
|
+
name: (identifier) @declaration.name) @declaration.const
|
|
105
|
+
|
|
106
|
+
;; Imports
|
|
107
|
+
(preproc_include) @import.statement
|
|
108
|
+
|
|
109
|
+
;; Type bindings — parameter annotations
|
|
110
|
+
(parameter_declaration
|
|
111
|
+
type: (_) @type-binding.type
|
|
112
|
+
declarator: (identifier) @type-binding.name) @type-binding.parameter
|
|
113
|
+
|
|
114
|
+
;; Type bindings — variable with type (init_declarator)
|
|
115
|
+
(declaration
|
|
116
|
+
type: (_) @type-binding.type
|
|
117
|
+
declarator: (init_declarator
|
|
118
|
+
declarator: (identifier) @type-binding.name)) @type-binding.assignment
|
|
119
|
+
|
|
120
|
+
;; References — free calls
|
|
121
|
+
;; Note: This also captures calls through function pointer variables (e.g. fp(x))
|
|
122
|
+
;; since tree-sitter-c produces structurally identical AST nodes for both direct
|
|
123
|
+
;; function calls and function-pointer-variable calls. A type-based guard to
|
|
124
|
+
;; distinguish variable-calls from function-calls is not implemented — this is a
|
|
125
|
+
;; known architectural trade-off shared with the Go resolver. The uniqueness
|
|
126
|
+
;; constraint in pickUniqueGlobalCallable limits false edge exposure.
|
|
127
|
+
(call_expression
|
|
128
|
+
function: (identifier) @reference.name) @reference.call.free
|
|
129
|
+
|
|
130
|
+
;; References — member calls via pointer (ptr->func())
|
|
131
|
+
(call_expression
|
|
132
|
+
function: (field_expression
|
|
133
|
+
argument: (_) @reference.receiver
|
|
134
|
+
field: (field_identifier) @reference.name)) @reference.call.member
|
|
135
|
+
|
|
136
|
+
;; References — field reads
|
|
137
|
+
(field_expression
|
|
138
|
+
argument: (_) @reference.receiver
|
|
139
|
+
field: (field_identifier) @reference.name) @reference.read
|
|
140
|
+
|
|
141
|
+
;; References — field writes (assignment)
|
|
142
|
+
(assignment_expression
|
|
143
|
+
left: (field_expression
|
|
144
|
+
argument: (_) @reference.receiver
|
|
145
|
+
field: (field_identifier) @reference.name)) @reference.write
|
|
146
|
+
`;
|
|
147
|
+
let _parser = null;
|
|
148
|
+
let _query = null;
|
|
149
|
+
export function getCParser() {
|
|
150
|
+
if (_parser === null) {
|
|
151
|
+
_parser = new Parser();
|
|
152
|
+
_parser.setLanguage(C);
|
|
153
|
+
}
|
|
154
|
+
return _parser;
|
|
155
|
+
}
|
|
156
|
+
export function getCScopeQuery() {
|
|
157
|
+
if (_query === null) {
|
|
158
|
+
_query = new Parser.Query(C, C_SCOPE_QUERY);
|
|
159
|
+
}
|
|
160
|
+
return _query;
|
|
161
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ScopeResolver } from '../../scope-resolution/contract/scope-resolver.js';
|
|
2
|
+
/**
|
|
3
|
+
* C `ScopeResolver` registered in `SCOPE_RESOLVERS` and consumed by
|
|
4
|
+
* the generic `runScopeResolution` orchestrator (RFC #909 Ring 3).
|
|
5
|
+
*
|
|
6
|
+
* C is a structurally simple language for scope resolution:
|
|
7
|
+
* - No classes (structs are value types, no method dispatch)
|
|
8
|
+
* - No inheritance (no MRO needed beyond the shared first-wins default)
|
|
9
|
+
* - No overloading (arity check is simple: variadic detection only)
|
|
10
|
+
* - `#include` is wildcard import (all symbols from header are visible)
|
|
11
|
+
* - `static` functions are file-local (not exported)
|
|
12
|
+
*/
|
|
13
|
+
export declare const cScopeResolver: ScopeResolver;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { SupportedLanguages } from '../../../../_shared/index.js';
|
|
2
|
+
import { buildMro, defaultLinearize } from '../../scope-resolution/passes/mro.js';
|
|
3
|
+
import { populateClassOwnedMembers } from '../../scope-resolution/scope/walkers.js';
|
|
4
|
+
import { cProvider } from '../c-cpp.js';
|
|
5
|
+
import { cArityCompatibility, cMergeBindings, resolveCImportTarget } from './index.js';
|
|
6
|
+
import { scanHeaderFiles } from './header-scan.js';
|
|
7
|
+
import { expandCWildcardNames, isStaticName, clearStaticNames } from './static-linkage.js';
|
|
8
|
+
/**
|
|
9
|
+
* C `ScopeResolver` registered in `SCOPE_RESOLVERS` and consumed by
|
|
10
|
+
* the generic `runScopeResolution` orchestrator (RFC #909 Ring 3).
|
|
11
|
+
*
|
|
12
|
+
* C is a structurally simple language for scope resolution:
|
|
13
|
+
* - No classes (structs are value types, no method dispatch)
|
|
14
|
+
* - No inheritance (no MRO needed beyond the shared first-wins default)
|
|
15
|
+
* - No overloading (arity check is simple: variadic detection only)
|
|
16
|
+
* - `#include` is wildcard import (all symbols from header are visible)
|
|
17
|
+
* - `static` functions are file-local (not exported)
|
|
18
|
+
*/
|
|
19
|
+
export const cScopeResolver = {
|
|
20
|
+
language: SupportedLanguages.C,
|
|
21
|
+
languageProvider: cProvider,
|
|
22
|
+
importEdgeReason: 'c-scope: include',
|
|
23
|
+
loadResolutionConfig: (repoPath) => {
|
|
24
|
+
// Clear stale static-linkage data from any previous invocation to
|
|
25
|
+
// prevent cross-repo contamination in server-mode scenarios.
|
|
26
|
+
clearStaticNames();
|
|
27
|
+
return scanHeaderFiles(repoPath);
|
|
28
|
+
},
|
|
29
|
+
resolveImportTarget: (targetRaw, fromFile, allFilePaths, resolutionConfig) => {
|
|
30
|
+
// Augment allFilePaths with .h files discovered via loadResolutionConfig
|
|
31
|
+
// since the phase only passes .c files to the C resolver but #include
|
|
32
|
+
// targets .h files classified as C++ in language detection.
|
|
33
|
+
const headerPaths = resolutionConfig;
|
|
34
|
+
if (headerPaths !== undefined && headerPaths.size > 0) {
|
|
35
|
+
const augmented = new Set(allFilePaths);
|
|
36
|
+
for (const h of headerPaths)
|
|
37
|
+
augmented.add(h);
|
|
38
|
+
return resolveCImportTarget(targetRaw, fromFile, augmented);
|
|
39
|
+
}
|
|
40
|
+
return resolveCImportTarget(targetRaw, fromFile, allFilePaths);
|
|
41
|
+
},
|
|
42
|
+
expandsWildcardTo: (targetModuleScope, parsedFiles) => expandCWildcardNames(targetModuleScope, parsedFiles),
|
|
43
|
+
mergeBindings: (existing, incoming, scopeId) => cMergeBindings(existing, incoming, scopeId),
|
|
44
|
+
arityCompatibility: (callsite, def) => cArityCompatibility(def, callsite),
|
|
45
|
+
buildMro: (graph, parsedFiles, nodeLookup) => buildMro(graph, parsedFiles, nodeLookup, defaultLinearize),
|
|
46
|
+
populateOwners: (parsed) => populateClassOwnedMembers(parsed),
|
|
47
|
+
isSuperReceiver: () => false,
|
|
48
|
+
// C is statically typed — disable field fallback heuristic
|
|
49
|
+
fieldFallbackOnMethodLookup: false,
|
|
50
|
+
// C has no method return types to propagate
|
|
51
|
+
propagatesReturnTypesAcrossImports: false,
|
|
52
|
+
// C #include brings in all symbols — enable global free call fallback
|
|
53
|
+
allowGlobalFreeCallFallback: true,
|
|
54
|
+
// C `static` functions have file-local (translation-unit) linkage —
|
|
55
|
+
// exclude them from global free-call fallback cross-file resolution.
|
|
56
|
+
isFileLocalDef: (def) => {
|
|
57
|
+
const simple = def.qualifiedName?.split('.').pop() ?? def.qualifiedName ?? '';
|
|
58
|
+
return isStaticName(def.filePath, simple);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CaptureMatch, ParsedImport, Scope, ScopeId, ScopeTree, TypeRef } from '../../../../_shared/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* C binding scope: always use default auto-hoist (null).
|
|
4
|
+
* C has no self/receiver bindings that need special scoping.
|
|
5
|
+
*/
|
|
6
|
+
export declare function cBindingScopeFor(_decl: CaptureMatch, _innermost: Scope, _tree: ScopeTree): ScopeId | null;
|
|
7
|
+
/**
|
|
8
|
+
* C import owning scope: always use default (null).
|
|
9
|
+
*/
|
|
10
|
+
export declare function cImportOwningScope(_imp: ParsedImport, _innermost: Scope, _tree: ScopeTree): ScopeId | null;
|
|
11
|
+
/**
|
|
12
|
+
* C receiver binding: always null. C has no methods or receivers.
|
|
13
|
+
*/
|
|
14
|
+
export declare function cReceiverBinding(_functionScope: Scope): TypeRef | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C binding scope: always use default auto-hoist (null).
|
|
3
|
+
* C has no self/receiver bindings that need special scoping.
|
|
4
|
+
*/
|
|
5
|
+
export function cBindingScopeFor(_decl, _innermost, _tree) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* C import owning scope: always use default (null).
|
|
10
|
+
*/
|
|
11
|
+
export function cImportOwningScope(_imp, _innermost, _tree) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* C receiver binding: always null. C has no methods or receivers.
|
|
16
|
+
*/
|
|
17
|
+
export function cReceiverBinding(_functionScope) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ParsedFile, ScopeId } from '../../../../_shared/index.js';
|
|
2
|
+
/** Record a symbol name as `static` (file-local linkage) for the given file. */
|
|
3
|
+
export declare function markStaticName(filePath: string, name: string): void;
|
|
4
|
+
/** Check whether a symbol name has `static` linkage in the given file. */
|
|
5
|
+
export declare function isStaticName(filePath: string, name: string): boolean;
|
|
6
|
+
/** Clear tracked static names (for testing). */
|
|
7
|
+
export declare function clearStaticNames(): void;
|
|
8
|
+
/**
|
|
9
|
+
* Return the names visible through a C wildcard import (`#include`).
|
|
10
|
+
* All module-scope defs from the target file are visible EXCEPT those
|
|
11
|
+
* declared with `static` storage class (file-local linkage in C).
|
|
12
|
+
*/
|
|
13
|
+
export declare function expandCWildcardNames(targetModuleScope: ScopeId, parsedFiles: readonly ParsedFile[]): readonly string[];
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-file set of function names declared with `static` storage class.
|
|
3
|
+
* Populated during `emitCScopeCaptures` and consumed by `expandCWildcardNames`
|
|
4
|
+
* to exclude file-local symbols from cross-file wildcard import visibility.
|
|
5
|
+
*
|
|
6
|
+
* NOTE: module-level state, single-process-single-repo use only.
|
|
7
|
+
* For server-mode or multi-repo-in-one-process use cases, call
|
|
8
|
+
* `clearStaticNames()` at the start of each resolution pass to avoid
|
|
9
|
+
* stale static-linkage data from a previous invocation.
|
|
10
|
+
*
|
|
11
|
+
* Key: filePath, Value: Set of static function names.
|
|
12
|
+
*/
|
|
13
|
+
const staticNames = new Map();
|
|
14
|
+
/** Record a symbol name as `static` (file-local linkage) for the given file. */
|
|
15
|
+
export function markStaticName(filePath, name) {
|
|
16
|
+
let names = staticNames.get(filePath);
|
|
17
|
+
if (names === undefined) {
|
|
18
|
+
names = new Set();
|
|
19
|
+
staticNames.set(filePath, names);
|
|
20
|
+
}
|
|
21
|
+
names.add(name);
|
|
22
|
+
}
|
|
23
|
+
/** Check whether a symbol name has `static` linkage in the given file. */
|
|
24
|
+
export function isStaticName(filePath, name) {
|
|
25
|
+
return staticNames.get(filePath)?.has(name) ?? false;
|
|
26
|
+
}
|
|
27
|
+
/** Clear tracked static names (for testing). */
|
|
28
|
+
export function clearStaticNames() {
|
|
29
|
+
staticNames.clear();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Return the names visible through a C wildcard import (`#include`).
|
|
33
|
+
* All module-scope defs from the target file are visible EXCEPT those
|
|
34
|
+
* declared with `static` storage class (file-local linkage in C).
|
|
35
|
+
*/
|
|
36
|
+
export function expandCWildcardNames(targetModuleScope, parsedFiles) {
|
|
37
|
+
const target = parsedFiles.find((p) => p.moduleScope === targetModuleScope);
|
|
38
|
+
if (target === undefined)
|
|
39
|
+
return [];
|
|
40
|
+
const seen = new Set();
|
|
41
|
+
const names = [];
|
|
42
|
+
for (const def of target.localDefs) {
|
|
43
|
+
const name = simpleName(def);
|
|
44
|
+
if (name === '')
|
|
45
|
+
continue;
|
|
46
|
+
if (isStaticName(target.filePath, name))
|
|
47
|
+
continue;
|
|
48
|
+
if (seen.has(name))
|
|
49
|
+
continue;
|
|
50
|
+
seen.add(name);
|
|
51
|
+
names.push(name);
|
|
52
|
+
}
|
|
53
|
+
return names;
|
|
54
|
+
}
|
|
55
|
+
function simpleName(def) {
|
|
56
|
+
return def.qualifiedName?.split('.').pop() ?? def.qualifiedName ?? '';
|
|
57
|
+
}
|
|
@@ -37,6 +37,7 @@ import { createCallExtractor } from '../call-extractors/generic.js';
|
|
|
37
37
|
import { cCallConfig, cppCallConfig } from '../call-extractors/configs/c-cpp.js';
|
|
38
38
|
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
|
|
39
39
|
import { stripUeMacros } from '../cpp-ue-preprocessor.js';
|
|
40
|
+
import { emitCScopeCaptures, interpretCImport, interpretCTypeBinding, cArityCompatibility, cBindingScopeFor, cImportOwningScope, cReceiverBinding, } from './c/index.js';
|
|
40
41
|
const C_BUILT_INS = new Set([
|
|
41
42
|
'printf',
|
|
42
43
|
'fprintf',
|
|
@@ -338,6 +339,15 @@ export const cProvider = defineLanguage({
|
|
|
338
339
|
heritageExtractor: createHeritageExtractor(SupportedLanguages.C),
|
|
339
340
|
labelOverride: cppLabelOverride,
|
|
340
341
|
builtInNames: C_BUILT_INS,
|
|
342
|
+
// ── RFC #909 Ring 3: scope-based resolution hooks (RFC §5) ──────────
|
|
343
|
+
emitScopeCaptures: emitCScopeCaptures,
|
|
344
|
+
interpretImport: interpretCImport,
|
|
345
|
+
interpretTypeBinding: interpretCTypeBinding,
|
|
346
|
+
bindingScopeFor: cBindingScopeFor,
|
|
347
|
+
importOwningScope: cImportOwningScope,
|
|
348
|
+
receiverBinding: cReceiverBinding,
|
|
349
|
+
arityCompatibility: cArityCompatibility,
|
|
350
|
+
// mergeBindings + resolveImportTarget live on ScopeResolver (see c/scope-resolver.ts).
|
|
341
351
|
});
|
|
342
352
|
export const cppProvider = defineLanguage({
|
|
343
353
|
id: SupportedLanguages.CPlusPlus,
|
|
@@ -22,6 +22,7 @@ import { synthesizeCsharpReceiverBinding } from './receiver-binding.js';
|
|
|
22
22
|
import { getCsharpParser, getCsharpScopeQuery } from './query.js';
|
|
23
23
|
import { recordCacheHit, recordCacheMiss } from './cache-stats.js';
|
|
24
24
|
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
25
|
+
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
25
26
|
/** Declaration anchors that carry function-like arity metadata. */
|
|
26
27
|
const FUNCTION_DECL_TAGS = [
|
|
27
28
|
'@declaration.method',
|
|
@@ -75,7 +76,7 @@ export function emitCsharpScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
|
75
76
|
// the LanguageProvider contract layer; cast here at the use site.
|
|
76
77
|
let tree = cachedTree;
|
|
77
78
|
if (tree === undefined) {
|
|
78
|
-
tree = getCsharpParser()
|
|
79
|
+
tree = parseSourceSafe(getCsharpParser(), sourceText, undefined, {
|
|
79
80
|
bufferSize: getTreeSitterBufferSize(sourceText),
|
|
80
81
|
});
|
|
81
82
|
recordCacheMiss();
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
import { getCsharpParser } from './query.js';
|
|
34
34
|
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
35
|
+
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
35
36
|
/** Build a structural view of a C# file by walking the tree-sitter
|
|
36
37
|
* AST. Prefers `cachedTree` (handed in via `treeCache`) so we don't
|
|
37
38
|
* re-parse files the orchestrator already parsed for `extractParsedFile`;
|
|
@@ -39,7 +40,7 @@ import { getTreeSitterBufferSize } from '../../constants.js';
|
|
|
39
40
|
* shared across calls. */
|
|
40
41
|
function extractFileStructure(content, cachedTree) {
|
|
41
42
|
const tree = cachedTree ??
|
|
42
|
-
getCsharpParser()
|
|
43
|
+
parseSourceSafe(getCsharpParser(), content, undefined, {
|
|
43
44
|
bufferSize: getTreeSitterBufferSize(content),
|
|
44
45
|
});
|
|
45
46
|
const namespaces = [];
|
|
@@ -332,7 +333,7 @@ export function populateCsharpNamespaceSiblings(parsedFiles, indexes, inputs) {
|
|
|
332
333
|
const key = q.includes('.') ? q.slice(q.lastIndexOf('.') + 1) : q;
|
|
333
334
|
if (key === '')
|
|
334
335
|
continue;
|
|
335
|
-
const arr = defsByName.get(key) ?? [];
|
|
336
|
+
const arr = [...(defsByName.get(key) ?? [])];
|
|
336
337
|
arr.push(def);
|
|
337
338
|
defsByName.set(key, arr);
|
|
338
339
|
}
|
|
@@ -6,10 +6,11 @@ import { splitGoImportStatement } from './import-decomposer.js';
|
|
|
6
6
|
import { synthesizeGoReceiverBinding } from './receiver-binding.js';
|
|
7
7
|
import { synthesizeGoTypeBindings } from './type-binding.js';
|
|
8
8
|
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
9
|
+
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
9
10
|
export function emitGoScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
10
11
|
let tree = cachedTree;
|
|
11
12
|
if (tree === undefined) {
|
|
12
|
-
tree = getGoParser()
|
|
13
|
+
tree = parseSourceSafe(getGoParser(), sourceText, undefined, {
|
|
13
14
|
bufferSize: getTreeSitterBufferSize(sourceText),
|
|
14
15
|
});
|
|
15
16
|
recordGoCacheMiss();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getGoParser } from './query.js';
|
|
2
2
|
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
3
|
+
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
3
4
|
export function populateGoRangeBindings(parsedFiles, _indexes, ctx) {
|
|
4
5
|
const parser = getGoParser();
|
|
5
6
|
for (const parsed of parsedFiles) {
|
|
@@ -8,7 +9,7 @@ export function populateGoRangeBindings(parsedFiles, _indexes, ctx) {
|
|
|
8
9
|
continue;
|
|
9
10
|
const cachedTree = ctx.treeCache?.get(parsed.filePath);
|
|
10
11
|
const tree = cachedTree ??
|
|
11
|
-
parser
|
|
12
|
+
parseSourceSafe(parser, sourceText, undefined, {
|
|
12
13
|
bufferSize: getTreeSitterBufferSize(sourceText),
|
|
13
14
|
});
|
|
14
15
|
const moduleScope = parsed.scopes.find((s) => s.kind === 'Module');
|
|
@@ -22,6 +22,7 @@ import { synthesizeReceiverTypeBinding } from './receiver-binding.js';
|
|
|
22
22
|
import { computePythonArityMetadata } from './arity-metadata.js';
|
|
23
23
|
import { recordCacheHit, recordCacheMiss } from './cache-stats.js';
|
|
24
24
|
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
25
|
+
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
25
26
|
import { pythonFunctionDefinitionLabel } from './simple-hooks.js';
|
|
26
27
|
export function emitPythonScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
27
28
|
// Skip the parse when the caller (parse phase's ASTCache) already
|
|
@@ -32,7 +33,7 @@ export function emitPythonScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
|
32
33
|
let tree = cachedTree;
|
|
33
34
|
if (tree === undefined) {
|
|
34
35
|
try {
|
|
35
|
-
tree = getPythonParser()
|
|
36
|
+
tree = parseSourceSafe(getPythonParser(), sourceText, undefined, {
|
|
36
37
|
bufferSize: getTreeSitterBufferSize(sourceText),
|
|
37
38
|
});
|
|
38
39
|
}
|
|
@@ -31,6 +31,7 @@ import { recordCacheHit, recordCacheMiss } from './cache-stats.js';
|
|
|
31
31
|
import { synthesizeTsReceiverBinding } from './receiver-binding.js';
|
|
32
32
|
import { computeTsArityMetadata } from './arity-metadata.js';
|
|
33
33
|
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
34
|
+
import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
|
|
34
35
|
/** tree-sitter-typescript node types for function-like scopes that may
|
|
35
36
|
* carry a synthesized `this` binding. Kept in sync with the
|
|
36
37
|
* `@scope.function` patterns in `query.ts`. */
|
|
@@ -119,7 +120,7 @@ export function emitTsScopeCaptures(sourceText, filePath, cachedTree) {
|
|
|
119
120
|
tree = undefined;
|
|
120
121
|
}
|
|
121
122
|
if (tree === undefined) {
|
|
122
|
-
tree = getTsParser(filePath)
|
|
123
|
+
tree = parseSourceSafe(getTsParser(filePath), sourceText, undefined, {
|
|
123
124
|
bufferSize: getTreeSitterBufferSize(sourceText),
|
|
124
125
|
});
|
|
125
126
|
recordCacheMiss();
|
|
@@ -5,6 +5,7 @@ import { generateId } from '../../lib/utils.js';
|
|
|
5
5
|
import { getLanguageFromFilename, SupportedLanguages } from '../../_shared/index.js';
|
|
6
6
|
import { extractVueScript, isVueSetupTopLevel } from './vue-sfc-extractor.js';
|
|
7
7
|
import { yieldToEventLoop } from './utils/event-loop.js';
|
|
8
|
+
import { parseSourceSafe } from '../tree-sitter/safe-parse.js';
|
|
8
9
|
import { isVerboseIngestionEnabled } from './utils/verbose.js';
|
|
9
10
|
import { getDefinitionNodeFromCaptures, findEnclosingClassInfo, getLabelFromCaptures, CLASS_CONTAINER_TYPES, } from './utils/ast-helpers.js';
|
|
10
11
|
import { detectFrameworkFromAST } from './framework-detection.js';
|
|
@@ -274,7 +275,7 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, sco
|
|
|
274
275
|
}
|
|
275
276
|
let tree;
|
|
276
277
|
try {
|
|
277
|
-
tree = parser
|
|
278
|
+
tree = parseSourceSafe(parser, parseContent, undefined, {
|
|
278
279
|
bufferSize: getTreeSitterBufferSize(parseContent),
|
|
279
280
|
});
|
|
280
281
|
}
|
|
@@ -414,6 +414,17 @@ export interface ScopeResolver {
|
|
|
414
414
|
* but is too loose as a default for strict module systems.
|
|
415
415
|
*/
|
|
416
416
|
readonly allowGlobalFreeCallFallback?: boolean;
|
|
417
|
+
/**
|
|
418
|
+
* Optional predicate to identify definitions with file-local linkage
|
|
419
|
+
* (e.g. C `static` functions). When provided, `pickUniqueGlobalCallable`
|
|
420
|
+
* excludes defs where `isFileLocalDef(def) === true` and the def lives
|
|
421
|
+
* in a different file from the caller. This prevents the global free-call
|
|
422
|
+
* fallback from creating CALLS edges to file-local symbols that are
|
|
423
|
+
* logically invisible from the caller's translation unit.
|
|
424
|
+
*
|
|
425
|
+
* Languages without file-local linkage semantics leave this undefined.
|
|
426
|
+
*/
|
|
427
|
+
readonly isFileLocalDef?: (def: SymbolDefinition) => boolean;
|
|
417
428
|
/**
|
|
418
429
|
* Optional post-finalize hook to inject cross-file bindings that
|
|
419
430
|
* aren't modeled via explicit imports. Runs after
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* Generic; promoted from `languages/python/scope-resolver.ts` per the scope-resolution
|
|
17
17
|
* generalization plan.
|
|
18
18
|
*/
|
|
19
|
-
import type { ParsedFile, Reference, ScopeId } from '../../../../_shared/index.js';
|
|
19
|
+
import type { ParsedFile, Reference, ScopeId, SymbolDefinition } from '../../../../_shared/index.js';
|
|
20
20
|
import type { KnowledgeGraph } from '../../../graph/types.js';
|
|
21
21
|
import type { ScopeResolutionIndexes } from '../../model/scope-resolution-indexes.js';
|
|
22
22
|
import type { SemanticModel } from '../../model/semantic-model.js';
|
|
@@ -26,4 +26,5 @@ export declare function emitFreeCallFallback(graph: KnowledgeGraph, scopes: Scop
|
|
|
26
26
|
readonly bySourceScope: ReadonlyMap<ScopeId, readonly Reference[]>;
|
|
27
27
|
}, handledSites: Set<string>, model: SemanticModel, workspaceIndex: WorkspaceResolutionIndex, options?: {
|
|
28
28
|
readonly allowGlobalFallback?: boolean;
|
|
29
|
+
readonly isFileLocalDef?: (def: SymbolDefinition) => boolean;
|
|
29
30
|
}): number;
|
|
@@ -55,7 +55,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
|
|
|
55
55
|
// the caller does not import the target package. Same-package calls are
|
|
56
56
|
// caught by findCallableBindingInScope above before reaching here.
|
|
57
57
|
if (fnDef === undefined && options.allowGlobalFallback === true) {
|
|
58
|
-
fnDef = pickUniqueGlobalCallable(site.name, model, scopes);
|
|
58
|
+
fnDef = pickUniqueGlobalCallable(site.name, model, scopes, parsed.filePath, options.isFileLocalDef);
|
|
59
59
|
}
|
|
60
60
|
if (fnDef === undefined)
|
|
61
61
|
continue;
|
|
@@ -88,7 +88,7 @@ export function emitFreeCallFallback(graph, scopes, parsedFiles, nodeLookup, _re
|
|
|
88
88
|
}
|
|
89
89
|
return emitted;
|
|
90
90
|
}
|
|
91
|
-
function pickUniqueGlobalCallable(name, model, scopes) {
|
|
91
|
+
function pickUniqueGlobalCallable(name, model, scopes, callerFilePath, isFileLocalDef) {
|
|
92
92
|
const scopeDefs = [];
|
|
93
93
|
const scopeSeen = new Set();
|
|
94
94
|
for (const def of scopes.defs.byId.values()) {
|
|
@@ -97,6 +97,11 @@ function pickUniqueGlobalCallable(name, model, scopes) {
|
|
|
97
97
|
continue;
|
|
98
98
|
if (def.type !== 'Function' && def.type !== 'Method' && def.type !== 'Constructor')
|
|
99
99
|
continue;
|
|
100
|
+
// Skip file-local defs (e.g. C `static` functions) that live in a
|
|
101
|
+
// different file from the caller — they are logically invisible.
|
|
102
|
+
if (isFileLocalDef !== undefined && def.filePath !== callerFilePath && isFileLocalDef(def)) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
100
105
|
const key = logicalCallableKey(def);
|
|
101
106
|
if (scopeSeen.has(key))
|
|
102
107
|
continue;
|
|
@@ -109,6 +114,12 @@ function pickUniqueGlobalCallable(name, model, scopes) {
|
|
|
109
114
|
const seen = new Set();
|
|
110
115
|
const push = (pool) => {
|
|
111
116
|
for (const def of pool) {
|
|
117
|
+
// Apply the same file-local linkage filter as Phase 1 —
|
|
118
|
+
// cross-file static defs must never leak through the
|
|
119
|
+
// SemanticModel fallback path.
|
|
120
|
+
if (isFileLocalDef !== undefined && def.filePath !== callerFilePath && isFileLocalDef(def)) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
112
123
|
const key = logicalCallableKey(def);
|
|
113
124
|
if (seen.has(key))
|
|
114
125
|
continue;
|
|
@@ -13,6 +13,7 @@ import { pythonScopeResolver } from '../../languages/python/scope-resolver.js';
|
|
|
13
13
|
import { csharpScopeResolver } from '../../languages/csharp/scope-resolver.js';
|
|
14
14
|
import { typescriptScopeResolver } from '../../languages/typescript/scope-resolver.js';
|
|
15
15
|
import { goScopeResolver } from '../../languages/go/scope-resolver.js';
|
|
16
|
+
import { cScopeResolver } from '../../languages/c/scope-resolver.js';
|
|
16
17
|
/** Map of `SupportedLanguages` → `ScopeResolver`. The phase iterates
|
|
17
18
|
* this map intersected with `MIGRATED_LANGUAGES` (the per-language
|
|
18
19
|
* flag set) so adding a resolver here without flipping the flag is
|
|
@@ -22,4 +23,5 @@ export const SCOPE_RESOLVERS = new Map([
|
|
|
22
23
|
[SupportedLanguages.CSharp, csharpScopeResolver],
|
|
23
24
|
[SupportedLanguages.TypeScript, typescriptScopeResolver],
|
|
24
25
|
[SupportedLanguages.Go, goScopeResolver],
|
|
26
|
+
[SupportedLanguages.C, cScopeResolver],
|
|
25
27
|
]);
|
|
@@ -169,7 +169,10 @@ export function runScopeResolution(input, provider) {
|
|
|
169
169
|
// ── Phase 4: emit graph edges (LOAD-BEARING ORDER — see I1) ────────────
|
|
170
170
|
const handledSites = new Set();
|
|
171
171
|
const receiverExtras = emitReceiverBoundCalls(graph, indexes, parsedFiles, nodeLookup, handledSites, provider, workspaceIndex, readonlyModel);
|
|
172
|
-
const freeCallExtras = emitFreeCallFallback(graph, indexes, parsedFiles, nodeLookup, referenceIndex, handledSites, readonlyModel, workspaceIndex, {
|
|
172
|
+
const freeCallExtras = emitFreeCallFallback(graph, indexes, parsedFiles, nodeLookup, referenceIndex, handledSites, readonlyModel, workspaceIndex, {
|
|
173
|
+
allowGlobalFallback: provider.allowGlobalFreeCallFallback === true,
|
|
174
|
+
isFileLocalDef: provider.isFileLocalDef,
|
|
175
|
+
});
|
|
173
176
|
const { emitted, skipped } = emitReferencesViaLookup(graph, indexes, referenceIndex, nodeLookup, handledSites);
|
|
174
177
|
const importsEmitted = emitImportEdges(graph, indexes.imports, indexes.scopeTree, provider.importEdgeReason);
|
|
175
178
|
if (PROF) {
|
|
@@ -16,6 +16,7 @@ import { createRequire } from 'node:module';
|
|
|
16
16
|
import { SupportedLanguages } from '../../../_shared/index.js';
|
|
17
17
|
import { getProvider } from '../languages/index.js';
|
|
18
18
|
import { getTreeSitterBufferSize, getTreeSitterContentByteLength, TREE_SITTER_MAX_BUFFER, } from '../constants.js';
|
|
19
|
+
import { parseSourceSafe } from '../../tree-sitter/safe-parse.js';
|
|
19
20
|
// tree-sitter-swift is an optionalDependency — may not be installed
|
|
20
21
|
const _require = createRequire(import.meta.url);
|
|
21
22
|
let Swift = null;
|
|
@@ -1026,7 +1027,7 @@ const processFileGroup = (files, language, queryString, result, onFileProcessed)
|
|
|
1026
1027
|
clearCaches(); // Reset memoization before each new file
|
|
1027
1028
|
let tree;
|
|
1028
1029
|
try {
|
|
1029
|
-
tree = parser
|
|
1030
|
+
tree = parseSourceSafe(parser, parseContent, undefined, {
|
|
1030
1031
|
bufferSize: getTreeSitterBufferSize(parseContent),
|
|
1031
1032
|
});
|
|
1032
1033
|
}
|
|
@@ -1102,6 +1102,14 @@ export const loadVectorExtension = async (targetConn, opts = {}) => {
|
|
|
1102
1102
|
const useModuleState = targetConn === undefined;
|
|
1103
1103
|
if (useModuleState && vectorExtensionLoaded)
|
|
1104
1104
|
return true;
|
|
1105
|
+
// INSTALL VECTOR crashes with SIGSEGV on Windows: the KuzuDB native extension
|
|
1106
|
+
// installer has an unhandled error path on Windows that raises a fatal signal
|
|
1107
|
+
// that JS try/catch cannot intercept. Skip loading — vector/embedding search
|
|
1108
|
+
// is unavailable but all graph index queries still work. Do NOT set
|
|
1109
|
+
// vectorExtensionLoaded here: the flag means "successfully loaded", and a
|
|
1110
|
+
// subsequent call would otherwise short-circuit to `return true` at the top.
|
|
1111
|
+
if (process.platform === 'win32')
|
|
1112
|
+
return false;
|
|
1105
1113
|
if (!isVectorExtensionSupportedByPlatform())
|
|
1106
1114
|
return false;
|
|
1107
1115
|
const c = targetConn ?? conn;
|