@cplieger/deadset-ts 8.0.0-dev.14 → 8.0.0-dev.16
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/dist/src/alias-chain.js +2 -2
- package/dist/src/analysis.js +43 -38
- package/dist/src/commands/read.js +6 -7
- package/dist/src/conformance-record.js +1 -1
- package/dist/src/consumers.js +4 -2
- package/dist/src/contract/config.generated.js +1 -1
- package/dist/src/contract/contract.generated.js +120 -2
- package/dist/src/dependencies.js +81 -49
- package/dist/src/entries/build-scripts.js +222 -0
- package/dist/src/{configuration-files.js → entries/configuration-files.js} +20 -58
- package/dist/src/{convention-rows.js → entries/convention-rows.js} +120 -27
- package/dist/src/entries/conventions.js +739 -0
- package/dist/src/{html-entries.js → entries/html-entries.js} +3 -3
- package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +2 -2
- package/dist/src/entries/run-directories.js +77 -0
- package/dist/src/entries/sources.js +144 -0
- package/dist/src/entries/static-module.js +669 -0
- package/dist/src/entries/test-runners.js +684 -0
- package/dist/src/{workflow-steps.js → entries/workflow-steps.js} +18 -8
- package/dist/src/extensions.js +37 -0
- package/dist/src/facts.js +38 -0
- package/dist/src/file-facts.js +1 -1
- package/dist/src/findings/emitters.js +5 -8
- package/dist/src/findings/self-check.js +36 -20
- package/dist/src/findings-pass.js +5 -6
- package/dist/src/framework-lifecycle.js +1 -1
- package/dist/src/fs/manifest.js +15 -20
- package/dist/src/generated-file.js +172 -29
- package/dist/src/graph.js +2 -5
- package/dist/src/index.js +1 -1
- package/dist/src/injection-container.js +1 -1
- package/dist/src/inventory/commonjs.js +507 -0
- package/dist/src/inventory/enumerate.js +167 -0
- package/dist/src/inventory/syntax.js +236 -0
- package/dist/src/inventory.js +305 -705
- package/dist/src/javascript-file.js +26 -11
- package/dist/src/load/classify.js +28 -9
- package/dist/src/load/diagnostics.js +8 -1
- package/dist/src/load/discover.js +16 -8
- package/dist/src/load/package-scope.js +56 -0
- package/dist/src/load/plan.js +2 -2
- package/dist/src/load/synthesize.js +5 -5
- package/dist/src/load/workspace-manifests.js +1 -1
- package/dist/src/matrix.js +6 -13
- package/dist/src/outside-tests.js +1 -1
- package/dist/src/paths.js +16 -0
- package/dist/src/platform-calls.js +78 -0
- package/dist/src/platform-symbols.js +140 -0
- package/dist/src/position.js +41 -0
- package/dist/src/ref.js +11 -20
- package/dist/src/references.js +281 -50
- package/dist/src/resolve.js +1 -1
- package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +4 -4
- package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +5 -8
- package/dist/src/{manifest.js → roots/manifest.js} +4 -4
- package/dist/src/roots/published-reach.js +412 -0
- package/dist/src/roots/root-set.js +489 -0
- package/dist/src/roots/unseen-loads.js +208 -0
- package/dist/src/serialization-contract.js +1 -1
- package/dist/src/session.js +3 -0
- package/dist/src/source-files.js +5 -9
- package/dist/src/suppress-inline.js +33 -81
- package/dist/src/suppress.js +30 -32
- package/dist/src/test-support.js +4 -2
- package/dist/src/verbs/analyze.js +13 -1
- package/dist/src/verbs/describe.js +5 -3
- package/jsr.json +1 -1
- package/package.json +3 -3
- package/src/alias-chain.ts +2 -2
- package/src/analysis.ts +77 -53
- package/src/automatic-types.ts +1 -1
- package/src/commands/read.ts +6 -8
- package/src/conformance-record.ts +1 -1
- package/src/consumers.ts +5 -1
- package/src/contract/config.generated.ts +1 -1
- package/src/contract/contract.generated.ts +139 -2
- package/src/dependencies.ts +98 -50
- package/src/entries/build-scripts.ts +292 -0
- package/src/{configuration-files.ts → entries/configuration-files.ts} +23 -75
- package/src/{convention-rows.ts → entries/convention-rows.ts} +167 -28
- package/src/{conventions.ts → entries/conventions.ts} +347 -522
- package/src/{html-entries.ts → entries/html-entries.ts} +5 -5
- package/src/{mdx-entries.ts → entries/mdx-entries.ts} +4 -4
- package/src/entries/run-directories.ts +108 -0
- package/src/entries/sources.ts +266 -0
- package/src/entries/static-module.ts +857 -0
- package/src/entries/test-runners.ts +868 -0
- package/src/{workflow-steps.ts → entries/workflow-steps.ts} +29 -11
- package/src/exempt.ts +3 -2
- package/src/extensions.ts +45 -0
- package/src/facts.ts +44 -0
- package/src/file-facts.ts +2 -2
- package/src/findings/emitters.ts +14 -10
- package/src/findings/self-check.ts +41 -22
- package/src/findings/visibility-narrowing.ts +1 -1
- package/src/findings-pass.ts +5 -12
- package/src/framework-lifecycle.ts +1 -1
- package/src/fs/manifest.ts +25 -21
- package/src/generated-file.ts +240 -36
- package/src/graph.ts +3 -6
- package/src/index.ts +1 -1
- package/src/injection-container.ts +1 -1
- package/src/inventory/commonjs.ts +696 -0
- package/src/inventory/enumerate.ts +203 -0
- package/src/inventory/syntax.ts +311 -0
- package/src/inventory.ts +424 -878
- package/src/javascript-file.ts +29 -12
- package/src/load/classify.ts +49 -13
- package/src/load/diagnostics.ts +11 -1
- package/src/load/discover.ts +28 -12
- package/src/load/package-scope.ts +74 -0
- package/src/load/plan.ts +11 -2
- package/src/load/synthesize.ts +6 -6
- package/src/load/test-globals.ts +1 -1
- package/src/load/workspace-manifests.ts +1 -1
- package/src/load/workspace-run.ts +1 -1
- package/src/matrix.ts +7 -14
- package/src/outside-tests.ts +1 -1
- package/src/paths.ts +18 -0
- package/src/platform-calls.ts +119 -0
- package/src/platform-symbols.ts +205 -0
- package/src/position.ts +42 -0
- package/src/ref.ts +11 -20
- package/src/references.ts +383 -73
- package/src/report.ts +1 -1
- package/src/resolve.ts +1 -1
- package/src/{configured-declarations.ts → roots/configured-declarations.ts} +7 -7
- package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +5 -8
- package/src/{manifest.ts → roots/manifest.ts} +5 -5
- package/src/roots/published-reach.ts +481 -0
- package/src/{roots.ts → roots/root-set.ts} +203 -630
- package/src/roots/unseen-loads.ts +307 -0
- package/src/serialization-contract.ts +1 -1
- package/src/session.ts +17 -1
- package/src/source-files.ts +5 -10
- package/src/suppress-inline.ts +53 -89
- package/src/suppress.ts +48 -33
- package/src/test-support.ts +8 -3
- package/src/verbs/analyze.ts +17 -4
- package/src/verbs/describe.ts +5 -2
- package/src/verbs/explain.ts +1 -1
- package/dist/src/build-scripts.js +0 -418
- package/dist/src/conventions.js +0 -907
- package/dist/src/entry-points.js +0 -513
- package/dist/src/roots.js +0 -865
- package/dist/src/unseen-loads.js +0 -100
- package/src/build-scripts.ts +0 -536
- package/src/entry-points.ts +0 -661
- package/src/unseen-loads.ts +0 -134
package/dist/src/position.js
CHANGED
|
@@ -25,6 +25,47 @@ export function isComponentFile(file) {
|
|
|
25
25
|
export function writtenLength(file) {
|
|
26
26
|
return isComponentFile(file) ? file.originalText.length : file.text.length;
|
|
27
27
|
}
|
|
28
|
+
/** Whether one character ends a line, under the language's line terminators. */
|
|
29
|
+
function endsLine(char) {
|
|
30
|
+
return char === "\n" || char === "\r" || char === "\u2028" || char === "\u2029";
|
|
31
|
+
}
|
|
32
|
+
/** The offset where the line holding `from` ends. */
|
|
33
|
+
export function lineEnd(text, from) {
|
|
34
|
+
let at = from;
|
|
35
|
+
while (at < text.length && !endsLine(text[at])) {
|
|
36
|
+
at += 1;
|
|
37
|
+
}
|
|
38
|
+
return at;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The offset of the first token at or after `from`: whitespace, comments and a leading
|
|
42
|
+
* hashbang are trivia.
|
|
43
|
+
*/
|
|
44
|
+
export function tokenStart(text, from) {
|
|
45
|
+
let at = from;
|
|
46
|
+
if (at === 0 && text.startsWith("#!")) {
|
|
47
|
+
at = lineEnd(text, 0);
|
|
48
|
+
}
|
|
49
|
+
for (;;) {
|
|
50
|
+
if (/\s/u.test(text[at] ?? "")) {
|
|
51
|
+
at += 1;
|
|
52
|
+
}
|
|
53
|
+
else if (text.startsWith("//", at)) {
|
|
54
|
+
at = lineEnd(text, at);
|
|
55
|
+
}
|
|
56
|
+
else if (text.startsWith("/*", at)) {
|
|
57
|
+
const close = text.indexOf("*/", at + 2);
|
|
58
|
+
at = close < 0 ? text.length : close + 2;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
return at;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** The line, counted from one, of the first token at or after one offset of one file. */
|
|
66
|
+
export function startLine(file, offset) {
|
|
67
|
+
return file.getLineAndCharacterOfPosition(tokenStart(file.text, offset)).line + 1;
|
|
68
|
+
}
|
|
28
69
|
/**
|
|
29
70
|
* The position of one offset of one file, rendered against the target root.
|
|
30
71
|
*
|
package/dist/src/ref.js
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The stable symbol reference: the identifier that names one declaration across
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* written.
|
|
8
|
-
*
|
|
9
|
-
* The position key of {@link ./position.ts} is the other identifier and has the
|
|
10
|
-
* other job: it locates a finding inside one run, and the two never mix.
|
|
2
|
+
* The stable symbol reference: the identifier that names one declaration across runs,
|
|
3
|
+
* reports, ignore entries, configured roots and cross-language edges. It is built from
|
|
4
|
+
* names and containers only, so an edit above a declaration leaves it unchanged, and it
|
|
5
|
+
* is compared as bytes, so this module writes the one canonical spelling. The position
|
|
6
|
+
* key of {@link ./position.ts} locates a finding inside one run; the two never mix.
|
|
11
7
|
*/
|
|
12
8
|
/** The language prefix, which namespaces every reference this analyzer emits. */
|
|
13
9
|
const PREFIX = "ts://";
|
|
@@ -30,16 +26,10 @@ const TS_FILE = String.raw `${TS_DIRS}[^/#\r\n]+(?:(?:\.d)?\.[mc]?ts|\.tsx|\.[mc
|
|
|
30
26
|
const SCOPE = `${PREFIX}${TS_PACKAGE}/${TS_FILE}`;
|
|
31
27
|
const MANIFEST_SCOPE = `${PREFIX}${TS_PACKAGE}/${TS_DIRS}package\\.json`;
|
|
32
28
|
/**
|
|
33
|
-
* One expression per
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* They are written here rather than read from the Contract at run time: the Contract
|
|
39
|
-
* is data a reader outside this program consults, and a product that read it while
|
|
40
|
-
* running would need it installed beside itself. A test compares this list against
|
|
41
|
-
* the release this analyzer is written against, so a grammar that grows a form
|
|
42
|
-
* arrives here as a failing test.
|
|
29
|
+
* One anchored expression per spelling the grammar defines; a reference is valid when it
|
|
30
|
+
* matches one. They are written here rather than read from the Contract at run time, so
|
|
31
|
+
* the product needs no Contract installed beside it; a test compares this list against
|
|
32
|
+
* the release this analyzer implements, so a grammar that grows a form fails it.
|
|
43
33
|
*/
|
|
44
34
|
export const REF_EXPRESSIONS = [
|
|
45
35
|
`^${SCOPE}#$`,
|
|
@@ -102,7 +92,8 @@ export function aliasFragment(name, block) {
|
|
|
102
92
|
const head = block === undefined ? "" : `${quoted(block)}.`;
|
|
103
93
|
return `${head}${nameComponent(name)}:alias`;
|
|
104
94
|
}
|
|
105
|
-
|
|
95
|
+
/** The canonical spelling of one component: a name, or a computed key. */
|
|
96
|
+
export function spell(component) {
|
|
106
97
|
return component.computed ? computedComponent(component.text) : nameComponent(component.text);
|
|
107
98
|
}
|
|
108
99
|
/**
|
package/dist/src/references.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { isArrayLiteralExpression, isAsExpression, isBinaryExpression, isCallExpression, isDecorator, isDeleteExpression, isElementAccessExpression, isExportDeclaration, isExpressionStatement, isExternalModuleReference, isForInStatement, isForOfStatement, isForStatement, isIdentifier, isImportDeclaration, isImportEqualsDeclaration, isInterfaceDeclaration, isMetaProperty, isModuleBlock, isModuleDeclaration, isNewExpression, isNamespaceExport, isNoSubstitutionTemplateLiteral, isObjectLiteralExpression, isParenthesizedExpression, isPostfixUnaryExpression, isPrefixUnaryExpression, isPropertyAccessExpression, isPropertyAssignment, isShorthandPropertyAssignment, isSpreadAssignment, isSpreadElement, isStringLiteral, isVoidExpression, SyntaxKind, } from "@typescript/native/ast";
|
|
1
|
+
import { isArrayLiteralExpression, isAsExpression, isBinaryExpression, isCallExpression, isDecorator, isDeleteExpression, isElementAccessExpression, isExportDeclaration, isExpressionStatement, isExternalModuleReference, isForInStatement, isForOfStatement, isForStatement, isIdentifier, isImportDeclaration, isImportEqualsDeclaration, isInterfaceDeclaration, isMetaProperty, isModuleBlock, isModuleDeclaration, isNewExpression, isNamespaceExport, isNoSubstitutionTemplateLiteral, isObjectLiteralExpression, isParenthesizedExpression, isPostfixUnaryExpression, isPrefixUnaryExpression, isPropertyAccessExpression, isPropertyAssignment, isShorthandPropertyAssignment, isSpreadAssignment, isSpreadElement, isStringLiteral, isStringLiteralLikeNode, isVoidExpression, SyntaxKind, } from "@typescript/native/ast";
|
|
2
2
|
import { parenthesesRemoved } from "./unwrap.js";
|
|
3
3
|
import { aliasChains } from "./alias-chain.js";
|
|
4
4
|
import { contextualUses } from "./contextual-uses.js";
|
|
5
5
|
import { destructuring, propertyReadsOf } from "./destructuring.js";
|
|
6
|
-
import { specifierCandidates } from "./configuration-files.js";
|
|
6
|
+
import { specifierCandidates } from "./entries/configuration-files.js";
|
|
7
7
|
import { namespaceUses } from "./namespace-objects.js";
|
|
8
|
-
import {
|
|
8
|
+
import { isParameterProperty, nodeKey } from "./inventory.js";
|
|
9
9
|
import { ambientGlobalInterfaces, augmentationReferences } from "./augmentations.js";
|
|
10
10
|
import { elementAccessReferences } from "./element-access.js";
|
|
11
11
|
import { indexedAccessReferences } from "./indexed-access.js";
|
|
@@ -13,11 +13,15 @@ import { keyofComparisonReferences } from "./keyof-comparisons.js";
|
|
|
13
13
|
import { unimplementedCalleeReads } from "./unimplemented-callees.js";
|
|
14
14
|
import { moduleDeclarationReferences } from "./module-declarations.js";
|
|
15
15
|
import { overrideReferences } from "./overrides.js";
|
|
16
|
-
import { dirnamePath, queriedModulePath, relativePath, resolvePath } from "./paths.js";
|
|
16
|
+
import { dirnamePath, queriedModulePath, relativePath, relativeURLPath, resolvePath, } from "./paths.js";
|
|
17
17
|
import { byPosition, isComponentFile, renderPosition } from "./position.js";
|
|
18
18
|
import { DEFAULT_BATCH_CAP, propertyTables, UNANSWERED } from "./query.js";
|
|
19
|
+
import { sourceFilesOf } from "./source-files.js";
|
|
19
20
|
import { typeParameterReads } from "./type-parameter-reads.js";
|
|
20
21
|
import { typeQueryAliases } from "./type-query-alias.js";
|
|
22
|
+
import { callsPlatform, isPlatformGlobal, startsThread } from "./platform-symbols.js";
|
|
23
|
+
import { writtenName } from "./platform-calls.js";
|
|
24
|
+
import { computedLoadsOf, isLoadCall } from "./roots/unseen-loads.js";
|
|
21
25
|
import { computedKeyNames, iterationReferences, keyNameOf, keyedUses, } from "./symbol-keys.js";
|
|
22
26
|
import { handedOn, valuesOf } from "./value-flow.js";
|
|
23
27
|
import { bytewise } from "./text/compare.js";
|
|
@@ -183,25 +187,23 @@ function isImportMetaURL(node) {
|
|
|
183
187
|
}
|
|
184
188
|
/** The module URL one node builds, where it builds one. */
|
|
185
189
|
function moduleURLOf(node) {
|
|
186
|
-
const
|
|
190
|
+
const literal = (argument) => {
|
|
187
191
|
const at = argument === undefined ? undefined : parenthesesRemoved(argument);
|
|
188
|
-
return at
|
|
189
|
-
(isStringLiteral(at) || isNoSubstitutionTemplateLiteral(at)) &&
|
|
190
|
-
/^\.\.?\//u.test(at.text)
|
|
191
|
-
? at.text
|
|
192
|
-
: undefined;
|
|
192
|
+
return isLiteralText(at) ? at.text : undefined;
|
|
193
193
|
};
|
|
194
|
-
|
|
194
|
+
const constructor = isNewExpression(node) ? writtenName(node.expression) : undefined;
|
|
195
|
+
if (isNewExpression(node) && constructor !== undefined) {
|
|
195
196
|
const [reference, base] = node.arguments ?? [];
|
|
196
|
-
const specifier =
|
|
197
|
+
const specifier = literal(reference);
|
|
197
198
|
return specifier !== undefined && base !== undefined && isImportMetaURL(base)
|
|
198
|
-
? { specifier, constructor
|
|
199
|
+
? { specifier, constructor, at: node }
|
|
199
200
|
: undefined;
|
|
200
201
|
}
|
|
201
202
|
if (isCallExpression(node)) {
|
|
202
203
|
const callee = parenthesesRemoved(node.expression);
|
|
203
|
-
const specifier =
|
|
204
|
+
const specifier = literal(node.arguments[0]);
|
|
204
205
|
if (specifier !== undefined &&
|
|
206
|
+
/^\.\.?\//u.test(specifier) &&
|
|
205
207
|
isPropertyAccessExpression(callee) &&
|
|
206
208
|
isMetaProperty(callee.expression) &&
|
|
207
209
|
callee.expression.keywordToken === SyntaxKind.ImportKeyword &&
|
|
@@ -211,6 +213,69 @@ function moduleURLOf(node) {
|
|
|
211
213
|
}
|
|
212
214
|
return undefined;
|
|
213
215
|
}
|
|
216
|
+
/** The constructors whose first argument addresses a worker. */
|
|
217
|
+
const WORKER_CONSTRUCTORS = new Set(["Worker", "SharedWorker"]);
|
|
218
|
+
/** Whether an options argument is an object literal whose `eval` member is written as anything but `false`. */
|
|
219
|
+
function evaluatesCode(options) {
|
|
220
|
+
const at = options === undefined ? undefined : parenthesesRemoved(options);
|
|
221
|
+
return (at !== undefined &&
|
|
222
|
+
isObjectLiteralExpression(at) &&
|
|
223
|
+
at.properties.some((property) => (isShorthandPropertyAssignment(property) &&
|
|
224
|
+
isIdentifier(property.name) &&
|
|
225
|
+
property.name.text === "eval") ||
|
|
226
|
+
(isPropertyAssignment(property) &&
|
|
227
|
+
(isIdentifier(property.name) || isStringLiteral(property.name)) &&
|
|
228
|
+
property.name.text === "eval" &&
|
|
229
|
+
parenthesesRemoved(property.initializer).kind !== SyntaxKind.FalseKeyword)));
|
|
230
|
+
}
|
|
231
|
+
/** The worker one node starts by a literal address, where it starts one. */
|
|
232
|
+
function workerOf(node) {
|
|
233
|
+
if (isNewExpression(node)) {
|
|
234
|
+
const constructor = writtenName(node.expression);
|
|
235
|
+
const [address, options] = node.arguments ?? [];
|
|
236
|
+
const literal = address === undefined ? undefined : parenthesesRemoved(address);
|
|
237
|
+
// A thread's constructor may be imported under another name, whose path is relative.
|
|
238
|
+
if (constructor === undefined ||
|
|
239
|
+
!isLiteralText(literal) ||
|
|
240
|
+
(!WORKER_CONSTRUCTORS.has(constructor.text) && !/^\.\.?\//u.test(literal.text))) {
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
const callee = parenthesesRemoved(node.expression);
|
|
244
|
+
const holder = isPropertyAccessExpression(callee)
|
|
245
|
+
? parenthesesRemoved(callee.expression)
|
|
246
|
+
: undefined;
|
|
247
|
+
return {
|
|
248
|
+
address: literal,
|
|
249
|
+
constructor,
|
|
250
|
+
holder: holder !== undefined && isIdentifier(holder) ? holder : undefined,
|
|
251
|
+
evaluated: evaluatesCode(options),
|
|
252
|
+
at: node,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
if (!isCallExpression(node)) {
|
|
256
|
+
return undefined;
|
|
257
|
+
}
|
|
258
|
+
const callee = parenthesesRemoved(node.expression);
|
|
259
|
+
const registry = isPropertyAccessExpression(callee) && callee.name.text === "register"
|
|
260
|
+
? parenthesesRemoved(callee.expression)
|
|
261
|
+
: undefined;
|
|
262
|
+
const navigator = registry !== undefined &&
|
|
263
|
+
isPropertyAccessExpression(registry) &&
|
|
264
|
+
registry.name.text === "serviceWorker"
|
|
265
|
+
? writtenName(registry.expression)
|
|
266
|
+
: undefined;
|
|
267
|
+
const [address] = node.arguments;
|
|
268
|
+
const literal = address === undefined ? undefined : parenthesesRemoved(address);
|
|
269
|
+
return navigator?.text === "navigator" && isLiteralText(literal)
|
|
270
|
+
? { address: literal, constructor: navigator, holder: undefined, evaluated: false, at: node }
|
|
271
|
+
: undefined;
|
|
272
|
+
}
|
|
273
|
+
/** The file of the target a relative specifier written in `file` names, by its source or output name. */
|
|
274
|
+
function fileNamed(file, specifier, fileIdByName) {
|
|
275
|
+
return specifierCandidates(dirnamePath(file.fileName), specifier)
|
|
276
|
+
.map((path) => fileIdByName.get(path))
|
|
277
|
+
.find((id) => id !== undefined);
|
|
278
|
+
}
|
|
214
279
|
/** Whether one node is a string literal or a template literal with no substitution. */
|
|
215
280
|
function isLiteralText(node) {
|
|
216
281
|
return node !== undefined && (isStringLiteral(node) || isNoSubstitutionTemplateLiteral(node));
|
|
@@ -218,10 +283,33 @@ function isLiteralText(node) {
|
|
|
218
283
|
/**
|
|
219
284
|
* The module specifier of the module one node evaluates, if it evaluates one: an import
|
|
220
285
|
* declaration, an import-equals declaration of an external module, an export
|
|
221
|
-
* declaration that names a module,
|
|
222
|
-
*
|
|
223
|
-
*
|
|
286
|
+
* declaration that names a module, an `import()` call whose argument is literal text, and
|
|
287
|
+
* a call that may be a `require()` of literal text: one written as the name `require`, or
|
|
288
|
+
* one of a relative specifier through another name. A type-only form evaluates nothing.
|
|
289
|
+
* An `import()` of a computed argument names no module this pass can know.
|
|
224
290
|
*/
|
|
291
|
+
function evaluationOf(node) {
|
|
292
|
+
if (isCallExpression(node) && node.expression.kind !== SyntaxKind.ImportKeyword) {
|
|
293
|
+
const [argument] = node.arguments;
|
|
294
|
+
const require = writtenName(node.expression);
|
|
295
|
+
if (require === undefined ||
|
|
296
|
+
!isLiteralText(argument) ||
|
|
297
|
+
(require.text !== "require" && !/^\.\.?\//u.test(argument.text))) {
|
|
298
|
+
return undefined;
|
|
299
|
+
}
|
|
300
|
+
return { node: argument, require, whole: !discarded(node) };
|
|
301
|
+
}
|
|
302
|
+
const specifier = evaluatedBy(node);
|
|
303
|
+
return specifier === undefined ? undefined : { node: specifier };
|
|
304
|
+
}
|
|
305
|
+
/** Whether an expression's value is thrown away: it is a statement of its own, or `void`'s operand. */
|
|
306
|
+
function discarded(expression) {
|
|
307
|
+
let at = expression.parent;
|
|
308
|
+
while (isParenthesizedExpression(at)) {
|
|
309
|
+
at = at.parent;
|
|
310
|
+
}
|
|
311
|
+
return isExpressionStatement(at) || isVoidExpression(at);
|
|
312
|
+
}
|
|
225
313
|
function evaluatedBy(node) {
|
|
226
314
|
if (isImportDeclaration(node)) {
|
|
227
315
|
return node.importClause?.phaseModifier === SyntaxKind.TypeKeyword
|
|
@@ -330,6 +418,8 @@ function sitesOf(file, declarations, fileId, unread) {
|
|
|
330
418
|
const evaluations = [];
|
|
331
419
|
const wholes = [];
|
|
332
420
|
const urls = [];
|
|
421
|
+
const workers = [];
|
|
422
|
+
const loadCalls = [];
|
|
333
423
|
const decorated = [];
|
|
334
424
|
const parameterWrites = [];
|
|
335
425
|
const namespaces = namespaceUses(file);
|
|
@@ -405,13 +495,20 @@ function sitesOf(file, declarations, fileId, unread) {
|
|
|
405
495
|
reads.push({ ...read, from: enclosing });
|
|
406
496
|
}
|
|
407
497
|
links.push(...linksOf(file, node, declarations, enclosing));
|
|
408
|
-
const evaluated =
|
|
498
|
+
const evaluated = evaluationOf(node);
|
|
409
499
|
if (evaluated !== undefined) {
|
|
410
|
-
evaluations.push({
|
|
500
|
+
evaluations.push({ ...evaluated, from: enclosing });
|
|
411
501
|
}
|
|
412
502
|
const url = moduleURLOf(node);
|
|
413
503
|
if (url !== undefined) {
|
|
414
|
-
urls.push(url);
|
|
504
|
+
urls.push({ ...url, from: enclosing });
|
|
505
|
+
}
|
|
506
|
+
const worker = workerOf(node);
|
|
507
|
+
if (worker !== undefined) {
|
|
508
|
+
workers.push({ ...worker, from: enclosing });
|
|
509
|
+
}
|
|
510
|
+
if (isLoadCall(node)) {
|
|
511
|
+
loadCalls.push({ call: node, from: enclosing });
|
|
415
512
|
}
|
|
416
513
|
const held = declarations.get(nodeKey(file, node));
|
|
417
514
|
const outer = enclosing;
|
|
@@ -445,6 +542,8 @@ function sitesOf(file, declarations, fileId, unread) {
|
|
|
445
542
|
evaluations,
|
|
446
543
|
wholes,
|
|
447
544
|
urls,
|
|
545
|
+
workers,
|
|
546
|
+
loadCalls,
|
|
448
547
|
decorated,
|
|
449
548
|
parameterWrites,
|
|
450
549
|
keyed,
|
|
@@ -611,20 +710,12 @@ function aloneIn(file, uses, writes, found) {
|
|
|
611
710
|
return result;
|
|
612
711
|
}
|
|
613
712
|
/**
|
|
614
|
-
* Every reference one project's own files make to
|
|
615
|
-
*
|
|
616
|
-
*
|
|
617
|
-
*
|
|
618
|
-
*
|
|
619
|
-
*
|
|
620
|
-
* walks the consumer's files instead and renders against its root, as
|
|
621
|
-
* {@link ReferenceOptions.consumer} states.
|
|
622
|
-
*
|
|
623
|
-
* The order is by the referencing position, then by the declaration named, the
|
|
624
|
-
* declaration referencing it and the use. That is a total order because one name
|
|
625
|
-
* references one declaration once from one declaration, while a chain of aliases reaches
|
|
626
|
-
* several declarations at one position and a bare star re-export's specifier both reads
|
|
627
|
-
* and evaluates the module it names.
|
|
713
|
+
* Every reference one project's own files make to its own declarations, and the files the
|
|
714
|
+
* test-file rules classified. `held` is the same project's inventory, where a resolved symbol
|
|
715
|
+
* is looked up; positions render against `targetRoot`, or a consumer's root as
|
|
716
|
+
* {@link ReferenceOptions.consumer} states. The order is by position, then the declaration
|
|
717
|
+
* named, the referencing declaration and the use: an alias chain or a bare star re-export
|
|
718
|
+
* names several at one position, and one name references one declaration once.
|
|
628
719
|
*/
|
|
629
720
|
export function references(project, held, targetRoot, options) {
|
|
630
721
|
const cap = options.batchCap ?? DEFAULT_BATCH_CAP;
|
|
@@ -638,6 +729,10 @@ export function references(project, held, targetRoot, options) {
|
|
|
638
729
|
let batched = 0;
|
|
639
730
|
let fileBatches = 0;
|
|
640
731
|
let residueFallbacks = 0;
|
|
732
|
+
let platformLookups = 0;
|
|
733
|
+
const asked = () => {
|
|
734
|
+
platformLookups += 1;
|
|
735
|
+
};
|
|
641
736
|
let shorthandLookups = 0;
|
|
642
737
|
const consumer = options.consumer;
|
|
643
738
|
const root = consumer?.root ?? targetRoot;
|
|
@@ -673,6 +768,8 @@ export function references(project, held, targetRoot, options) {
|
|
|
673
768
|
}
|
|
674
769
|
return moduleBodies.get(moduleId) ?? [];
|
|
675
770
|
};
|
|
771
|
+
let ownFiles;
|
|
772
|
+
const unseenLoads = [];
|
|
676
773
|
const exportsCache = new Map();
|
|
677
774
|
/**
|
|
678
775
|
* Every declaration one module exports, each re-export walked along its chain. A module
|
|
@@ -716,7 +813,7 @@ export function references(project, held, targetRoot, options) {
|
|
|
716
813
|
* live. A name a namespace import binds may be a use of any file.
|
|
717
814
|
*/
|
|
718
815
|
const named = (node) => {
|
|
719
|
-
const byName =
|
|
816
|
+
const byName = held.byName;
|
|
720
817
|
const text = node.getText();
|
|
721
818
|
const imported = importedNames(node.getSourceFile()).get(text) ?? [];
|
|
722
819
|
return [
|
|
@@ -740,7 +837,7 @@ export function references(project, held, targetRoot, options) {
|
|
|
740
837
|
return;
|
|
741
838
|
}
|
|
742
839
|
aliased.set(id, symbol === UNANSWERED
|
|
743
|
-
? (
|
|
840
|
+
? (held.byName.get(alias.name) ?? []).map((one) => ({
|
|
744
841
|
id: one,
|
|
745
842
|
stepped: true,
|
|
746
843
|
guessed: true,
|
|
@@ -783,6 +880,10 @@ export function references(project, held, targetRoot, options) {
|
|
|
783
880
|
return { file, fileId, ...sitesOf(file, declarations, fileId, unread) };
|
|
784
881
|
});
|
|
785
882
|
const fileIdByName = new Map(walked.filter((one) => fileIds.has(one.fileId)).map((one) => [one.file.fileName, one.fileId]));
|
|
883
|
+
const loadable = walked
|
|
884
|
+
.filter((one) => fileIds.has(one.fileId))
|
|
885
|
+
.map(({ file, fileId }) => ({ file, fileId }));
|
|
886
|
+
const loadableById = new Map(loadable.map((one) => [one.fileId, one.file]));
|
|
786
887
|
const contextual = contextualUses(project, held, chains, walked.flatMap((one) => one.literals), walked.flatMap((one) => one.flows), cap, tables);
|
|
787
888
|
const writtenBy = new Map();
|
|
788
889
|
for (const write of contextual.writes) {
|
|
@@ -862,8 +963,9 @@ export function references(project, held, targetRoot, options) {
|
|
|
862
963
|
}
|
|
863
964
|
}
|
|
864
965
|
const keyNames = computedKeyNames(held.symbols);
|
|
865
|
-
for (const { file, fileId, uses, reads, links, evaluations, wholes, urls, decorated, parameterWrites, keyed, } of walked) {
|
|
966
|
+
for (const { file, fileId, uses, reads, links, evaluations, wholes, urls, workers, loadCalls, decorated, parameterWrites, keyed, } of walked) {
|
|
866
967
|
const test = testFile.get(file) === true;
|
|
968
|
+
const loads = computedLoadsOf(file, loadCalls, loadable, (fileName) => options.directories.bundlerRootOf(fileName));
|
|
867
969
|
// A component file's markup may use any binding its blocks declare at the top level.
|
|
868
970
|
const markup = isComponentFile(file);
|
|
869
971
|
const bindings = markup ? importBindings(file) : [];
|
|
@@ -900,10 +1002,20 @@ export function references(project, held, targetRoot, options) {
|
|
|
900
1002
|
...new Set([
|
|
901
1003
|
...uses.filter((site) => site.shorthand === undefined).map((site) => site.node),
|
|
902
1004
|
...links.map((link) => link.node),
|
|
903
|
-
...evaluations.
|
|
1005
|
+
...evaluations.flatMap((evaluation) => evaluation.require === undefined
|
|
1006
|
+
? [evaluation.node]
|
|
1007
|
+
: [
|
|
1008
|
+
evaluation.require,
|
|
1009
|
+
...(evaluation.require.text === "require" ? [evaluation.node] : []),
|
|
1010
|
+
]),
|
|
904
1011
|
...wholes.map((whole) => whole.specifier),
|
|
905
1012
|
...urls.flatMap((url) => url.constructor ?? []),
|
|
1013
|
+
...workers.flatMap((worker) => worker.holder === undefined ? [worker.constructor] : [worker.constructor, worker.holder]),
|
|
906
1014
|
...bindings.map((binding) => binding.node),
|
|
1015
|
+
...loads.flatMap((load) => [
|
|
1016
|
+
...(load.require === undefined ? [] : [load.require]),
|
|
1017
|
+
...(load.asset ? [] : load.files.map((loaded) => loaded.file)),
|
|
1018
|
+
]),
|
|
907
1019
|
]),
|
|
908
1020
|
];
|
|
909
1021
|
const answered = new Map();
|
|
@@ -939,7 +1051,22 @@ export function references(project, held, targetRoot, options) {
|
|
|
939
1051
|
});
|
|
940
1052
|
}
|
|
941
1053
|
}
|
|
942
|
-
|
|
1054
|
+
const loading = evaluations.filter((one) => one.require === undefined ||
|
|
1055
|
+
callsPlatform(project, "require", one.require, answered.get(one.require), asked));
|
|
1056
|
+
// A script declares no module, so the checker names nothing for a specifier of one;
|
|
1057
|
+
// the compiler's module resolution still names its file.
|
|
1058
|
+
const unnamed = loading.flatMap(({ node }) => answered.get(node) === undefined &&
|
|
1059
|
+
isStringLiteralLikeNode(node) &&
|
|
1060
|
+
queriedFile(file, node, fileIdByName) === undefined
|
|
1061
|
+
? [node]
|
|
1062
|
+
: []);
|
|
1063
|
+
const resolved = project.resolvedFileNames(unnamed);
|
|
1064
|
+
const scripts = new Map(unnamed.map((node, at) => {
|
|
1065
|
+
const name = resolved[at];
|
|
1066
|
+
return [node, name === undefined ? undefined : fileIdByName.get(name)];
|
|
1067
|
+
}));
|
|
1068
|
+
const wholeReads = [];
|
|
1069
|
+
for (const evaluation of loading) {
|
|
943
1070
|
const queried = queriedFile(file, evaluation.node, fileIdByName);
|
|
944
1071
|
if (queried !== undefined) {
|
|
945
1072
|
found.push({
|
|
@@ -952,6 +1079,28 @@ export function references(project, held, targetRoot, options) {
|
|
|
952
1079
|
});
|
|
953
1080
|
}
|
|
954
1081
|
const module = answered.get(evaluation.node);
|
|
1082
|
+
// Node's require resolves a relative specifier the program records no resolution for,
|
|
1083
|
+
// as in a TypeScript file, by its own extension search.
|
|
1084
|
+
const script = scripts.get(evaluation.node) ??
|
|
1085
|
+
(evaluation.require !== undefined &&
|
|
1086
|
+
module === undefined &&
|
|
1087
|
+
isLiteralText(evaluation.node) &&
|
|
1088
|
+
/^\.\.?\//u.test(evaluation.node.text)
|
|
1089
|
+
? fileNamed(file, evaluation.node.text, fileIdByName)
|
|
1090
|
+
: undefined);
|
|
1091
|
+
if (script !== undefined && evaluation.whole === true && module === undefined) {
|
|
1092
|
+
wholeReads.push({ evaluation, fileId: script });
|
|
1093
|
+
}
|
|
1094
|
+
if (script !== undefined) {
|
|
1095
|
+
found.push({
|
|
1096
|
+
from: evaluation.from,
|
|
1097
|
+
to: script,
|
|
1098
|
+
position: renderPosition(file, root, evaluation.node.getStart()),
|
|
1099
|
+
use: "evaluation",
|
|
1100
|
+
resolution: "syntax",
|
|
1101
|
+
test,
|
|
1102
|
+
});
|
|
1103
|
+
}
|
|
955
1104
|
if (module === undefined) {
|
|
956
1105
|
continue;
|
|
957
1106
|
}
|
|
@@ -971,21 +1120,37 @@ export function references(project, held, targetRoot, options) {
|
|
|
971
1120
|
}
|
|
972
1121
|
}
|
|
973
1122
|
}
|
|
1123
|
+
// A required file the checker names no module for is read whole where the call's value
|
|
1124
|
+
// is used: the value is the file's exports object, which this pass does not follow.
|
|
1125
|
+
const required = wholeReads.flatMap((one) => {
|
|
1126
|
+
const loaded = loadableById.get(one.fileId);
|
|
1127
|
+
return loaded === undefined ? [] : [{ ...one, loaded }];
|
|
1128
|
+
});
|
|
1129
|
+
const modules = project.symbolsAt(required.map((one) => project.handle(one.loaded)), cap);
|
|
1130
|
+
required.forEach(({ evaluation }, at) => {
|
|
1131
|
+
const module = modules[at];
|
|
1132
|
+
const position = renderPosition(file, root, evaluation.node.getStart());
|
|
1133
|
+
for (const target of module === undefined ? [] : exportsRead(module)) {
|
|
1134
|
+
found.push({
|
|
1135
|
+
from: evaluation.from,
|
|
1136
|
+
to: target.id,
|
|
1137
|
+
position,
|
|
1138
|
+
use: "read",
|
|
1139
|
+
resolution: target.guessed ? "by-name" : "batch",
|
|
1140
|
+
test,
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1143
|
+
});
|
|
974
1144
|
for (const url of urls) {
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
// library's declaration; a `URL` the target declares has no other.
|
|
978
|
-
if (typeof constructor === "object" &&
|
|
979
|
-
constructor.declarations.length > 0 &&
|
|
980
|
-
constructor.declarations.every((handle) => ownPaths.has(handle.path))) {
|
|
1145
|
+
if (url.constructor !== undefined &&
|
|
1146
|
+
!callsPlatform(project, "URL", url.constructor, answered.get(url.constructor), asked)) {
|
|
981
1147
|
continue;
|
|
982
1148
|
}
|
|
983
|
-
const
|
|
984
|
-
|
|
985
|
-
.find((id) => id !== undefined);
|
|
1149
|
+
const path = relativeURLPath(dirnamePath(file.fileName), url.specifier);
|
|
1150
|
+
const loaded = path === undefined ? undefined : fileNamed(file, path, fileIdByName);
|
|
986
1151
|
if (loaded !== undefined) {
|
|
987
1152
|
found.push({
|
|
988
|
-
from:
|
|
1153
|
+
from: url.from,
|
|
989
1154
|
to: loaded,
|
|
990
1155
|
position: renderPosition(file, root, url.at.getStart()),
|
|
991
1156
|
use: "evaluation",
|
|
@@ -994,6 +1159,70 @@ export function references(project, held, targetRoot, options) {
|
|
|
994
1159
|
});
|
|
995
1160
|
}
|
|
996
1161
|
}
|
|
1162
|
+
for (const worker of workers) {
|
|
1163
|
+
const symbol = answered.get(worker.constructor);
|
|
1164
|
+
const text = worker.address.text;
|
|
1165
|
+
let path;
|
|
1166
|
+
if (startsThread(project, symbol, worker.holder && answered.get(worker.holder), asked)) {
|
|
1167
|
+
path =
|
|
1168
|
+
worker.evaluated || !/^\.\.?\//u.test(text)
|
|
1169
|
+
? undefined
|
|
1170
|
+
: resolvePath(options.directories.workingDirectoryOf(file.fileName), text);
|
|
1171
|
+
}
|
|
1172
|
+
else if ((WORKER_CONSTRUCTORS.has(worker.constructor.text) ||
|
|
1173
|
+
worker.constructor.text === "navigator") &&
|
|
1174
|
+
isPlatformGlobal(project, symbol)) {
|
|
1175
|
+
path = relativeURLPath(dirnamePath(file.fileName), text);
|
|
1176
|
+
}
|
|
1177
|
+
ownFiles ??= sourceFilesOf(project, targetRoot);
|
|
1178
|
+
for (const started of path === undefined ? [] : ownFiles.named(path)) {
|
|
1179
|
+
const to = declaredAt(started);
|
|
1180
|
+
if (to !== undefined && fileIds.has(to)) {
|
|
1181
|
+
found.push({
|
|
1182
|
+
from: worker.from,
|
|
1183
|
+
to,
|
|
1184
|
+
position: renderPosition(file, root, worker.at.getStart()),
|
|
1185
|
+
use: "evaluation",
|
|
1186
|
+
resolution: "syntax",
|
|
1187
|
+
test,
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
// A computed load imports each file it loads where the call is written, reading what
|
|
1193
|
+
// the file exports unless it reads the file as text or a URL; callsPlatform owns which
|
|
1194
|
+
// call is a `require`.
|
|
1195
|
+
for (const load of loads) {
|
|
1196
|
+
if (load.require !== undefined &&
|
|
1197
|
+
!callsPlatform(project, "require", load.require, answered.get(load.require), asked)) {
|
|
1198
|
+
continue;
|
|
1199
|
+
}
|
|
1200
|
+
const position = renderPosition(file, root, load.call.getStart());
|
|
1201
|
+
if (!load.resolved && !test && consumer === undefined && !file.isDeclarationFile) {
|
|
1202
|
+
unseenLoads.push(position);
|
|
1203
|
+
}
|
|
1204
|
+
for (const loaded of load.files) {
|
|
1205
|
+
found.push({
|
|
1206
|
+
from: load.eager ? fileId : load.from,
|
|
1207
|
+
to: loaded.fileId,
|
|
1208
|
+
position,
|
|
1209
|
+
use: "evaluation",
|
|
1210
|
+
resolution: "syntax",
|
|
1211
|
+
test,
|
|
1212
|
+
});
|
|
1213
|
+
const module = load.asset ? undefined : answered.get(loaded.file);
|
|
1214
|
+
for (const target of module === undefined ? [] : exportsRead(module)) {
|
|
1215
|
+
found.push({
|
|
1216
|
+
from: load.from,
|
|
1217
|
+
to: target.id,
|
|
1218
|
+
position,
|
|
1219
|
+
use: "read",
|
|
1220
|
+
resolution: target.guessed ? "by-name" : "batch",
|
|
1221
|
+
test,
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
997
1226
|
for (const whole of wholes) {
|
|
998
1227
|
const module = answered.get(whole.specifier);
|
|
999
1228
|
if (module === undefined) {
|
|
@@ -1060,7 +1289,7 @@ export function references(project, held, targetRoot, options) {
|
|
|
1060
1289
|
}
|
|
1061
1290
|
const position = renderPosition(file, root, read.key.getStart());
|
|
1062
1291
|
const targets = symbol === UNANSWERED
|
|
1063
|
-
? (
|
|
1292
|
+
? (held.byName.get(read.name) ?? []).map((id) => ({
|
|
1064
1293
|
id,
|
|
1065
1294
|
stepped: false,
|
|
1066
1295
|
guessed: true,
|
|
@@ -1187,12 +1416,14 @@ export function references(project, held, targetRoot, options) {
|
|
|
1187
1416
|
? found
|
|
1188
1417
|
: found.map((reference) => ({ ...reference, consumer: consumer.id })),
|
|
1189
1418
|
testFilePaths: tests.sort(bytewise),
|
|
1419
|
+
unseenLoads,
|
|
1190
1420
|
cost: {
|
|
1191
1421
|
batched,
|
|
1192
1422
|
fileBatches,
|
|
1193
1423
|
residueFallbacks,
|
|
1194
1424
|
shorthandLookups,
|
|
1195
1425
|
aliasSteps: chains.steps,
|
|
1426
|
+
platformLookups,
|
|
1196
1427
|
patternBatches: destructured.cost.patternBatches,
|
|
1197
1428
|
patternLookups: destructured.cost.patternLookups,
|
|
1198
1429
|
contextualBatches: contextual.batches,
|
package/dist/src/resolve.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SETTINGS } from "./contract/config.generated.js";
|
|
2
2
|
import { FAMILY_KEY_LENGTH } from "./contract/contract.generated.js";
|
|
3
3
|
import {} from "./config.js";
|
|
4
|
-
import { CONVENTION_ROWS } from "./convention-rows.js";
|
|
4
|
+
import { CONVENTION_ROWS } from "./entries/convention-rows.js";
|
|
5
5
|
import { refuseOverBound } from "./fs/document.js";
|
|
6
6
|
import { dotted, isRecord, locatedFault, placeIn, pointerOf, readStrict, StrictJSONError, } from "./json-document.js";
|
|
7
7
|
import { FIXED_SEVERITY_CODES } from "./kinds.js";
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { isCallExpression, isExportDeclaration, isExternalModuleReference, isImportDeclaration, isImportEqualsDeclaration, isNoSubstitutionTemplateLiteral, isStringLiteral, SyntaxKind, } from "@typescript/native/ast";
|
|
8
8
|
import { SymbolFlags } from "@typescript/native/sync";
|
|
9
|
-
import { resolvedTargets } from "
|
|
10
|
-
import { declaredComponent } from "
|
|
11
|
-
import { must, Unanswerable } from "
|
|
12
|
-
import { nameComponent } from "
|
|
9
|
+
import { resolvedTargets } from "../calls.js";
|
|
10
|
+
import { declaredComponent } from "../inventory.js";
|
|
11
|
+
import { must, Unanswerable } from "../query.js";
|
|
12
|
+
import { nameComponent } from "../ref.js";
|
|
13
13
|
/** The meanings a name of the global scope is looked up under: any of them. */
|
|
14
14
|
const ANY_MEANING = SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace;
|
|
15
15
|
/** The suffix that marks a static member at the end of a path. */
|