ucn 5.5.1 → 5.5.2
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/.claude/skills/ucn/SKILL.md +35 -9
- package/.claude/skills/ucn/references/commands.md +38 -16
- package/.claude/skills/ucn/references/resolution-rules.md +126 -20
- package/.claude/skills/ucn/references/trust-contract.md +5 -3
- package/README.md +30 -21
- package/cli/index.js +1 -1
- package/core/accessors.js +341 -54
- package/core/account.js +74 -20
- package/core/analysis.js +257 -125
- package/core/ast-analysis.js +12 -3
- package/core/brief.js +8 -4
- package/core/build-worker.js +2 -1
- package/core/cache.js +137 -6
- package/core/call-name-cache.js +134 -0
- package/core/callable-scope.js +21 -0
- package/core/callers.js +4726 -940
- package/core/check.js +22 -5
- package/core/class-identity.js +399 -12
- package/core/constructor-calls.js +831 -0
- package/core/constructor-hierarchy.js +147 -0
- package/core/constructor-protocol.js +196 -0
- package/core/contract-membership.js +346 -140
- package/core/cpp-conversion-constraints.js +123 -0
- package/core/cpp-conversion-syntax.js +216 -0
- package/core/cpp-conversions.js +414 -0
- package/core/cpp-scope.js +245 -44
- package/core/deadcode.js +35 -15
- package/core/decorator-binding.js +137 -3
- package/core/enum-reference-syntax.js +134 -0
- package/core/execute.js +17 -1
- package/core/external-macros.js +42 -10
- package/core/go-packages.js +171 -0
- package/core/graph-build.js +2 -0
- package/core/graph.js +75 -59
- package/core/ignore-rules.js +2 -1
- package/core/imports.js +145 -19
- package/core/index-ir.js +41 -4
- package/core/ir.js +27 -6
- package/core/macro-expansion.js +38 -2
- package/core/out-of-class-members.js +182 -0
- package/core/output/analysis-ext.js +4 -2
- package/core/output/analysis.js +89 -20
- package/core/output/graph.js +12 -3
- package/core/output/lines.js +4 -3
- package/core/output/public.js +1 -0
- package/core/output/reporting.js +6 -1
- package/core/output/shared.js +2 -0
- package/core/output/tracing.js +28 -22
- package/core/output-budget.js +2 -2
- package/core/parallel-build.js +52 -1
- package/core/project.js +217 -112
- package/core/provenance-constructor-base.js +161 -0
- package/core/provenance-facts.js +257 -27
- package/core/provenance-overload.js +458 -54
- package/core/provenance-type.js +487 -0
- package/core/provenance.js +234 -15
- package/core/public-command.js +17 -2
- package/core/query-bodies.js +159 -0
- package/core/reflection.js +255 -2
- package/core/rename-token-syntax.js +111 -0
- package/core/reporting.js +13 -7
- package/core/rust-macro-expansion.js +151 -19
- package/core/rust-modules.js +1 -1
- package/core/rust-names.js +607 -0
- package/core/search.js +70 -17
- package/core/shared.js +98 -1
- package/core/source-memo.js +201 -0
- package/core/text-usage-syntax.js +38 -0
- package/core/tracing.js +7 -1
- package/core/type-denotation.js +124 -37
- package/core/type-references.js +615 -246
- package/core/value-references.js +2777 -0
- package/core/verify.js +1097 -281
- package/languages/adapter.js +28 -4
- package/languages/c-family.js +1118 -164
- package/languages/constructor-bases.js +105 -0
- package/languages/cpp-platform.js +26 -0
- package/languages/cpp-site-syntax.js +83 -0
- package/languages/csharp-scope.js +439 -0
- package/languages/csharp.js +428 -68
- package/languages/go.js +385 -207
- package/languages/html.js +4 -2
- package/languages/index.js +397 -2
- package/languages/java-platform.js +226 -0
- package/languages/java-unicode.js +269 -0
- package/languages/java.js +461 -117
- package/languages/javascript.js +418 -66
- package/languages/lexical-scope.js +190 -23
- package/languages/python.js +404 -54
- package/languages/rust.js +510 -82
- package/languages/utils.js +67 -8
- package/mcp/server.js +8 -2
- package/package.json +2 -2
package/languages/index.js
CHANGED
|
@@ -8,6 +8,11 @@ const path = require('path');
|
|
|
8
8
|
const { UcnError } = require('../core/errors');
|
|
9
9
|
const { createLanguageAdapter } = require('./adapter');
|
|
10
10
|
|
|
11
|
+
// Modules read lazily (load cycles), each resolved once: a require() per
|
|
12
|
+
// call in hot paths was measurable (fix #436).
|
|
13
|
+
let lazyJavaUnicodeModuleCache = null;
|
|
14
|
+
const lazyJavaUnicodeModule = () => lazyJavaUnicodeModuleCache || (lazyJavaUnicodeModuleCache = require('./java-unicode'));
|
|
15
|
+
|
|
11
16
|
// Lazy-loaded tree-sitter
|
|
12
17
|
let TreeSitter = null;
|
|
13
18
|
|
|
@@ -33,6 +38,9 @@ function protocolMembers(rules) {
|
|
|
33
38
|
const named = rule.pattern ? rule.pattern.test(name) : rule.names.includes(name);
|
|
34
39
|
if (!named) continue;
|
|
35
40
|
if (rule.member && ctx.isMember === false) continue;
|
|
41
|
+
// A member type alias (fix #427: `typedef int& reference;`).
|
|
42
|
+
if (rule.typeMember && !ctx.isTypeMember) continue;
|
|
43
|
+
if (!rule.typeMember && ctx.isTypeMember) continue;
|
|
36
44
|
// Owner kinds the runtime exempts from the protocol (fix #392:
|
|
37
45
|
// Java enum constants serialize by name and ignore the callbacks).
|
|
38
46
|
if (rule.exceptOwnerKinds && typeof ctx.ownerKinds === 'function' &&
|
|
@@ -96,6 +104,40 @@ const JAVA_LANG_NOT_SERIALIZABLE = ['Object', 'Runnable', 'AutoCloseable', 'Comp
|
|
|
96
104
|
|
|
97
105
|
const STRUCTURAL_TRAITS = {
|
|
98
106
|
typeSystem: 'structural',
|
|
107
|
+
// A write on the instance can replace an inherited method with a
|
|
108
|
+
// callable value, including a wrapper of the previous method.
|
|
109
|
+
instanceAttributesShadowMethods: true,
|
|
110
|
+
// An external type can supply an inherent method before a project
|
|
111
|
+
// trait implementation at the same receiver probe step.
|
|
112
|
+
inherentMethodsPrecedeTraitImpls: false,
|
|
113
|
+
// Field access follows proven dereference wrappers on a return value.
|
|
114
|
+
derefFieldAccess: false,
|
|
115
|
+
// Whether importing a module runs its top-level code when the importer
|
|
116
|
+
// loads (JS/TS/HTML scripts, Python): only then is an import cycle an
|
|
117
|
+
// import-time cycle (fix #433).
|
|
118
|
+
importsRunModules: true,
|
|
119
|
+
// The receiver keyword whose member lookup starts at the enclosing
|
|
120
|
+
// class's bases, skipping its own members (`super.m()`, Python
|
|
121
|
+
// `super().m()`, C# `base.M()`), or null (fix #428).
|
|
122
|
+
superReceiver: 'super',
|
|
123
|
+
// The methods whose own receiver constructs their class (fix #434):
|
|
124
|
+
// `new this(..)` in a static method, `new this.constructor(..)` in an
|
|
125
|
+
// instance method. `binding` is the parser's 'class' or 'instance'.
|
|
126
|
+
ownClassMethod: (method, binding) => binding === 'class' ? method.type === 'static' : method.type !== 'static',
|
|
127
|
+
// Whether files without module syntax share one global scope (classic
|
|
128
|
+
// scripts): their top-level declarations are globals (fix #434).
|
|
129
|
+
scriptsShareGlobalScope: true,
|
|
130
|
+
plainQueryTree: true,
|
|
131
|
+
physicalCallTokenSyntax: true,
|
|
132
|
+
scopeAlternativeBindings: false,
|
|
133
|
+
nameReferenceFamily: 'js',
|
|
134
|
+
staticValueImportSyntax: null,
|
|
135
|
+
implicitEnumCaseLabels: false,
|
|
136
|
+
valuePatternConstants: false,
|
|
137
|
+
moduleValueLookup: false,
|
|
138
|
+
typeArgumentValues: null,
|
|
139
|
+
separateStaticStorage: true,
|
|
140
|
+
valueScopes: null,
|
|
99
141
|
// A type's identity is its declaring module (a source file or inline
|
|
100
142
|
// module), not the directory (fix #384): two same-name types in two
|
|
101
143
|
// modules of one directory are distinct (JS/TS, Python modules, Rust
|
|
@@ -112,6 +154,9 @@ const STRUCTURAL_TRAITS = {
|
|
|
112
154
|
// 'namespace-usings' (C#: enclosing namespaces, then using directives,
|
|
113
155
|
// global usings and project-file <Using> items), or null.
|
|
114
156
|
typeNameScoping: null,
|
|
157
|
+
typeNameSourceCanonical: null,
|
|
158
|
+
typeNameOwnersAt: null,
|
|
159
|
+
implementationOwnerSyntax: null,
|
|
115
160
|
// Types every file imports on demand without writing it (Java java.lang,
|
|
116
161
|
// JLS 7.3): { module, names }. A project type of the same name in another
|
|
117
162
|
// package is visible only through an import.
|
|
@@ -128,7 +173,23 @@ const STRUCTURAL_TRAITS = {
|
|
|
128
173
|
// signature must not use `= value` syntax (Go/Java/Rust).
|
|
129
174
|
hasDefaultParams: true,
|
|
130
175
|
allMethodsVirtual: false,
|
|
176
|
+
// A class member fills the slot of every supertype declaring that member
|
|
177
|
+
// (an override of `A.m` in `D(A, B)` overrides `B.m` too), and a member a
|
|
178
|
+
// class inherits implements its own interfaces' members (TS `class Impl
|
|
179
|
+
// extends Base implements Bean`): plan's rename closure climbs from
|
|
180
|
+
// every slot holder (fix #426). memberHidingModifier: the modifier of a
|
|
181
|
+
// member that hides the inherited one instead (C# `new`).
|
|
182
|
+
memberFillsSupertypeSlots: true,
|
|
183
|
+
inheritedMemberFillsSlots: true,
|
|
184
|
+
memberHidingModifier: null,
|
|
185
|
+
virtualMemberModifiers: null,
|
|
131
186
|
hasArityOverloads: false,
|
|
187
|
+
userDefinedConversions: null,
|
|
188
|
+
overloadPhases: null,
|
|
189
|
+
overloadFileSymbols: false,
|
|
190
|
+
inheritedOverloadSignatures: false,
|
|
191
|
+
// Interface instance members join lookup after the superclass chain.
|
|
192
|
+
interfaceMembersInMethodLookup: false,
|
|
132
193
|
// Whether `from pkg import name` can bind a SUBMODULE file as a plain
|
|
133
194
|
// name (fix #224). Python sets true: graph-build resolves the composed
|
|
134
195
|
// dotted specifier and records it in moduleResolved, making the receiver
|
|
@@ -155,6 +216,31 @@ const STRUCTURAL_TRAITS = {
|
|
|
155
216
|
// inside a class means this.execute(), and static imports bind foreign
|
|
156
217
|
// class methods to bare names (fix #220).
|
|
157
218
|
bareCallReachesMethods: false,
|
|
219
|
+
// A function declared in a function body is a binding of that body
|
|
220
|
+
// (JS/TS function scope, fix #423; Python defs, fix #402): a bare name
|
|
221
|
+
// outside the enclosing function never names it.
|
|
222
|
+
nestedItemsBlockScoped: true,
|
|
223
|
+
// Whether a declaration binds its name in its whole scope whatever its
|
|
224
|
+
// position (JS/TS: function declarations hoist, `let`/`const`/`class`
|
|
225
|
+
// names resolve statically; fix #423). Python binds names as statements
|
|
226
|
+
// run, so a module-level reference sees only earlier bindings.
|
|
227
|
+
staticModuleScope: true,
|
|
228
|
+
// Where a bare (receiver-less) name can denote a class or enum MEMBER
|
|
229
|
+
// value when bare names never reach methods (fix #420): 'declaration-body'
|
|
230
|
+
// (JS/TS: only inside the enum or namespace declaring it), 'class-body'
|
|
231
|
+
// (Python: directly in the class body, never in its methods), 'imports'
|
|
232
|
+
// (Rust: enum variants a `use` brings in), 'none' (Go struct fields, C).
|
|
233
|
+
// Imports in these languages never name a member either.
|
|
234
|
+
bareValueMemberScope: 'declaration-body',
|
|
235
|
+
// An enum member names a type of its own (TS literal enum member types:
|
|
236
|
+
// `kind: Kind.Text` in an annotation reads the member, fix #431).
|
|
237
|
+
enumMemberTypes: true,
|
|
238
|
+
// A type path can name a field (`T::f` for a static member): Rust sets
|
|
239
|
+
// false (fix #431).
|
|
240
|
+
typePathReachesFields: true,
|
|
241
|
+
// Classes whose synthesized initializer takes their fields as keyword
|
|
242
|
+
// parameters (Python dataclasses, NamedTuple, TypedDict), or null.
|
|
243
|
+
fieldInitializers: null,
|
|
158
244
|
// A method-shaped call CAN reach a standalone function here: attribute
|
|
159
245
|
// assignment rebinds functions onto objects (obj.print = print), so the
|
|
160
246
|
// #218b gate routes such calls visible instead of excluding (fix #220).
|
|
@@ -165,6 +251,24 @@ const STRUCTURAL_TRAITS = {
|
|
|
165
251
|
// Whether `Type(...)` constructs a class without a `new` token. Python
|
|
166
252
|
// classes are ordinary callable objects; JS/TS classes require `new`.
|
|
167
253
|
classesCallableWithoutNew: false,
|
|
254
|
+
hasConstructors: true,
|
|
255
|
+
fixedConstructorName: 'constructor',
|
|
256
|
+
constructorArgumentNodes: { delegation: { nodeType: 'call_expression', argsField: 'arguments' } },
|
|
257
|
+
functionalTypeConstruction: false,
|
|
258
|
+
constructorInheritance: { order: 'single', classNodes: ['class_declaration', 'class'], headerNode: 'class_heritage' },
|
|
259
|
+
implicitBaseConstruction: null,
|
|
260
|
+
// Whether a constructor delegation is spelled by a keyword (`this(..)`,
|
|
261
|
+
// `super(..)`, `base(..)`) rather than by the type's name (C++
|
|
262
|
+
// mem-initializers): such a site holds no token a type rename edits
|
|
263
|
+
// (fix #421).
|
|
264
|
+
keywordConstructorDelegation: false,
|
|
265
|
+
constructorUsesAreTypeReferences: false,
|
|
266
|
+
packExpansionArguments: false,
|
|
267
|
+
// Whether a call may pass more or fewer arguments than the callee
|
|
268
|
+
// declares without error (JavaScript): argument count then never decides
|
|
269
|
+
// which one callable runs. TypeScript reports the mismatch at compile time
|
|
270
|
+
// and Python raises at run time, so there it stays evidence (fix #421).
|
|
271
|
+
lenientCallArity: false,
|
|
168
272
|
// Whether a decorator REPLACES the callable it decorates with its own
|
|
169
273
|
// return value (Python/JS decorators, fix #364). What a decorated async
|
|
170
274
|
// function's call returns is then decided by the decorator, not by the
|
|
@@ -212,6 +316,11 @@ const STRUCTURAL_TRAITS = {
|
|
|
212
316
|
// `Func<int> f = Build`): plan renames it by the language's simple-name
|
|
213
317
|
// lookup. Java spells method values apart (`Type::m`).
|
|
214
318
|
methodGroupReferences: false,
|
|
319
|
+
methodGroupReceiver: null,
|
|
320
|
+
// AST terminal-name test for invocations wrapped in generic syntax.
|
|
321
|
+
isInvokedName: null,
|
|
322
|
+
accessorReferenceShape: null,
|
|
323
|
+
accessorTypeSyntax: null,
|
|
215
324
|
// Whether a class may declare a field and a method of one name, so a
|
|
216
325
|
// paren-less member access (`this.size`) names the field and a method
|
|
217
326
|
// value is spelled apart (`obj::m`, `Type::m`) (fix #390: Java, Rust).
|
|
@@ -262,10 +371,42 @@ const STRUCTURAL_TRAITS = {
|
|
|
262
371
|
};
|
|
263
372
|
const NOMINAL_TRAITS = {
|
|
264
373
|
typeSystem: 'nominal',
|
|
374
|
+
instanceAttributesShadowMethods: false,
|
|
375
|
+
inherentMethodsPrecedeTraitImpls: false,
|
|
376
|
+
derefFieldAccess: false,
|
|
377
|
+
importsRunModules: false,
|
|
378
|
+
superReceiver: null,
|
|
379
|
+
ownClassMethod: null,
|
|
380
|
+
scriptsShareGlobalScope: false,
|
|
381
|
+
hasConstructors: false,
|
|
382
|
+
fixedConstructorName: null,
|
|
383
|
+
constructorInheritance: null,
|
|
384
|
+
implicitBaseConstruction: null,
|
|
385
|
+
keywordConstructorDelegation: false,
|
|
386
|
+
constructorUsesAreTypeReferences: false,
|
|
387
|
+
packExpansionArguments: false,
|
|
388
|
+
// Whether a member may be defined outside its class body (C++
|
|
389
|
+
// `W::W(int) {}` in a source file, its class in a header): such a
|
|
390
|
+
// definition holds the body of one in-class declaration (fix #421).
|
|
391
|
+
outOfClassMemberDefinitions: false,
|
|
392
|
+
plainQueryTree: true,
|
|
393
|
+
physicalCallTokenSyntax: true,
|
|
394
|
+
scopeAlternativeBindings: false,
|
|
395
|
+
nameReferenceFamily: null,
|
|
396
|
+
staticValueImportSyntax: null,
|
|
397
|
+
implicitEnumCaseLabels: false,
|
|
398
|
+
valuePatternConstants: false,
|
|
399
|
+
moduleValueLookup: false,
|
|
400
|
+
typeArgumentValues: null,
|
|
401
|
+
separateStaticStorage: false,
|
|
402
|
+
valueScopes: null,
|
|
265
403
|
moduleTypeIdentity: false,
|
|
266
404
|
standardPathRoots: [],
|
|
267
405
|
typeNameScoping: null,
|
|
406
|
+
typeNameSourceCanonical: null,
|
|
407
|
+
typeNameOwnersAt: null,
|
|
268
408
|
implicitTypeImport: null,
|
|
409
|
+
implementationOwnerSyntax: null,
|
|
269
410
|
methodCallInclusion: 'auto',
|
|
270
411
|
packageScope: 'file',
|
|
271
412
|
hasReceiverPackageCalls: false,
|
|
@@ -291,11 +432,25 @@ const NOMINAL_TRAITS = {
|
|
|
291
432
|
// sets and Rust inherent methods bind statically — only interface/trait
|
|
292
433
|
// receivers dispatch there, which is detected per-type, not per-language.
|
|
293
434
|
allMethodsVirtual: false,
|
|
435
|
+
// See STRUCTURAL_TRAITS (fix #426): Go and Rust members never fill
|
|
436
|
+
// other supertypes' slots (structural satisfaction and trait impls have
|
|
437
|
+
// closures of their own); Java, C# and C++ override.
|
|
438
|
+
memberFillsSupertypeSlots: false,
|
|
439
|
+
inheritedMemberFillsSlots: false,
|
|
440
|
+
memberHidingModifier: null,
|
|
441
|
+
virtualMemberModifiers: null,
|
|
294
442
|
// Whether one class can define several same-name methods differing only
|
|
295
443
|
// in parameters (Java overloading). Drives the overload discipline in
|
|
296
444
|
// the caller contract: a pinned overload is only confirmed when the call
|
|
297
445
|
// site provably binds it.
|
|
298
446
|
hasArityOverloads: false,
|
|
447
|
+
// User-defined conversions keep otherwise incompatible argument types
|
|
448
|
+
// possible; selecting an overload still needs a positive conversion proof.
|
|
449
|
+
userDefinedConversions: null,
|
|
450
|
+
overloadPhases: null,
|
|
451
|
+
overloadFileSymbols: false,
|
|
452
|
+
inheritedOverloadSignatures: false,
|
|
453
|
+
interfaceMembersInMethodLookup: false,
|
|
299
454
|
// What a TYPE-QUALIFIED method call looks like, so a receiver that merely
|
|
300
455
|
// shares the target type's NAME isn't mistaken for the type itself:
|
|
301
456
|
// 'static' — Type.method() static form, any arity (Java).
|
|
@@ -324,6 +479,10 @@ const NOMINAL_TRAITS = {
|
|
|
324
479
|
// cobra/grpc-go-measured). Java overrides true (implicit this-calls,
|
|
325
480
|
// static imports).
|
|
326
481
|
bareCallReachesMethods: false,
|
|
482
|
+
bareValueMemberScope: 'none',
|
|
483
|
+
enumMemberTypes: false,
|
|
484
|
+
typePathReachesFields: true,
|
|
485
|
+
fieldInitializers: null,
|
|
327
486
|
// Whether a method-shaped call (x.f()) can reach a standalone FUNCTION:
|
|
328
487
|
// Go func-typed fields are name-callable (s.Run() may invoke a stored
|
|
329
488
|
// function), so exclusion needs !bindingId there; Rust requires (s.f)()
|
|
@@ -346,6 +505,8 @@ const NOMINAL_TRAITS = {
|
|
|
346
505
|
// methods — false. Per-language override, not preset-wide.
|
|
347
506
|
memberAccessNeverMethod: false,
|
|
348
507
|
classesCallableWithoutNew: false,
|
|
508
|
+
constructorArgumentNodes: {},
|
|
509
|
+
functionalTypeConstruction: false,
|
|
349
510
|
decoratorsWrapCallables: false,
|
|
350
511
|
callableDecorators: null,
|
|
351
512
|
knownAsyncGlobals: null,
|
|
@@ -361,6 +522,11 @@ const NOMINAL_TRAITS = {
|
|
|
361
522
|
docCrefReferences: false,
|
|
362
523
|
// Simple-name method groups (fix #395, C#).
|
|
363
524
|
methodGroupReferences: false,
|
|
525
|
+
methodGroupReceiver: null,
|
|
526
|
+
// AST terminal-name test for invocations wrapped in generic syntax.
|
|
527
|
+
isInvokedName: null,
|
|
528
|
+
accessorReferenceShape: null,
|
|
529
|
+
accessorTypeSyntax: null,
|
|
364
530
|
// A static import of a type brings only the members the type itself
|
|
365
531
|
// declares, never inherited ones (fix #392, C# `using static`). Java's
|
|
366
532
|
// static imports reach inherited static members.
|
|
@@ -438,6 +604,7 @@ const LANGUAGES = {
|
|
|
438
604
|
languageProtocolMember: JS_PROTOCOL_MEMBERS,
|
|
439
605
|
storedPromises: true,
|
|
440
606
|
knownAsyncGlobals: ['fetch'],
|
|
607
|
+
lenientCallArity: true,
|
|
441
608
|
testFileCandidates: (base, ext) => [`${base}.test${ext}`, `${base}.spec${ext}`, `${base}.test.ts`, `${base}.test.js`, `${base}.spec.ts`, `${base}.spec.js`],
|
|
442
609
|
testDirs: ['__tests__'],
|
|
443
610
|
},
|
|
@@ -485,6 +652,21 @@ const LANGUAGES = {
|
|
|
485
652
|
traits: {
|
|
486
653
|
...STRUCTURAL_TRAITS,
|
|
487
654
|
selfParam: ['self', 'cls'],
|
|
655
|
+
// `cls(..)` in a classmethod (or an implicit one), `type(self)(..)`
|
|
656
|
+
// and `self.__class__(..)` in an instance method construct the
|
|
657
|
+
// method's class through its first parameter (fix #434).
|
|
658
|
+
ownClassMethod: (method, binding, receiver) => method.paramsStructured?.[0]?.name === receiver &&
|
|
659
|
+
(binding === 'class'
|
|
660
|
+
? method.type === 'classmethod' || ['__init_subclass__', '__class_getitem__'].includes(method.name)
|
|
661
|
+
: !['classmethod', 'staticmethod'].includes(method.type) && method.name !== '__new__'),
|
|
662
|
+
// An inherited member shadows other bases' members in the MRO,
|
|
663
|
+
// no interface contract: not modeled as slot evidence (fix #426).
|
|
664
|
+
inheritedMemberFillsSlots: false,
|
|
665
|
+
memberLookupOrder: 'c3',
|
|
666
|
+
fixedConstructorName: null,
|
|
667
|
+
nameReferenceFamily: 'python',
|
|
668
|
+
scriptsShareGlobalScope: false,
|
|
669
|
+
separateStaticStorage: false,
|
|
488
670
|
// fix #224: `from pkg import name` may bind a SUBMODULE file, not
|
|
489
671
|
// a symbol — graph-build resolves the composed dotted specifier
|
|
490
672
|
// and query code treats such receivers as module receivers. JS
|
|
@@ -493,10 +675,24 @@ const LANGUAGES = {
|
|
|
493
675
|
// `__x` (not a dunder) is name-mangled per class (fix #397).
|
|
494
676
|
privateMemberName: name => /^__/.test(String(name)) && !/__$/.test(String(name)),
|
|
495
677
|
classesCallableWithoutNew: true,
|
|
678
|
+
constructorInheritance: { order: 'c3', classNodes: ['class_definition'], headerField: 'superclasses', keywordNode: 'keyword_argument' },
|
|
679
|
+
constructorProtocol: { initializer: '__init__', allocator: '__new__', metaclass: 'metaclass', builtinRoot: 'object',
|
|
680
|
+
functionNode: 'function_definition', classNode: 'class_definition',
|
|
681
|
+
headerField: 'superclasses', keywordNode: 'keyword_argument' },
|
|
496
682
|
// Call sites bind by parameter name (f(x=1)); signatures carry
|
|
497
683
|
// keyword-only (`*`) and positional-only (`/`) markers (fix #281).
|
|
498
684
|
keywordArguments: true,
|
|
499
685
|
assignmentDeclaresLocal: true,
|
|
686
|
+
bareValueMemberScope: 'class-body',
|
|
687
|
+
enumMemberTypes: false,
|
|
688
|
+
// Classes whose initializer the standard library synthesizes from
|
|
689
|
+
// their own fields (fix #431): a keyword argument of their
|
|
690
|
+
// construction names a field. Resolved qualified names.
|
|
691
|
+
fieldInitializers: {
|
|
692
|
+
decorators: ['dataclasses.dataclass'],
|
|
693
|
+
bases: ['typing.NamedTuple', 'typing_extensions.NamedTuple',
|
|
694
|
+
'typing.TypedDict', 'typing_extensions.TypedDict'],
|
|
695
|
+
},
|
|
500
696
|
// Calling an async def creates a coroutine object in any scope:
|
|
501
697
|
// audit-async checks such calls in sync functions too, and
|
|
502
698
|
// follows a local assigned from the call to the uses that need
|
|
@@ -507,10 +703,12 @@ const LANGUAGES = {
|
|
|
507
703
|
// f` / `except ImportError: def f`) is one item with an
|
|
508
704
|
// alternative per runtime configuration (fix #398F).
|
|
509
705
|
conditionalDefinitions: 'branch',
|
|
706
|
+
scopeAlternativeBindings: true,
|
|
510
707
|
// A def inside a function body binds a local of that function: a
|
|
511
708
|
// bare name outside it never names it (fix #402), unless the
|
|
512
709
|
// function declares the name `global`.
|
|
513
710
|
nestedItemsBlockScoped: true,
|
|
711
|
+
staticModuleScope: false,
|
|
514
712
|
// Decorators with a known effect on what calling the decorated
|
|
515
713
|
// function returns (fix #364), as resolved qualified names (a
|
|
516
714
|
// trailing `()` marks a decorator factory call). Any other
|
|
@@ -568,6 +766,8 @@ const LANGUAGES = {
|
|
|
568
766
|
...NOMINAL_TRAITS,
|
|
569
767
|
selfParam: null,
|
|
570
768
|
packageScope: 'directory',
|
|
769
|
+
nameReferenceFamily: 'go',
|
|
770
|
+
closedQueryBodies: ['function_declaration', 'method_declaration', 'func_literal'],
|
|
571
771
|
hasReceiverPackageCalls: true,
|
|
572
772
|
exportVisibility: 'capitalization',
|
|
573
773
|
hasDynamicImports: false,
|
|
@@ -581,6 +781,9 @@ const LANGUAGES = {
|
|
|
581
781
|
},
|
|
582
782
|
testFileCandidates: (base, ext) => [`${base}_test.go`],
|
|
583
783
|
nameBoundTestFunctions: GO_EXAMPLE_NAMES,
|
|
784
|
+
// One package-level name declared in files of one package under
|
|
785
|
+
// different build constraints is one item (fix #425).
|
|
786
|
+
conditionalDefinitions: 'build-constraint',
|
|
584
787
|
},
|
|
585
788
|
},
|
|
586
789
|
rust: {
|
|
@@ -592,18 +795,38 @@ const LANGUAGES = {
|
|
|
592
795
|
traits: {
|
|
593
796
|
...NOMINAL_TRAITS,
|
|
594
797
|
selfParam: ['self', '&self', '&mut self', 'mut self'],
|
|
798
|
+
inherentMethodsPrecedeTraitImpls: true,
|
|
799
|
+
derefFieldAccess: true,
|
|
800
|
+
nameReferenceFamily: 'rust',
|
|
801
|
+
// Members live in impl blocks, separate from the declaration
|
|
802
|
+
// of the type. Resolve the written self type in the impl scope.
|
|
803
|
+
implementationOwnerSyntax: { node: 'impl_item', field: 'type' },
|
|
804
|
+
staticEnumReferenceSyntax: true,
|
|
805
|
+
valuePatternConstants: true,
|
|
806
|
+
moduleValueLookup: true,
|
|
807
|
+
typeArgumentValues: 'generic-parameter',
|
|
808
|
+
// A struct's fields are reached through a value (`x.f`, struct
|
|
809
|
+
// expressions and patterns); a type path `T::f` names an
|
|
810
|
+
// associated item (fix #431).
|
|
811
|
+
typePathReachesFields: false,
|
|
595
812
|
hasDynamicImports: false,
|
|
596
813
|
moduleTypeIdentity: true,
|
|
597
814
|
// Same-scope definitions of one name are configuration
|
|
598
815
|
// alternatives selected by `#[cfg]` (fix #376).
|
|
599
816
|
conditionalDefinitions: 'attribute',
|
|
600
817
|
typeQualifiedCallStyle: 'path',
|
|
818
|
+
// A path segment's case tells a type from a module (CamelCase
|
|
819
|
+
// types, snake_case modules: the language's naming lints); C++
|
|
820
|
+
// namespaces are not case-coded, its qualifiers are resolved by
|
|
821
|
+
// name lookup (fix #427).
|
|
822
|
+
caseCodedPathQualifiers: true,
|
|
601
823
|
standardPathRoots: ['std', 'core', 'alloc'],
|
|
602
824
|
// Call records say whether their value is consumed where it is
|
|
603
825
|
// produced (`valueConsumed`, `consumingMethod`; fix #371).
|
|
604
826
|
callValueFacts: true,
|
|
605
827
|
memberAccessNeverMethod: true,
|
|
606
828
|
fieldsAndMethodsSeparate: true,
|
|
829
|
+
bareValueMemberScope: 'imports',
|
|
607
830
|
genericBoundDispatchClosed: true,
|
|
608
831
|
macroTemplateBodies: true,
|
|
609
832
|
// Macro invocations are written `name!(...)` / `#[name]`: a
|
|
@@ -612,6 +835,12 @@ const LANGUAGES = {
|
|
|
612
835
|
// A fn declared inside a fn body is an item of that block: a
|
|
613
836
|
// bare path outside the block never names it (fix #377).
|
|
614
837
|
nestedItemsBlockScoped: true,
|
|
838
|
+
// A name resolves through the scopes that bind it, innermost
|
|
839
|
+
// first: block items and `use` declarations, then the module's
|
|
840
|
+
// items and explicit `use` bindings, then its globs, with types,
|
|
841
|
+
// values and macros in separate namespaces (fix #422,
|
|
842
|
+
// core/rust-names.js).
|
|
843
|
+
itemScopeResolution: true,
|
|
615
844
|
// Names every module sees without a `use` (the std prelude of
|
|
616
845
|
// editions 2015-2024 and the primitive types): a name no `use`,
|
|
617
846
|
// glob or item binds must be one of them, or come from a macro
|
|
@@ -636,11 +865,39 @@ const LANGUAGES = {
|
|
|
636
865
|
treeSitterLang: 'java',
|
|
637
866
|
module: () => require('./java'),
|
|
638
867
|
treeSitterModule: () => require('tree-sitter-java'),
|
|
868
|
+
// tree-sitter-java misreads a type annotation before a variable
|
|
869
|
+
// arity parameter's `...` (`Object @Nullable ... args`, JLS 8.4.1).
|
|
870
|
+
parseRecovery: () => require('./java').recoverTypeAnnotatedVarargs,
|
|
639
871
|
traits: {
|
|
640
872
|
...NOMINAL_TRAITS,
|
|
873
|
+
// A method overrides/implements every supertype's same-signature
|
|
874
|
+
// member, an inherited one included (JLS 8.4.8) (fix #426).
|
|
875
|
+
memberFillsSupertypeSlots: true,
|
|
876
|
+
inheritedMemberFillsSlots: true,
|
|
877
|
+
superReceiver: 'super',
|
|
878
|
+
hasConstructors: true,
|
|
879
|
+
implicitBaseConstruction: { classes: ['class_declaration'], headerField: 'superclass',
|
|
880
|
+
constructors: ['constructor_declaration'], delegationNodes: ['explicit_constructor_invocation'],
|
|
881
|
+
ownerScope: node => require('./java').implicitOwnerScope(node),
|
|
882
|
+
baseKinds: ['class'], separator: '.' },
|
|
883
|
+
keywordConstructorDelegation: true,
|
|
884
|
+
constructorArgumentNodes: {
|
|
885
|
+
delegation: { nodeType: 'explicit_constructor_invocation', argsField: 'arguments' },
|
|
886
|
+
enum: { nodeType: 'enum_constant', argsField: 'arguments' },
|
|
887
|
+
},
|
|
641
888
|
fieldsAndMethodsSeparate: true,
|
|
889
|
+
nameReferenceFamily: 'java',
|
|
890
|
+
staticEnumReferenceSyntax: true,
|
|
891
|
+
closedQueryBodies: ['method_declaration', 'constructor_declaration',
|
|
892
|
+
'compact_constructor_declaration', 'lambda_expression'],
|
|
893
|
+
staticValueImportSyntax: tree => require('./java').staticValueImportSyntax(tree),
|
|
894
|
+
// Pattern variables are scoped by the pattern's flow (fix #420).
|
|
895
|
+
patternBindingReach: (binding, reference) => require('./java').patternBindingReach(binding, reference),
|
|
896
|
+
implicitEnumCaseLabels: true,
|
|
642
897
|
standardPathRoots: ['java', 'javax'],
|
|
643
898
|
typeNameScoping: 'package-on-demand',
|
|
899
|
+
typeNameSourceCanonical: (source, parseError, lines) => lazyJavaUnicodeModule().typeNameSourceCanonical(source, parseError, lines),
|
|
900
|
+
typeNameOwnersAt: (source, site) => lazyJavaUnicodeModule().typeNameOwnersAt(source, site),
|
|
644
901
|
typeNamedSourceFile: true,
|
|
645
902
|
// The public top-level types of java.lang (JDK 8-21, preview
|
|
646
903
|
// included): a spec-level list, not project knowledge.
|
|
@@ -677,6 +934,10 @@ const LANGUAGES = {
|
|
|
677
934
|
selfParam: ['this'],
|
|
678
935
|
allMethodsVirtual: true,
|
|
679
936
|
hasArityOverloads: true,
|
|
937
|
+
overloadPhases: 'strict-loose-variable',
|
|
938
|
+
overloadFileSymbols: true,
|
|
939
|
+
inheritedOverloadSignatures: true,
|
|
940
|
+
interfaceMembersInMethodLookup: true,
|
|
680
941
|
universalSupertype: 'Object',
|
|
681
942
|
universalSupertypeMembers: { toString: 0, equals: 1, hashCode: 0, clone: 0, finalize: 0 },
|
|
682
943
|
// Serialization callbacks and fields the JVM uses reflectively.
|
|
@@ -718,6 +979,7 @@ const LANGUAGES = {
|
|
|
718
979
|
...NOMINAL_TRAITS,
|
|
719
980
|
selfParam: null,
|
|
720
981
|
packageScope: 'file',
|
|
982
|
+
nameReferenceFamily: 'c',
|
|
721
983
|
hasDynamicImports: false,
|
|
722
984
|
exportVisibility: 'linkage',
|
|
723
985
|
// Same-signature definitions in one file are `#if` alternatives.
|
|
@@ -727,6 +989,7 @@ const LANGUAGES = {
|
|
|
727
989
|
// spelled NAME( where #define NAME( is in effect is the macro
|
|
728
990
|
// (fix #377).
|
|
729
991
|
macroInvocationSyntax: 'call',
|
|
992
|
+
usageKindsOnly: true,
|
|
730
993
|
typeQualifiedCallStyle: 'static',
|
|
731
994
|
bareCallReachesMethods: false,
|
|
732
995
|
methodCallReachesFunctions: true,
|
|
@@ -744,6 +1007,27 @@ const LANGUAGES = {
|
|
|
744
1007
|
treeSitterModule: () => require('tree-sitter-cpp'),
|
|
745
1008
|
traits: {
|
|
746
1009
|
...NOMINAL_TRAITS,
|
|
1010
|
+
// An override overrides every base's virtual of its signature; an
|
|
1011
|
+
// inherited member never implements another base's pure virtual
|
|
1012
|
+
// (fix #426).
|
|
1013
|
+
memberFillsSupertypeSlots: true,
|
|
1014
|
+
virtualMemberModifiers: ['virtual', 'override'],
|
|
1015
|
+
hasConstructors: true,
|
|
1016
|
+
implicitBaseConstruction: { classes: ['class_specifier', 'struct_specifier'], headerNode: 'base_class_clause',
|
|
1017
|
+
constructors: ['function_definition', 'field_declaration', 'declaration'], defaultPotential: true,
|
|
1018
|
+
constructorInfo: (...args) => require('./c-family').implicitConstructorInfo(...args),
|
|
1019
|
+
ownerScope: node => require('./c-family').implicitOwnerScope(node),
|
|
1020
|
+
baseKinds: ['class', 'struct'], separator: '::' },
|
|
1021
|
+
functionalTypeConstruction: true,
|
|
1022
|
+
outOfClassMemberDefinitions: true,
|
|
1023
|
+
constructorArgumentNodes: { direct: { nodeType: 'init_declarator', argsField: 'value' },
|
|
1024
|
+
delegation: { nodeType: 'field_initializer', argsNodeType: 'argument_list' } },
|
|
1025
|
+
isInvokedName: (node, options) => require('./c-family').isInvokedName(node, options),
|
|
1026
|
+
nameReferenceFamily: 'c',
|
|
1027
|
+
typeArgumentValues: 'ordinary',
|
|
1028
|
+
// A call's arguments may expand a parameter pack (`f(params...)`):
|
|
1029
|
+
// the written count is not the argument count (fix #430).
|
|
1030
|
+
packExpansionArguments: true,
|
|
747
1031
|
selfParam: ['this'],
|
|
748
1032
|
packageScope: 'file',
|
|
749
1033
|
hasDynamicImports: false,
|
|
@@ -754,12 +1038,22 @@ const LANGUAGES = {
|
|
|
754
1038
|
// spelled NAME( where #define NAME( is in effect is the macro
|
|
755
1039
|
// (fix #377).
|
|
756
1040
|
macroInvocationSyntax: 'call',
|
|
1041
|
+
usageKindsOnly: true,
|
|
757
1042
|
typeQualifiedCallStyle: 'path',
|
|
758
1043
|
standardPathRoots: ['std'],
|
|
759
1044
|
hasArityOverloads: true,
|
|
1045
|
+
userDefinedConversions: 'constructors-and-operators',
|
|
760
1046
|
// Range-for lowers onto member begin()/end() with no name token.
|
|
1047
|
+
// The standard library's traits read member types by name
|
|
1048
|
+
// (fix #427): std::iterator_traits (value_type, difference_type,
|
|
1049
|
+
// pointer, reference, iterator_category, iterator_concept),
|
|
1050
|
+
// std::pointer_traits (element_type), container adaptors
|
|
1051
|
+
// (size_type, const_reference), transparent comparators.
|
|
761
1052
|
languageProtocolMember: protocolMembers([
|
|
762
1053
|
{ names: ['begin', 'end'], member: true },
|
|
1054
|
+
{ names: ['value_type', 'difference_type', 'pointer', 'reference', 'iterator_category',
|
|
1055
|
+
'iterator_concept', 'element_type', 'size_type', 'const_reference', 'is_transparent'],
|
|
1056
|
+
member: true, typeMember: true },
|
|
763
1057
|
]),
|
|
764
1058
|
// C++ instance dispatch is virtual only when the declaration
|
|
765
1059
|
// explicitly says virtual/override (unlike Java's implicit rule).
|
|
@@ -782,21 +1076,61 @@ const LANGUAGES = {
|
|
|
782
1076
|
treeSitterModule: () => require('tree-sitter-c-sharp'),
|
|
783
1077
|
traits: {
|
|
784
1078
|
...NOMINAL_TRAITS,
|
|
1079
|
+
// Interface mapping takes inherited members (C# spec 18.6.5); a
|
|
1080
|
+
// `new` member hides the inherited one, starting a slot of its
|
|
1081
|
+
// own (fix #426).
|
|
1082
|
+
memberFillsSupertypeSlots: true,
|
|
1083
|
+
inheritedMemberFillsSlots: true,
|
|
1084
|
+
superReceiver: 'base',
|
|
1085
|
+
memberHidingModifier: 'new',
|
|
1086
|
+
virtualMemberModifiers: ['virtual', 'abstract', 'override'],
|
|
1087
|
+
hasConstructors: true,
|
|
1088
|
+
implicitBaseConstruction: { classes: ['class_declaration', 'record_declaration'], headerNode: 'base_list',
|
|
1089
|
+
constructors: ['constructor_declaration'], delegationNodes: ['constructor_initializer'],
|
|
1090
|
+
ownerScope: node => require('./csharp').implicitOwnerScope(node),
|
|
1091
|
+
firstBaseOnly: true, referenceTypesOnly: true, baseKinds: ['class', 'record'], separator: '.' },
|
|
1092
|
+
keywordConstructorDelegation: true,
|
|
1093
|
+
// A use of a constructor is a use of its type (fix #430): a
|
|
1094
|
+
// `: this(..)` initializer depends on the type as `: base(..)`
|
|
1095
|
+
// depends on the base.
|
|
1096
|
+
constructorUsesAreTypeReferences: true,
|
|
1097
|
+
plainQueryTree: false,
|
|
1098
|
+
isInvokedName: (node, options) => require('./csharp').isInvokedName(node, options),
|
|
1099
|
+
nameReferenceFamily: 'csharp',
|
|
1100
|
+
staticEnumReferenceSyntax: true,
|
|
1101
|
+
enumReferenceContext: node => ({
|
|
1102
|
+
scopes: require('./csharp-scope').usingScopesOf(node),
|
|
1103
|
+
directives: require('./csharp').queryUsingDirectives(node.tree),
|
|
1104
|
+
}),
|
|
1105
|
+
closedQueryBodies: ['method_declaration', 'constructor_declaration', 'destructor_declaration',
|
|
1106
|
+
'operator_declaration', 'conversion_operator_declaration', 'local_function_statement',
|
|
1107
|
+
'accessor_declaration', 'lambda_expression', 'anonymous_method_expression'],
|
|
1108
|
+
queryBodyViews: tree => require('./csharp').queryBodyViews(tree),
|
|
1109
|
+
queryBodyTree: (...args) => require('./csharp').queryBodyTree(...args),
|
|
785
1110
|
standardPathRoots: ['System'],
|
|
786
1111
|
conditionalDefinitions: 'preprocessor',
|
|
787
1112
|
typeNameScoping: 'namespace-usings',
|
|
1113
|
+
constructorArgumentNodes: { delegation: { nodeType: 'constructor_initializer', argsNodeType: 'argument_list' } },
|
|
788
1114
|
genericArityIsIdentity: true,
|
|
789
1115
|
typeArgumentsFromArgumentsOnly: true,
|
|
790
1116
|
selfParam: ['this', 'base'],
|
|
791
1117
|
packageScope: 'namespace',
|
|
792
1118
|
hasDynamicImports: false,
|
|
793
1119
|
hasArityOverloads: true,
|
|
1120
|
+
userDefinedConversions: 'operators',
|
|
794
1121
|
bareCallReachesMethods: true,
|
|
1122
|
+
// The type the compiler synthesizes for top-level statements: a
|
|
1123
|
+
// local function there has no other class in lexical scope.
|
|
1124
|
+
topLevelStatementsType: 'Program',
|
|
1125
|
+
inheritedOverloadSignatures: true,
|
|
795
1126
|
typeQualifiedCallStyle: 'static',
|
|
796
1127
|
universalSupertype: 'Object',
|
|
797
1128
|
universalSupertypeMembers: { ToString: 0, Equals: 1, GetHashCode: 0, Finalize: 0 },
|
|
798
1129
|
docCrefReferences: true,
|
|
799
1130
|
methodGroupReferences: true,
|
|
1131
|
+
methodGroupReceiver: node => require('./csharp').methodGroupReceiver(node),
|
|
1132
|
+
accessorReferenceShape: (tree, usage) => require('./csharp').accessorReferenceShape(tree, usage),
|
|
1133
|
+
accessorTypeSyntax: text => require('./csharp').accessorTypeSyntax(text),
|
|
800
1134
|
staticImportsDeclaredOnly: true,
|
|
801
1135
|
// Pattern-bound members the compiler lowers syntax onto
|
|
802
1136
|
// (foreach, await, deconstruction) - invoked with no name token.
|
|
@@ -844,6 +1178,22 @@ const LANGUAGES = {
|
|
|
844
1178
|
treeSitterModule: () => require('tree-sitter-html'),
|
|
845
1179
|
traits: {
|
|
846
1180
|
...STRUCTURAL_TRAITS,
|
|
1181
|
+
lenientCallArity: true,
|
|
1182
|
+
// Embedded scripts supply their own parse trees.
|
|
1183
|
+
physicalCallTokenSyntax: false,
|
|
1184
|
+
// The script source with its rows and columns kept, parsed in its
|
|
1185
|
+
// own language where an edit reads tokens (fix #419).
|
|
1186
|
+
embeddedSyntax: { language: 'javascript', source: (content, parser) => {
|
|
1187
|
+
const html = require('./html');
|
|
1188
|
+
return html.buildVirtualJSContent(content, html.extractScriptBlocks(content, parser));
|
|
1189
|
+
} },
|
|
1190
|
+
constructorInheritance: { ...STRUCTURAL_TRAITS.constructorInheritance, syntaxLanguage: 'javascript',
|
|
1191
|
+
source: (content, parser) => {
|
|
1192
|
+
const html = require('./html');
|
|
1193
|
+
return html.buildVirtualJSContent(content, html.extractScriptBlocks(content, parser));
|
|
1194
|
+
} },
|
|
1195
|
+
valueScopes: (content, parser) => require('./html')
|
|
1196
|
+
.extractScriptBlocks(content, parser, { includeScopes: true }),
|
|
847
1197
|
selfParam: ['this'],
|
|
848
1198
|
storedPromises: true,
|
|
849
1199
|
knownAsyncGlobals: ['fetch'],
|
|
@@ -981,7 +1331,14 @@ function _installNodeFieldCaches(TS) {
|
|
|
981
1331
|
Object.defineProperty(base, NAMED_CHILDREN_LIST, {
|
|
982
1332
|
configurable: true,
|
|
983
1333
|
writable: true,
|
|
984
|
-
value() {
|
|
1334
|
+
value(parent) {
|
|
1335
|
+
const children = namedList(this);
|
|
1336
|
+
// The traversal already knows this native child edge.
|
|
1337
|
+
// Keep leaf facts lazy: an empty list alone needs none.
|
|
1338
|
+
const facts = this[NODE_FACTS];
|
|
1339
|
+
if (parent !== undefined && facts !== undefined) facts.parent = parent;
|
|
1340
|
+
return children;
|
|
1341
|
+
},
|
|
985
1342
|
});
|
|
986
1343
|
Object.defineProperty(base, 'namedChildren', {
|
|
987
1344
|
configurable: true,
|
|
@@ -1145,9 +1502,13 @@ function getParser(language) {
|
|
|
1145
1502
|
}
|
|
1146
1503
|
|
|
1147
1504
|
parsers[language] = parser;
|
|
1505
|
+
parserLanguages.set(parser, language);
|
|
1148
1506
|
return parser;
|
|
1149
1507
|
}
|
|
1150
1508
|
|
|
1509
|
+
// The language each cached parser reads, for grammar-gap recovery (fix #428).
|
|
1510
|
+
const parserLanguages = new WeakMap();
|
|
1511
|
+
|
|
1151
1512
|
/**
|
|
1152
1513
|
* Detect language from file path
|
|
1153
1514
|
* @param {string} filePath - File path
|
|
@@ -1241,10 +1602,32 @@ function getParseOptions(contentLength = 0) {
|
|
|
1241
1602
|
let _lastParseParser = null;
|
|
1242
1603
|
let _lastParseContent = null;
|
|
1243
1604
|
let _lastParseTree = null;
|
|
1605
|
+
// The plain parse of the file an analysis reads (fix #436): a language may
|
|
1606
|
+
// parse other views of the source after it (recoveries, configurations),
|
|
1607
|
+
// and an index-time fact of the literal tree then needs no second parse.
|
|
1608
|
+
let _literalCapture = null;
|
|
1609
|
+
|
|
1610
|
+
/** Remember the tree of the next plain parse of exactly (parser, content). */
|
|
1611
|
+
function captureLiteralParse(parser, content) {
|
|
1612
|
+
_literalCapture = { parser, content, tree: null };
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
/** The tree captureLiteralParse remembered (null if none), ending the capture. */
|
|
1616
|
+
function takeLiteralParse() {
|
|
1617
|
+
const capture = _literalCapture;
|
|
1618
|
+
_literalCapture = null;
|
|
1619
|
+
return capture?.tree || null;
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
function noteLiteralParse(parser, content, tree) {
|
|
1623
|
+
if (_literalCapture && !_literalCapture.tree && tree && parser === _literalCapture.parser &&
|
|
1624
|
+
content === _literalCapture.content) _literalCapture.tree = tree;
|
|
1625
|
+
}
|
|
1244
1626
|
|
|
1245
1627
|
function safeParse(parser, content, oldTree = undefined, options = {}) {
|
|
1246
1628
|
// Fast path: return cached tree if same parser and content (no oldTree override)
|
|
1247
1629
|
if (!oldTree && parser === _lastParseParser && content === _lastParseContent && _lastParseTree) {
|
|
1630
|
+
noteLiteralParse(parser, content, _lastParseTree);
|
|
1248
1631
|
return _lastParseTree;
|
|
1249
1632
|
}
|
|
1250
1633
|
|
|
@@ -1266,12 +1649,22 @@ function safeParse(parser, content, oldTree = undefined, options = {}) {
|
|
|
1266
1649
|
let lastError;
|
|
1267
1650
|
for (const bufferSize of bufferSizes) {
|
|
1268
1651
|
try {
|
|
1269
|
-
|
|
1652
|
+
let tree = parser.parse(content, oldTree, { ...options, bufferSize });
|
|
1653
|
+
// A language whose grammar misses a construct of valid source
|
|
1654
|
+
// recovers that construct by a reparse with the construct's
|
|
1655
|
+
// inert tokens blanked (positions unchanged, fix #428).
|
|
1656
|
+
const recovery = oldTree ? null : LANGUAGES[parserLanguages.get(parser)]?.parseRecovery;
|
|
1657
|
+
if (recovery && tree?.rootNode?.hasError) {
|
|
1658
|
+
const recovered = recovery()(tree, content,
|
|
1659
|
+
text => parser.parse(text, undefined, { ...options, bufferSize }));
|
|
1660
|
+
if (recovered) tree = recovered;
|
|
1661
|
+
}
|
|
1270
1662
|
// Cache the result for same-(parser, content) reuse
|
|
1271
1663
|
if (!oldTree) {
|
|
1272
1664
|
_lastParseParser = parser;
|
|
1273
1665
|
_lastParseContent = content;
|
|
1274
1666
|
_lastParseTree = tree;
|
|
1667
|
+
noteLiteralParse(parser, content, tree);
|
|
1275
1668
|
}
|
|
1276
1669
|
return tree;
|
|
1277
1670
|
} catch (e) {
|
|
@@ -1313,6 +1706,8 @@ module.exports = {
|
|
|
1313
1706
|
PARSE_OPTIONS,
|
|
1314
1707
|
getParseOptions,
|
|
1315
1708
|
safeParse,
|
|
1709
|
+
captureLiteralParse,
|
|
1710
|
+
takeLiteralParse,
|
|
1316
1711
|
langTraits,
|
|
1317
1712
|
DEFAULT_BUFFER_SIZE,
|
|
1318
1713
|
MAX_BUFFER_SIZE
|