@cplieger/deadset-ts 8.0.0-dev.2 → 8.0.0-dev.20
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 +3 -1
- package/THIRD_PARTY_NOTICES.md +27 -0
- package/dist/bin/mapper-connection.js +2 -1
- package/dist/bin/node-host.js +24 -5
- package/dist/src/alias-chain.js +2 -7
- package/dist/src/amd.js +81 -0
- package/dist/src/analysis.js +269 -432
- package/dist/src/augmentations.js +64 -3
- package/dist/src/automatic-types.js +10 -29
- package/dist/src/bindings.js +382 -0
- package/dist/src/calls.js +279 -43
- package/dist/src/commands/held.js +499 -0
- package/dist/src/commands/read.js +161 -0
- package/dist/src/commands/shell.js +169 -0
- package/dist/src/commands/tools.js +1847 -0
- package/dist/src/component-files.js +3 -2
- package/dist/src/component-layer.js +4 -2
- package/dist/src/config.js +6 -82
- package/dist/src/conformance-record.js +1 -1
- package/dist/src/consumers.js +10 -38
- package/dist/src/contextual-uses.js +57 -26
- package/dist/src/contract/config.generated.js +561 -0
- package/dist/src/contract/contract.generated.js +1369 -0
- package/dist/src/contract/report.generated.js +866 -0
- package/dist/src/dependencies.js +164 -121
- package/dist/src/destructuring.js +1 -19
- package/dist/src/edges.js +38 -122
- package/dist/src/element-access.js +181 -168
- package/dist/src/entries/build-scripts.js +222 -0
- package/dist/src/{configuration-files.js → entries/configuration-files.js} +52 -256
- package/dist/src/{convention-rows.js → entries/convention-rows.js} +170 -30
- package/dist/src/entries/conventions.js +740 -0
- package/dist/src/{html-entries.js → entries/html-entries.js} +12 -42
- package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +5 -28
- package/dist/src/entries/run-directories.js +77 -0
- package/dist/src/entries/sources.js +144 -0
- package/dist/src/entries/static-module.js +670 -0
- package/dist/src/entries/test-runners.js +650 -0
- package/dist/src/entries/workflow-steps.js +345 -0
- package/dist/src/enum-group.js +3 -10
- package/dist/src/erased-stores.js +4 -6
- package/dist/src/exempt-classes.js +1 -63
- package/dist/src/exempt.js +21 -66
- package/dist/src/exposure.js +400 -0
- package/dist/src/extensions.js +37 -0
- package/dist/src/facts.js +38 -0
- package/dist/src/failure.js +36 -0
- package/dist/src/file-facts.js +3 -26
- package/dist/src/findings/completion.js +109 -56
- package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
- package/dist/src/findings/emitters.js +27 -41
- package/dist/src/{implementations.js → findings/implementations.js} +3 -3
- package/dist/src/{in-operands.js → findings/in-operands.js} +3 -2
- package/dist/src/findings/interfaces.js +4 -5
- package/dist/src/findings/intra-function.js +16 -13
- package/dist/src/findings/non-code-artifacts.js +17 -12
- package/dist/src/findings/reads-and-writes.js +86 -27
- package/dist/src/findings/self-check.js +44 -30
- package/dist/src/findings/unused-declarations.js +29 -45
- package/dist/src/findings/visibility-narrowing.js +23 -31
- package/dist/src/findings-pass.js +13 -21
- package/dist/src/framework-lifecycle.js +46 -19
- package/dist/src/fs/document.js +52 -0
- package/dist/src/fs/manifest.js +67 -0
- package/dist/src/fs/tree.js +88 -0
- package/dist/src/generated-file.js +174 -28
- package/dist/src/git-ignore.js +39 -26
- package/dist/src/import-bindings.js +73 -28
- package/dist/src/index/sites.js +557 -0
- package/dist/src/index.js +2 -2
- package/dist/src/indexed-access.js +523 -478
- package/dist/src/injection-container.js +2 -2
- package/dist/src/interface-satisfaction.js +1 -1
- package/dist/src/intra-function-parts.js +63 -43
- 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 +323 -724
- package/dist/src/javascript-file.js +48 -0
- package/dist/src/json-document.js +198 -67
- package/dist/src/keyof-comparisons.js +126 -107
- package/dist/src/kinds.js +3 -366
- package/dist/src/{components.js → liveness/components.js} +2 -3
- package/dist/src/{graph.js → liveness/graph.js} +52 -28
- package/dist/src/liveness/matrix.js +99 -0
- package/dist/src/liveness/sweep.js +558 -0
- package/dist/src/load/classify.js +289 -0
- package/dist/src/load/diagnostics.js +87 -0
- package/dist/src/load/discover.js +285 -0
- package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
- package/dist/src/load/expected-module.js +136 -0
- package/dist/src/load/load.js +27 -0
- package/dist/src/load/module-lookup.js +37 -0
- package/dist/src/load/package-scope.js +56 -0
- package/dist/src/load/plan.js +313 -0
- package/dist/src/load/specifiers.js +113 -0
- package/dist/src/load/synthesize.js +152 -0
- package/dist/src/load/test-globals.js +207 -0
- package/dist/src/load/test-joins.js +82 -0
- package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
- package/dist/src/{workspace-programs.js → load/workspace-programs.js} +89 -66
- package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +24 -66
- package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
- package/dist/src/{workspace.js → load/workspace.js} +62 -124
- package/dist/src/module-declarations.js +70 -85
- package/dist/src/overrides.js +134 -112
- package/dist/src/partial.js +2 -1
- package/dist/src/paths.js +82 -16
- package/dist/src/platform-calls.js +78 -0
- package/dist/src/platform-symbols.js +134 -0
- package/dist/src/position.js +43 -1
- package/dist/src/print.js +11 -79
- package/dist/src/product.js +13 -0
- package/dist/src/query.js +47 -0
- package/dist/src/ref.js +12 -20
- package/dist/src/references/read-rule.js +1 -0
- package/dist/src/references/read-rules.js +48 -0
- package/dist/src/references/sink.js +237 -0
- package/dist/src/references/sources.js +450 -0
- package/dist/src/references.js +117 -1074
- package/dist/src/report-schema.js +51 -0
- package/dist/src/report.js +57 -41
- package/dist/src/reporters/annotations.js +15 -8
- package/dist/src/reporters/sarif.js +16 -10
- package/dist/src/reporters/template.js +4 -19
- package/dist/src/resolve.js +246 -730
- package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +22 -24
- package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +6 -15
- package/dist/src/roots/manifest.js +216 -0
- package/dist/src/roots/published-reach.js +412 -0
- package/dist/src/roots/root-set.js +487 -0
- package/dist/src/roots/unseen-loads.js +236 -0
- package/dist/src/run.js +66 -77
- package/dist/src/schema.js +320 -343
- package/dist/src/scope.js +38 -115
- package/dist/src/serialization-contract.js +601 -22
- package/dist/src/session.js +37 -29
- package/dist/src/source-files.js +6 -10
- package/dist/src/stores.js +4 -2
- package/dist/src/suppress-file.js +25 -28
- package/dist/src/suppress-inline.js +36 -83
- package/dist/src/suppress.js +50 -71
- package/dist/src/symbol-keys.js +92 -88
- package/dist/src/template-field.js +9 -19
- package/dist/src/tests/file-class.js +76 -0
- package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
- package/dist/src/{test-support.js → tests/support.js} +5 -12
- package/dist/src/text/compare.js +26 -0
- package/dist/src/text/glob.js +194 -0
- package/dist/src/text/named-files.js +298 -0
- package/dist/src/text/yaml.js +684 -0
- package/dist/src/type-errors.js +11 -232
- package/dist/src/type-parameter-reads.js +178 -139
- package/dist/src/unimplemented-callees.js +262 -242
- package/dist/src/unwrap.js +23 -0
- package/dist/src/usage.js +10 -0
- package/dist/src/vendor/unbash/ansi-c.js +132 -0
- package/dist/src/vendor/unbash/arithmetic-parts.js +37 -0
- package/dist/src/vendor/unbash/arithmetic.js +591 -0
- package/dist/src/vendor/unbash/assignment.js +131 -0
- package/dist/src/vendor/unbash/chars.js +48 -0
- package/dist/src/vendor/unbash/command.js +41 -0
- package/dist/src/vendor/unbash/expansion.js +80 -0
- package/dist/src/vendor/unbash/glob.js +268 -0
- package/dist/src/vendor/unbash/heredoc.js +27 -0
- package/dist/src/vendor/unbash/internal-types.js +1 -0
- package/dist/src/vendor/unbash/lexer.js +4274 -0
- package/dist/src/vendor/unbash/limits.js +3 -0
- package/dist/src/vendor/unbash/parser.js +1366 -0
- package/dist/src/vendor/unbash/parts.js +57 -0
- package/dist/src/vendor/unbash/substitution-context.js +8 -0
- package/dist/src/vendor/unbash/traversal.js +212 -0
- package/dist/src/vendor/unbash/types.js +1 -0
- package/dist/src/vendor/unbash/word-value.js +61 -0
- package/dist/src/vendor/unbash/word.js +40 -0
- package/dist/src/verbs/analyze.js +194 -127
- package/dist/src/verbs/describe.js +13 -18
- package/dist/src/verbs/explain.js +85 -139
- package/dist/src/verbs/print-config.js +2 -1
- package/dist/src/verbs/print-projects.js +6 -4
- package/dist/src/verbs/print-retained.js +7 -5
- package/dist/src/verbs/print-roots.js +4 -2
- package/dist/src/verbs/verb.js +1 -5
- package/dist/src/verbs/version.js +14 -3
- package/jsr.json +2 -1
- package/package.json +14 -8
- package/src/alias-chain.ts +2 -9
- package/src/amd.ts +130 -0
- package/src/analysis.ts +424 -650
- package/src/augmentations.ts +93 -4
- package/src/automatic-types.ts +12 -30
- package/src/bindings.ts +460 -0
- package/src/calls.ts +338 -46
- package/src/commands/held.ts +632 -0
- package/src/commands/read.ts +242 -0
- package/src/commands/shell.ts +228 -0
- package/src/commands/tools.ts +2382 -0
- package/src/component-files.ts +4 -2
- package/src/component-layer.ts +4 -2
- package/src/config.ts +31 -302
- package/src/conformance-record.ts +1 -1
- package/src/consumers.ts +16 -66
- package/src/contextual-uses.ts +66 -34
- package/src/contract/config.generated.ts +821 -0
- package/src/contract/contract.generated.ts +1452 -0
- package/src/contract/report.generated.ts +1241 -0
- package/src/dependencies.ts +222 -127
- package/src/destructuring.ts +1 -31
- package/src/edges.ts +41 -140
- package/src/element-access.ts +190 -187
- package/src/entries/build-scripts.ts +292 -0
- package/src/{configuration-files.ts → entries/configuration-files.ts} +68 -278
- package/src/{convention-rows.ts → entries/convention-rows.ts} +227 -31
- package/src/{conventions.ts → entries/conventions.ts} +367 -583
- package/src/{html-entries.ts → entries/html-entries.ts} +22 -48
- package/src/{mdx-entries.ts → entries/mdx-entries.ts} +7 -30
- package/src/entries/run-directories.ts +108 -0
- package/src/entries/sources.ts +266 -0
- package/src/entries/static-module.ts +858 -0
- package/src/entries/test-runners.ts +835 -0
- package/src/entries/workflow-steps.ts +432 -0
- package/src/enum-group.ts +2 -11
- package/src/erased-stores.ts +3 -7
- package/src/exempt-classes.ts +1 -75
- package/src/exempt.ts +70 -98
- package/src/exposure.ts +492 -0
- package/src/extensions.ts +45 -0
- package/src/facts.ts +46 -0
- package/src/failure.ts +63 -0
- package/src/file-facts.ts +15 -25
- package/src/finding.ts +10 -10
- package/src/findings/boundary.ts +11 -0
- package/src/findings/completion.ts +133 -64
- package/src/findings/dependencies-and-module-machinery.ts +4 -7
- package/src/findings/emitter.ts +9 -10
- package/src/findings/emitters.ts +38 -52
- package/src/{implementations.ts → findings/implementations.ts} +4 -4
- package/src/{in-operands.ts → findings/in-operands.ts} +4 -3
- package/src/findings/interfaces.ts +7 -9
- package/src/findings/intra-function.ts +16 -14
- package/src/findings/non-code-artifacts.ts +24 -15
- package/src/findings/reads-and-writes.ts +118 -41
- package/src/findings/self-check.ts +51 -38
- package/src/findings/unused-declarations.ts +31 -49
- package/src/findings/visibility-narrowing.ts +36 -40
- package/src/findings-pass.ts +15 -31
- package/src/framework-lifecycle.ts +47 -19
- package/src/fs/document.ts +70 -0
- package/src/fs/manifest.ts +96 -0
- package/src/fs/tree.ts +110 -0
- package/src/generated-file.ts +242 -35
- package/src/git-ignore.ts +50 -26
- package/src/host.ts +12 -5
- package/src/import-bindings.ts +98 -29
- package/src/index/sites.ts +781 -0
- package/src/index.ts +2 -2
- package/src/indexed-access.ts +570 -527
- package/src/injection-container.ts +2 -2
- package/src/interface-satisfaction.ts +2 -2
- package/src/intra-function-parts.ts +73 -44
- 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 +442 -895
- package/src/javascript-file.ts +54 -0
- package/src/json-document.ts +241 -76
- package/src/keyof-comparisons.ts +133 -122
- package/src/kinds.ts +5 -413
- package/src/{components.ts → liveness/components.ts} +4 -6
- package/src/{graph.ts → liveness/graph.ts} +100 -35
- package/src/liveness/matrix.ts +162 -0
- package/src/liveness/sweep.ts +855 -0
- package/src/load/classify.ts +433 -0
- package/src/load/diagnostics.ts +154 -0
- package/src/load/discover.ts +471 -0
- package/src/{emit-map.ts → load/emit-map.ts} +1 -1
- package/src/load/expected-module.ts +194 -0
- package/src/load/load.ts +73 -0
- package/src/load/module-lookup.ts +50 -0
- package/src/load/package-scope.ts +74 -0
- package/src/load/plan.ts +513 -0
- package/src/load/specifiers.ts +171 -0
- package/src/load/synthesize.ts +230 -0
- package/src/load/test-globals.ts +251 -0
- package/src/load/test-joins.ts +98 -0
- package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
- package/src/{workspace-programs.ts → load/workspace-programs.ts} +128 -85
- package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +41 -77
- package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
- package/src/{workspace.ts → load/workspace.ts} +90 -134
- package/src/module-declarations.ts +74 -98
- package/src/overrides.ts +162 -134
- package/src/partial.ts +3 -2
- package/src/paths.ts +92 -16
- package/src/platform-calls.ts +119 -0
- package/src/platform-symbols.ts +189 -0
- package/src/position.ts +44 -1
- package/src/print.ts +12 -92
- package/src/product.ts +18 -0
- package/src/query.ts +92 -0
- package/src/ref.ts +12 -20
- package/src/references/read-rule.ts +60 -0
- package/src/references/read-rules.ts +55 -0
- package/src/references/sink.ts +314 -0
- package/src/references/sources.ts +632 -0
- package/src/references.ts +187 -1450
- package/src/report-schema.ts +68 -0
- package/src/report.ts +103 -226
- package/src/reporters/annotations.ts +22 -11
- package/src/reporters/json.ts +1 -1
- package/src/reporters/reporter.ts +2 -4
- package/src/reporters/reporters.ts +1 -1
- package/src/reporters/sarif.ts +29 -16
- package/src/reporters/template.ts +4 -20
- package/src/reporters/text.ts +3 -3
- package/src/resolve.ts +284 -1115
- package/src/{configured-declarations.ts → roots/configured-declarations.ts} +27 -29
- package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +7 -16
- package/src/roots/manifest.ts +303 -0
- package/src/roots/published-reach.ts +486 -0
- package/src/{roots.ts → roots/root-set.ts} +286 -469
- package/src/roots/unseen-loads.ts +345 -0
- package/src/run.ts +75 -91
- package/src/schema.ts +391 -388
- package/src/scope.ts +46 -138
- package/src/serialization-contract.ts +769 -23
- package/src/session.ts +87 -55
- package/src/source-files.ts +6 -11
- package/src/stores.ts +15 -3
- package/src/suppress-file.ts +24 -33
- package/src/suppress-inline.ts +55 -91
- package/src/suppress.ts +78 -79
- package/src/symbol-keys.ts +104 -107
- package/src/template-field.ts +15 -25
- package/src/tests/file-class.ts +135 -0
- package/src/{outside-tests.ts → tests/outside.ts} +16 -10
- package/src/{test-support.ts → tests/support.ts} +15 -21
- package/src/text/compare.ts +27 -0
- package/src/text/glob.ts +210 -0
- package/src/text/named-files.ts +388 -0
- package/src/text/yaml.ts +747 -0
- package/src/type-errors.ts +18 -288
- package/src/type-parameter-reads.ts +187 -158
- package/src/unimplemented-callees.ts +297 -280
- package/src/unwrap.ts +34 -0
- package/src/usage.ts +10 -0
- package/src/vendor/unbash/LICENSE +15 -0
- package/src/vendor/unbash/VENDORED.md +16 -0
- package/src/vendor/unbash/ansi-c.ts +132 -0
- package/src/vendor/unbash/arithmetic-parts.ts +53 -0
- package/src/vendor/unbash/arithmetic.ts +641 -0
- package/src/vendor/unbash/assignment.ts +163 -0
- package/src/vendor/unbash/chars.ts +48 -0
- package/src/vendor/unbash/command.ts +47 -0
- package/src/vendor/unbash/expansion.ts +144 -0
- package/src/vendor/unbash/glob.ts +284 -0
- package/src/vendor/unbash/heredoc.ts +34 -0
- package/src/vendor/unbash/internal-types.ts +94 -0
- package/src/vendor/unbash/lexer.ts +4352 -0
- package/src/vendor/unbash/limits.ts +3 -0
- package/src/vendor/unbash/parser.ts +1612 -0
- package/src/vendor/unbash/parts.ts +96 -0
- package/src/vendor/unbash/substitution-context.ts +20 -0
- package/src/vendor/unbash/traversal.ts +182 -0
- package/src/vendor/unbash/types.ts +660 -0
- package/src/vendor/unbash/word-value.ts +64 -0
- package/src/vendor/unbash/word.ts +50 -0
- package/src/verbs/analyze.ts +255 -164
- package/src/verbs/describe.ts +19 -17
- package/src/verbs/explain.ts +93 -169
- package/src/verbs/print-config.ts +2 -1
- package/src/verbs/print-projects.ts +6 -4
- package/src/verbs/print-retained.ts +7 -5
- package/src/verbs/print-roots.ts +4 -2
- package/src/verbs/verb.ts +2 -8
- package/src/verbs/version.ts +15 -3
- package/dist/src/base-url.js +0 -18
- package/dist/src/conventions.js +0 -937
- package/dist/src/discover.js +0 -468
- package/dist/src/entry-points.js +0 -529
- package/dist/src/glob.js +0 -65
- package/dist/src/manifest.js +0 -165
- package/dist/src/matrix.js +0 -246
- package/dist/src/pnpm-workspace.js +0 -120
- package/dist/src/roots.js +0 -672
- package/dist/src/setup-failure.js +0 -23
- package/dist/src/sweep.js +0 -224
- package/dist/src/test-joins.js +0 -101
- package/dist/src/version.js +0 -7
- package/dist/src/workflow-steps.js +0 -185
- package/src/base-url.ts +0 -24
- package/src/discover.ts +0 -653
- package/src/entry-points.ts +0 -687
- package/src/glob.ts +0 -67
- package/src/manifest.ts +0 -234
- package/src/matrix.ts +0 -423
- package/src/pnpm-workspace.ts +0 -135
- package/src/setup-failure.ts +0 -39
- package/src/sweep.ts +0 -347
- package/src/test-joins.ts +0 -120
- package/src/version.ts +0 -7
- package/src/workflow-steps.ts +0 -216
package/dist/src/inventory.js
CHANGED
|
@@ -1,702 +1,141 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
const
|
|
1
|
+
import { isClassDeclaration, isComputedPropertyName, isConstructorDeclaration, isEnumMember, isFunctionDeclaration, isGetAccessorDeclaration, isIdentifier, isInterfaceDeclaration, isMethodDeclaration, isMethodSignatureDeclaration, isParameterDeclaration, isPrivateIdentifier, isPropertyDeclaration, isPropertySignatureDeclaration, isSetAccessorDeclaration, isTypeAliasDeclaration, ModifierFlags, SyntaxKind, } from "@typescript/native/ast";
|
|
2
|
+
import { byPosition, positionKey, renderPosition, startLine } from "./position.js";
|
|
3
|
+
import { renderRef, spell } from "./ref.js";
|
|
4
|
+
import { signatureOf } from "./signatures.js";
|
|
5
|
+
/** The reader's word for each kind of declaration, as a finding names it. */
|
|
6
|
+
export const WORDS = {
|
|
7
|
+
file: "file",
|
|
8
|
+
function: "function",
|
|
9
|
+
class: "class",
|
|
10
|
+
interface: "interface",
|
|
11
|
+
type: "type alias",
|
|
12
|
+
enum: "enum",
|
|
13
|
+
namespace: "namespace",
|
|
14
|
+
variable: "variable",
|
|
15
|
+
"export-alias": "re-export",
|
|
16
|
+
method: "method",
|
|
17
|
+
"class-member": "class member",
|
|
18
|
+
"interface-method": "interface method",
|
|
19
|
+
"type-member": "type member",
|
|
20
|
+
"enum-member": "enum member",
|
|
21
|
+
"type-parameter": "type parameter",
|
|
22
|
+
};
|
|
7
23
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* the path is read from the root, which cannot collide, because a package name never
|
|
12
|
-
* starts with a dot.
|
|
13
|
-
*
|
|
14
|
-
* One directory is read at most once, because a package holds many files and a
|
|
15
|
-
* manifest read is a filesystem call.
|
|
16
|
-
*/
|
|
17
|
-
export function packageScope(host, root) {
|
|
18
|
-
const named = new Map();
|
|
19
|
-
const manifestName = (dir) => {
|
|
20
|
-
let text;
|
|
21
|
-
try {
|
|
22
|
-
text = host.readFile(joinPath(root, dir, MANIFEST));
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return undefined;
|
|
26
|
-
}
|
|
27
|
-
let value;
|
|
28
|
-
try {
|
|
29
|
-
value = JSON.parse(text);
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
// A manifest this program cannot read names no package, which is the same
|
|
33
|
-
// answer as an absent one: the file is then scoped by the target root.
|
|
34
|
-
return undefined;
|
|
35
|
-
}
|
|
36
|
-
if (typeof value !== "object" || value === null) {
|
|
37
|
-
return undefined;
|
|
38
|
-
}
|
|
39
|
-
const name = value["name"];
|
|
40
|
-
return typeof name === "string" && name !== "" ? name : undefined;
|
|
41
|
-
};
|
|
42
|
-
const nearest = (dir) => {
|
|
43
|
-
if (named.has(dir)) {
|
|
44
|
-
return named.get(dir);
|
|
45
|
-
}
|
|
46
|
-
const name = manifestName(dir);
|
|
47
|
-
const found = name !== undefined ? { name, at: dir } : dir === "" ? undefined : nearest(parentOf(dir));
|
|
48
|
-
named.set(dir, found);
|
|
49
|
-
return found;
|
|
50
|
-
};
|
|
51
|
-
return (path) => {
|
|
52
|
-
const found = nearest(parentOf(path));
|
|
53
|
-
if (found === undefined) {
|
|
54
|
-
return { package: ".", path };
|
|
55
|
-
}
|
|
56
|
-
return { package: found.name, path: found.at === "" ? path : path.slice(found.at.length + 1) };
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
/** The directory one path below the root sits in, and the root itself as the empty path. */
|
|
60
|
-
function parentOf(path) {
|
|
61
|
-
const dir = dirnamePath(path);
|
|
62
|
-
return dir === "." ? "" : dir;
|
|
63
|
-
}
|
|
64
|
-
/** The modifier flags one node carries, and zero for a node that carries none. */
|
|
65
|
-
function modifiersOf(node) {
|
|
66
|
-
return node.modifierFlags ?? 0;
|
|
67
|
-
}
|
|
68
|
-
/** Whether a declaration is ambient: in a declaration file, or under a `declare` modifier. */
|
|
69
|
-
function isAmbient(file, node) {
|
|
70
|
-
if (file.isDeclarationFile) {
|
|
71
|
-
return true;
|
|
72
|
-
}
|
|
73
|
-
for (let at = node; at !== undefined; at = at.parent) {
|
|
74
|
-
if ((modifiersOf(at) & ModifierFlags.Ambient) !== 0) {
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
/** The type parameters one node declares, and none for a node that declares none. */
|
|
81
|
-
function typeParametersOf(node) {
|
|
82
|
-
if (isFunctionDeclaration(node) ||
|
|
83
|
-
isMethodDeclaration(node) ||
|
|
84
|
-
isMethodSignatureDeclaration(node) ||
|
|
85
|
-
isClassDeclaration(node) ||
|
|
86
|
-
isInterfaceDeclaration(node) ||
|
|
87
|
-
isTypeAliasDeclaration(node)) {
|
|
88
|
-
return node.typeParameters ?? [];
|
|
89
|
-
}
|
|
90
|
-
return [];
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* The reference component one declaration name node spells, and undefined for a
|
|
94
|
-
* name the grammar does not represent: a binding pattern, and a computed key whose
|
|
95
|
-
* source text carries a closing bracket.
|
|
96
|
-
*/
|
|
97
|
-
function componentOf(name) {
|
|
98
|
-
if (name === undefined) {
|
|
99
|
-
return undefined;
|
|
100
|
-
}
|
|
101
|
-
if (isComputedPropertyName(name)) {
|
|
102
|
-
const text = name.expression.getText();
|
|
103
|
-
return text.includes("]") ? undefined : { text, computed: true };
|
|
104
|
-
}
|
|
105
|
-
if (isIdentifier(name) || isPrivateIdentifier(name)) {
|
|
106
|
-
return { text: name.getText(), computed: false };
|
|
107
|
-
}
|
|
108
|
-
if (isStringOrNumericName(name)) {
|
|
109
|
-
// A string or numeric key's own text carries its quotes and its numeric
|
|
110
|
-
// spelling; the reference carries the value, which the component then quotes.
|
|
111
|
-
return { text: literalTextOf(name), computed: false };
|
|
112
|
-
}
|
|
113
|
-
return undefined;
|
|
114
|
-
}
|
|
115
|
-
function isStringOrNumericName(name) {
|
|
116
|
-
const text = name.getText();
|
|
117
|
-
return (text.startsWith('"') || text.startsWith("'") || text.startsWith("`") || /^[0-9]/u.test(text));
|
|
118
|
-
}
|
|
119
|
-
/** One member's identity inside its container: its component, and its side of a class. */
|
|
120
|
-
function memberKey(component, isStatic) {
|
|
121
|
-
return `${component.computed ? "[" : ""}${component.text}${isStatic ? ":static" : ""}`;
|
|
122
|
-
}
|
|
123
|
-
/** The type one node is, through however many parentheses are written around it. */
|
|
124
|
-
function unparenthesizedType(type) {
|
|
125
|
-
let held = type;
|
|
126
|
-
while (isParenthesizedTypeNode(held)) {
|
|
127
|
-
held = held.type;
|
|
128
|
-
}
|
|
129
|
-
return held;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* The direct constituents of one type. Parentheses are syntax and are not a
|
|
133
|
-
* constituent, so a parenthesized type contributes the constituents it holds: the
|
|
134
|
-
* constituents of `(A | B) & C` are `A`, `B` and `C`. A union or an intersection
|
|
135
|
-
* written without them stays one constituent.
|
|
136
|
-
*/
|
|
137
|
-
function constituentsOf(type) {
|
|
138
|
-
const held = unparenthesizedType(type);
|
|
139
|
-
if (!isUnionTypeNode(held) && !isIntersectionTypeNode(held)) {
|
|
140
|
-
return [held];
|
|
141
|
-
}
|
|
142
|
-
return held.types.flatMap((member) => isParenthesizedTypeNode(member) ? constituentsOf(member) : [member]);
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* The members one type alias declares: the members of the object type it writes, and
|
|
146
|
-
* of every object type that is a direct constituent of a union or an intersection it
|
|
147
|
-
* writes. A constituent naming another type declares nothing here, because that
|
|
148
|
-
* declaration carries its own members.
|
|
149
|
-
*
|
|
150
|
-
* A name two constituents both declare is left out of all of them. The alias stands
|
|
151
|
-
* for such a member, because the two declarations are one member of the type and
|
|
152
|
-
* neither of them is the one a reference to it would name.
|
|
153
|
-
*/
|
|
154
|
-
function aliasMembers(type) {
|
|
155
|
-
const literals = constituentsOf(type).filter(isTypeLiteralNode);
|
|
156
|
-
if (literals.length < 2) {
|
|
157
|
-
return literals[0]?.members ?? [];
|
|
158
|
-
}
|
|
159
|
-
const declaring = new Map();
|
|
160
|
-
for (const literal of literals) {
|
|
161
|
-
for (const key of new Set(literal.members.map(keyOf))) {
|
|
162
|
-
if (key !== undefined) {
|
|
163
|
-
declaring.set(key, (declaring.get(key) ?? 0) + 1);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
return literals.flatMap((literal) => literal.members.filter((member) => {
|
|
168
|
-
const key = keyOf(member);
|
|
169
|
-
return key !== undefined && declaring.get(key) === 1;
|
|
170
|
-
}));
|
|
171
|
-
}
|
|
172
|
-
/** One type member's identity, and undefined for a member the grammar cannot name. */
|
|
173
|
-
function keyOf(member) {
|
|
174
|
-
const component = componentOf(nameNodeOf(member));
|
|
175
|
-
return component === undefined ? undefined : memberKey(component, false);
|
|
176
|
-
}
|
|
177
|
-
/** The value one string or numeric key denotes, which is what the reference names. */
|
|
178
|
-
function literalTextOf(name) {
|
|
179
|
-
const text = name.getText();
|
|
180
|
-
if (text.startsWith('"') || text.startsWith("'") || text.startsWith("`")) {
|
|
181
|
-
return text.slice(1, -1);
|
|
182
|
-
}
|
|
183
|
-
return text;
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* The component one declaration's reference carries, and its declared name where the
|
|
187
|
-
* two differ.
|
|
188
|
-
*
|
|
189
|
-
* A declaration its module exports as the default is named `default`, because that is
|
|
190
|
-
* its export name and a module has at most one, so the spelling is unambiguous and it
|
|
191
|
-
* holds for an anonymous declaration too. Its declared name is a fact about the source
|
|
192
|
-
* rather than about the export, so it travels beside the component as the display name.
|
|
193
|
-
*/
|
|
194
|
-
function exportedAs(node, name) {
|
|
195
|
-
const declared = componentOf(name);
|
|
196
|
-
if ((modifiersOf(node) & ModifierFlags.Default) === 0) {
|
|
197
|
-
return { component: declared, localName: undefined };
|
|
198
|
-
}
|
|
199
|
-
return { component: { text: "default", computed: false }, localName: declared?.text };
|
|
200
|
-
}
|
|
201
|
-
/** The visibility one member declaration's modifiers and name give it. */
|
|
202
|
-
function visibilityOf(node, name) {
|
|
203
|
-
if (name !== undefined && isPrivateIdentifier(name)) {
|
|
204
|
-
return "private-name";
|
|
205
|
-
}
|
|
206
|
-
const flags = modifiersOf(node);
|
|
207
|
-
if ((flags & ModifierFlags.Private) !== 0) {
|
|
208
|
-
return "private";
|
|
209
|
-
}
|
|
210
|
-
if ((flags & ModifierFlags.Protected) !== 0) {
|
|
211
|
-
return "protected";
|
|
212
|
-
}
|
|
213
|
-
return "public";
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* The binding elements of a destructuring declaration that each declare a name of their
|
|
217
|
-
* own, at any depth, but one with a default, whose removal skips the default's
|
|
218
|
-
* evaluation, and one beside a rest element of its object pattern, whose removal
|
|
219
|
-
* changes what the rest holds.
|
|
220
|
-
*/
|
|
221
|
-
function patternElements(name) {
|
|
222
|
-
if (!isObjectBindingPattern(name) && !isArrayBindingPattern(name)) {
|
|
223
|
-
return [];
|
|
224
|
-
}
|
|
225
|
-
const rest = isObjectBindingPattern(name) &&
|
|
226
|
-
name.elements.some((element) => element.dotDotDotToken !== undefined);
|
|
227
|
-
return name.elements.flatMap((element) => {
|
|
228
|
-
if (!isBindingElement(element) ||
|
|
229
|
-
element.initializer !== undefined ||
|
|
230
|
-
(rest && element.dotDotDotToken === undefined)) {
|
|
231
|
-
return [];
|
|
232
|
-
}
|
|
233
|
-
const bound = element.name;
|
|
234
|
-
if (bound === undefined) {
|
|
235
|
-
return [];
|
|
236
|
-
}
|
|
237
|
-
return isIdentifier(bound) ? [{ element, name: bound }] : patternElements(bound);
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
/** The name node of one declaration, for the kinds that carry one. */
|
|
241
|
-
function nameNodeOf(node) {
|
|
242
|
-
return node.name;
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* The fragment component one declaration's name spells in a reference, as the inventory
|
|
246
|
-
* spells it, or undefined for a name the grammar does not represent.
|
|
247
|
-
*/
|
|
248
|
-
export function declaredComponent(node) {
|
|
249
|
-
const component = componentOf(nameNodeOf(node));
|
|
250
|
-
if (component === undefined) {
|
|
251
|
-
return undefined;
|
|
252
|
-
}
|
|
253
|
-
return component.computed ? computedComponent(component.text) : nameComponent(component.text);
|
|
254
|
-
}
|
|
255
|
-
/**
|
|
256
|
-
* One node's identity inside one program, which is how two readings of that program
|
|
257
|
-
* name one declaration.
|
|
258
|
-
*
|
|
259
|
-
* The two mechanisms behind the member set resolve a member separately and meet here;
|
|
260
|
-
* so does the reference pass, which starts from a resolved symbol's declaration and
|
|
261
|
-
* needs the declaration this enumeration made for it.
|
|
24
|
+
* One node's identity inside one program, which is how two readings of that program name
|
|
25
|
+
* one declaration: the binder's table and the tree meet here, and so does the reference
|
|
26
|
+
* pass, which starts from a resolved symbol's declaration.
|
|
262
27
|
*/
|
|
263
28
|
export function nodeKey(file, node) {
|
|
264
29
|
return `${file.fileName}:${String(node.pos)}:${String(node.end)}:${String(node.kind)}`;
|
|
265
30
|
}
|
|
266
|
-
/** Whether `node` is written inside `declaration`, compared by file and range. */
|
|
267
|
-
function writtenInside(declaration, node) {
|
|
268
|
-
return (node.getSourceFile().fileName === declaration.getSourceFile().fileName &&
|
|
269
|
-
declaration.pos <= node.pos &&
|
|
270
|
-
node.end <= declaration.end);
|
|
271
|
-
}
|
|
272
|
-
/** `export default`, up to the keyword that stands where an unnamed default export's name would. */
|
|
273
|
-
const DEFAULT_EXPORT = /^export\s+(?=default\b)/u;
|
|
274
|
-
/**
|
|
275
|
-
* Where an unnamed declaration is placed: at `default` when it is the default export, so it
|
|
276
|
-
* never shares the file's own position, else at its first token.
|
|
277
|
-
*/
|
|
278
|
-
function unnamedStart(node) {
|
|
279
|
-
const start = node.getStart();
|
|
280
|
-
const prefix = DEFAULT_EXPORT.exec(node.getText());
|
|
281
|
-
return prefix === null ? start : start + prefix[0].length;
|
|
282
|
-
}
|
|
283
31
|
/**
|
|
284
32
|
* Whether one node is a parameter property: a constructor parameter carrying an
|
|
285
|
-
* accessibility, `readonly` or `override` modifier, which also declares an instance
|
|
286
|
-
*
|
|
33
|
+
* accessibility, `readonly` or `override` modifier, which also declares an instance member
|
|
34
|
+
* of the class, with the parameter's node as the member's declaration.
|
|
287
35
|
*/
|
|
288
36
|
export function isParameterProperty(node) {
|
|
289
37
|
return (isParameterDeclaration(node) &&
|
|
290
38
|
isConstructorDeclaration(node.parent) &&
|
|
291
39
|
(modifiersOf(node) & ModifierFlags.ParameterPropertyModifier) !== 0);
|
|
292
40
|
}
|
|
293
|
-
/**
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
return
|
|
300
|
-
}
|
|
301
|
-
/** The kind a type element takes: a method of an interface, or any other member. */
|
|
302
|
-
function typeMemberKind(node, inInterface) {
|
|
303
|
-
return inInterface && isMethodSignatureDeclaration(node) ? "interface-method" : "type-member";
|
|
41
|
+
/**
|
|
42
|
+
* The fragment component one declaration's name spells in a reference, as the inventory
|
|
43
|
+
* spells it, or undefined for a name the grammar does not represent.
|
|
44
|
+
*/
|
|
45
|
+
export function declaredComponent(node) {
|
|
46
|
+
const component = componentOf(nameNodeOf(node));
|
|
47
|
+
return component === undefined ? undefined : spell(component);
|
|
304
48
|
}
|
|
305
49
|
/**
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
* program holds that is not below it ends the enumeration rather than being passed
|
|
310
|
-
* over. `host` is the filesystem the manifests that name each file's package are
|
|
311
|
-
* read through, and nothing else is read from it.
|
|
312
|
-
*
|
|
313
|
-
* The order is by rendered position, so two enumerations of one project return the
|
|
314
|
-
* same list whatever order the program reported its files in.
|
|
50
|
+
* Collects one project's declarations, from every {@link DeclarationSource} and from the
|
|
51
|
+
* binder's tables, and renders them. A member is kept once per container, by its
|
|
52
|
+
* component and its side of a class, whichever mechanism names it first.
|
|
315
53
|
*/
|
|
316
|
-
export
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
const module = moduleOf(path);
|
|
338
|
-
const fileRecord = keep({
|
|
339
|
-
file,
|
|
340
|
-
node: file,
|
|
54
|
+
export class Builder {
|
|
55
|
+
#targetRoot;
|
|
56
|
+
#records = [];
|
|
57
|
+
#byNode = new Map();
|
|
58
|
+
#exportScopes = [];
|
|
59
|
+
#containers = [];
|
|
60
|
+
#modules = [];
|
|
61
|
+
#unansweredOwners = new Set();
|
|
62
|
+
#openTables = new Set();
|
|
63
|
+
constructor(targetRoot) {
|
|
64
|
+
this.#targetRoot = targetRoot;
|
|
65
|
+
}
|
|
66
|
+
get exportScopes() {
|
|
67
|
+
return this.#exportScopes;
|
|
68
|
+
}
|
|
69
|
+
get containers() {
|
|
70
|
+
return this.#containers;
|
|
71
|
+
}
|
|
72
|
+
/** One file's own record, which is also the export scope of its module. */
|
|
73
|
+
file(file, module, path) {
|
|
74
|
+
const record = this.#keep(file, file, 0, {
|
|
341
75
|
module,
|
|
342
|
-
position: renderPosition(file, targetRoot, 0),
|
|
343
|
-
endLine: renderPosition(file, targetRoot, Math.max(file.end - 1, 0)).line,
|
|
344
76
|
kind: "file",
|
|
345
77
|
parentChain: [],
|
|
346
|
-
// A file's reference names its module, so no component of it is ever spelled;
|
|
347
|
-
//
|
|
78
|
+
// A file's reference names its module, so no component of it is ever spelled; the
|
|
79
|
+
// path is what a text line renders for it.
|
|
348
80
|
component: { text: path, computed: false },
|
|
349
81
|
localName: path,
|
|
350
82
|
parent: undefined,
|
|
351
|
-
visibility: "public",
|
|
352
|
-
static: false,
|
|
353
|
-
exported: false,
|
|
354
|
-
typeParameter: undefined,
|
|
355
83
|
});
|
|
356
|
-
exportScopes.push({ owner:
|
|
357
|
-
|
|
358
|
-
const written = writtenLength(file);
|
|
359
|
-
walkStatements(file.statements.filter((statement) => statement.end <= written), fileRecord);
|
|
360
|
-
}
|
|
361
|
-
/** One declaration of a module, a namespace or a container body. */
|
|
362
|
-
function walkStatements(statements, owner) {
|
|
363
|
-
for (const statement of statements) {
|
|
364
|
-
walkStatement(statement, owner);
|
|
365
|
-
}
|
|
84
|
+
this.#exportScopes.push({ owner: record, nameNode: file });
|
|
85
|
+
return record;
|
|
366
86
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
node,
|
|
87
|
+
/** One declaration written under `owner`, placed at its name, and its type parameters. */
|
|
88
|
+
declare(node, owner, kind, name, named) {
|
|
89
|
+
const record = this.#keep(owner.file, node, name?.getStart() ?? unnamedStart(node), {
|
|
371
90
|
module: owner.module,
|
|
372
|
-
position: renderPosition(owner.file, targetRoot, name?.getStart() ?? unnamedStart(node)),
|
|
373
|
-
endLine: renderPosition(owner.file, targetRoot, Math.max(node.end - 1, 0)).line,
|
|
374
91
|
kind,
|
|
375
92
|
parentChain: owner.kind === "file" ? [] : chainOf(owner),
|
|
376
|
-
|
|
377
|
-
localName: named.localName,
|
|
93
|
+
...named,
|
|
378
94
|
parent: owner,
|
|
379
95
|
visibility: visibilityOf(node, name),
|
|
380
96
|
static: (modifiersOf(node) & ModifierFlags.Static) !== 0,
|
|
381
|
-
exported: false,
|
|
382
|
-
typeParameter: undefined,
|
|
383
97
|
});
|
|
384
|
-
declareTypeParameters(node, record);
|
|
98
|
+
this.#declareTypeParameters(node, record);
|
|
385
99
|
return record;
|
|
386
100
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
continue;
|
|
392
|
-
}
|
|
393
|
-
keep({
|
|
394
|
-
file: owner.file,
|
|
395
|
-
node: parameter,
|
|
396
|
-
module: owner.module,
|
|
397
|
-
position: renderPosition(owner.file, targetRoot, name.getStart()),
|
|
398
|
-
endLine: renderPosition(owner.file, targetRoot, Math.max(parameter.end - 1, 0)).line,
|
|
399
|
-
kind: "type-parameter",
|
|
400
|
-
parentChain: owner.parentChain,
|
|
401
|
-
component: owner.component,
|
|
402
|
-
localName: undefined,
|
|
403
|
-
parent: owner,
|
|
404
|
-
visibility: "public",
|
|
405
|
-
static: owner.static,
|
|
406
|
-
exported: false,
|
|
407
|
-
typeParameter: name.getText(),
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
function walkStatement(node, owner) {
|
|
412
|
-
if (isFunctionDeclaration(node)) {
|
|
413
|
-
const named = exportedAs(node, node.name);
|
|
414
|
-
if (named.component !== undefined) {
|
|
415
|
-
declare(node, owner, "function", node.name, { ...named, component: named.component });
|
|
416
|
-
}
|
|
417
|
-
return;
|
|
418
|
-
}
|
|
419
|
-
if (isClassDeclaration(node)) {
|
|
420
|
-
const named = exportedAs(node, node.name);
|
|
421
|
-
if (named.component === undefined) {
|
|
422
|
-
return;
|
|
423
|
-
}
|
|
424
|
-
const record = declare(node, owner, "class", node.name, {
|
|
425
|
-
...named,
|
|
426
|
-
component: named.component,
|
|
427
|
-
});
|
|
428
|
-
containers.push({
|
|
429
|
-
owner: record,
|
|
430
|
-
declaration: node,
|
|
431
|
-
nameNode: node.name,
|
|
432
|
-
members: [...node.members, ...parameterPropertiesOf(node)],
|
|
433
|
-
memberKind: "class-member",
|
|
434
|
-
isClass: true,
|
|
435
|
-
membersAreExports: false,
|
|
436
|
-
});
|
|
101
|
+
/** A container of members; a class's constructors are where its parts are bound. */
|
|
102
|
+
container(container) {
|
|
103
|
+
this.#containers.push(container);
|
|
104
|
+
if (container.memberKind !== "class-member") {
|
|
437
105
|
return;
|
|
438
106
|
}
|
|
439
|
-
|
|
440
|
-
const
|
|
441
|
-
|
|
442
|
-
return;
|
|
107
|
+
for (const member of container.members.filter(isConstructorDeclaration)) {
|
|
108
|
+
for (const at of [member, ...member.parameters.filter((one) => !isParameterProperty(one))]) {
|
|
109
|
+
container.owner.partLines.add(startLine(container.owner.file, at.pos));
|
|
443
110
|
}
|
|
444
|
-
const record = declare(node, owner, "interface", node.name, {
|
|
445
|
-
...named,
|
|
446
|
-
component: named.component,
|
|
447
|
-
});
|
|
448
|
-
containers.push({
|
|
449
|
-
owner: record,
|
|
450
|
-
declaration: node,
|
|
451
|
-
nameNode: node.name,
|
|
452
|
-
members: node.members,
|
|
453
|
-
memberKind: "interface-method",
|
|
454
|
-
isClass: false,
|
|
455
|
-
membersAreExports: false,
|
|
456
|
-
});
|
|
457
|
-
return;
|
|
458
|
-
}
|
|
459
|
-
if (isTypeAliasDeclaration(node)) {
|
|
460
|
-
const named = exportedAs(node, node.name);
|
|
461
|
-
if (named.component === undefined) {
|
|
462
|
-
return;
|
|
463
|
-
}
|
|
464
|
-
const record = declare(node, owner, "type", node.name, {
|
|
465
|
-
...named,
|
|
466
|
-
component: named.component,
|
|
467
|
-
});
|
|
468
|
-
// A type alias keeps no member table of its own: the members belong to the
|
|
469
|
-
// object types its declaration writes, so the declaration is what carries them.
|
|
470
|
-
const members = aliasMembers(node.type);
|
|
471
|
-
if (members.length > 0) {
|
|
472
|
-
containers.push({
|
|
473
|
-
owner: record,
|
|
474
|
-
declaration: node,
|
|
475
|
-
nameNode: undefined,
|
|
476
|
-
members,
|
|
477
|
-
memberKind: "type-member",
|
|
478
|
-
isClass: false,
|
|
479
|
-
membersAreExports: false,
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
return;
|
|
483
|
-
}
|
|
484
|
-
if (isEnumDeclaration(node)) {
|
|
485
|
-
const named = exportedAs(node, node.name);
|
|
486
|
-
if (named.component === undefined) {
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
const record = declare(node, owner, "enum", node.name, {
|
|
490
|
-
...named,
|
|
491
|
-
component: named.component,
|
|
492
|
-
});
|
|
493
|
-
containers.push({
|
|
494
|
-
owner: record,
|
|
495
|
-
declaration: node,
|
|
496
|
-
nameNode: node.name,
|
|
497
|
-
members: node.members,
|
|
498
|
-
memberKind: "enum-member",
|
|
499
|
-
isClass: false,
|
|
500
|
-
membersAreExports: true,
|
|
501
|
-
});
|
|
502
|
-
return;
|
|
503
|
-
}
|
|
504
|
-
if (isModuleDeclaration(node)) {
|
|
505
|
-
const component = componentOf(node.name);
|
|
506
|
-
if (component === undefined) {
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
509
|
-
const record = declare(node, owner, "namespace", node.name, {
|
|
510
|
-
component,
|
|
511
|
-
localName: undefined,
|
|
512
|
-
});
|
|
513
|
-
exportScopes.push({ owner: record, nameNode: node.name });
|
|
514
|
-
if (isStringLiteral(node.name)) {
|
|
515
|
-
modules.push([record, node.name.text]);
|
|
516
|
-
}
|
|
517
|
-
const body = node.body;
|
|
518
|
-
if (body === undefined) {
|
|
519
|
-
return;
|
|
520
|
-
}
|
|
521
|
-
if (isModuleBlock(body)) {
|
|
522
|
-
walkStatements(body.statements, record);
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
walkStatement(body, record);
|
|
526
|
-
return;
|
|
527
|
-
}
|
|
528
|
-
if (isVariableStatement(node)) {
|
|
529
|
-
for (const declaration of node.declarationList.declarations) {
|
|
530
|
-
const component = componentOf(declaration.name);
|
|
531
|
-
if (component !== undefined) {
|
|
532
|
-
declare(declaration, owner, "variable", declaration.name, {
|
|
533
|
-
component,
|
|
534
|
-
localName: undefined,
|
|
535
|
-
});
|
|
536
|
-
continue;
|
|
537
|
-
}
|
|
538
|
-
for (const { element, name } of patternElements(declaration.name)) {
|
|
539
|
-
declare(element, owner, "variable", name, {
|
|
540
|
-
component: { text: name.text, computed: false },
|
|
541
|
-
localName: undefined,
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
return;
|
|
546
|
-
}
|
|
547
|
-
if (isExportDeclaration(node)) {
|
|
548
|
-
walkExportDeclaration(node, owner);
|
|
549
|
-
return;
|
|
550
|
-
}
|
|
551
|
-
if (isExportAssignment(node) && !node.isExportEquals) {
|
|
552
|
-
declare(node, owner, "export-alias", undefined, {
|
|
553
|
-
component: { text: "default", computed: false },
|
|
554
|
-
localName: undefined,
|
|
555
|
-
});
|
|
556
111
|
}
|
|
557
112
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
if (clause === undefined) {
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
564
|
-
if (isNamespaceExport(clause)) {
|
|
565
|
-
const component = componentOf(clause.name);
|
|
566
|
-
if (component !== undefined) {
|
|
567
|
-
declare(clause, owner, "export-alias", clause.name, { component, localName: undefined });
|
|
568
|
-
}
|
|
569
|
-
return;
|
|
570
|
-
}
|
|
571
|
-
for (const element of clause.elements ?? []) {
|
|
572
|
-
const name = nameNodeOf(element);
|
|
573
|
-
const component = componentOf(name);
|
|
574
|
-
if (component !== undefined) {
|
|
575
|
-
declare(element, owner, "export-alias", name, { component, localName: undefined });
|
|
576
|
-
}
|
|
577
|
-
}
|
|
113
|
+
/** A namespace whose export table says which of its declarations it exports. */
|
|
114
|
+
exportScope(owner, nameNode) {
|
|
115
|
+
this.#exportScopes.push({ owner, nameNode });
|
|
578
116
|
}
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
const batched = [
|
|
583
|
-
...exportScopes.map((scope) => scope.nameNode),
|
|
584
|
-
...containers.map((container) => container.nameNode).filter((node) => node !== undefined),
|
|
585
|
-
];
|
|
586
|
-
const handles = batched.map((node) => project.handle(node));
|
|
587
|
-
const resolved = project.symbolsAt(handles);
|
|
588
|
-
const symbolOf = new Map();
|
|
589
|
-
// A scope or a container whose symbol or table went unanswered keeps what its syntax
|
|
590
|
-
// declares, and everything under it is recorded unanswered.
|
|
591
|
-
const unansweredOwners = new Set();
|
|
592
|
-
batched.forEach((node, index) => {
|
|
593
|
-
const symbol = resolved[index];
|
|
594
|
-
if (typeof symbol === "object") {
|
|
595
|
-
symbolOf.set(node, symbol);
|
|
596
|
-
}
|
|
597
|
-
});
|
|
598
|
-
resolved.slice(0, exportScopes.length).forEach((symbol, index) => {
|
|
599
|
-
const scope = exportScopes[index];
|
|
600
|
-
if (symbol === UNANSWERED && scope !== undefined) {
|
|
601
|
-
unansweredOwners.add(scope.owner);
|
|
602
|
-
}
|
|
603
|
-
});
|
|
604
|
-
containers
|
|
605
|
-
.filter((container) => container.nameNode !== undefined)
|
|
606
|
-
.forEach((container, index) => {
|
|
607
|
-
if (resolved[exportScopes.length + index] === UNANSWERED) {
|
|
608
|
-
unansweredOwners.add(container.owner);
|
|
609
|
-
}
|
|
610
|
-
});
|
|
611
|
-
let exportTables = 0;
|
|
612
|
-
for (const scope of exportScopes) {
|
|
613
|
-
const symbol = symbolOf.get(scope.nameNode);
|
|
614
|
-
if (symbol === undefined) {
|
|
615
|
-
continue;
|
|
616
|
-
}
|
|
617
|
-
exportTables += 1;
|
|
618
|
-
const table = project.queries.exportsOf(symbol);
|
|
619
|
-
if (!isAnswered(table)) {
|
|
620
|
-
unansweredOwners.add(scope.owner);
|
|
621
|
-
}
|
|
622
|
-
for (const [, exported] of isAnswered(table) ? table : []) {
|
|
623
|
-
for (const declaration of exported.declarations) {
|
|
624
|
-
const held = project.declarationAt(declaration);
|
|
625
|
-
if (held === undefined) {
|
|
626
|
-
continue;
|
|
627
|
-
}
|
|
628
|
-
const record = byNode.get(nodeKey(held.node.getSourceFile(), held.node));
|
|
629
|
-
if (record === undefined) {
|
|
630
|
-
continue;
|
|
631
|
-
}
|
|
632
|
-
record.exported = true;
|
|
633
|
-
}
|
|
634
|
-
}
|
|
117
|
+
/** A `declare module` declaration named by a string literal. */
|
|
118
|
+
module(record, name) {
|
|
119
|
+
this.#modules.push([record, name]);
|
|
635
120
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
const seen = new Map();
|
|
640
|
-
if (symbol !== undefined) {
|
|
641
|
-
if (!container.membersAreExports) {
|
|
642
|
-
memberTables += 1;
|
|
643
|
-
const table = project.queries.membersOf(symbol);
|
|
644
|
-
if (isAnswered(table)) {
|
|
645
|
-
readTable(container, table, seen, false);
|
|
646
|
-
}
|
|
647
|
-
else {
|
|
648
|
-
unansweredOwners.add(container.owner);
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
if (container.membersAreExports || container.isClass) {
|
|
652
|
-
memberTables += 1;
|
|
653
|
-
const table = project.queries.exportsOf(symbol);
|
|
654
|
-
if (isAnswered(table)) {
|
|
655
|
-
readTable(container, table, seen, container.isClass);
|
|
656
|
-
}
|
|
657
|
-
else {
|
|
658
|
-
unansweredOwners.add(container.owner);
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
completeFromTree(container, seen);
|
|
121
|
+
/** The declaration enumerated at one node, where one is. */
|
|
122
|
+
recordAt(node) {
|
|
123
|
+
return this.#byNode.get(nodeKey(node.getSourceFile(), node));
|
|
663
124
|
}
|
|
664
|
-
/**
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
for (const [, member] of table) {
|
|
672
|
-
const declarations = member.declarations
|
|
673
|
-
.map((handle) => project.declarationAt(handle))
|
|
674
|
-
.filter((held) => held !== undefined);
|
|
675
|
-
if (declarations.length === 0) {
|
|
676
|
-
continue;
|
|
677
|
-
}
|
|
678
|
-
const own = declarations.filter((held) => ownFiles.has(held.node.getSourceFile().fileName));
|
|
679
|
-
if (own.length === 0) {
|
|
680
|
-
continue;
|
|
681
|
-
}
|
|
682
|
-
// A merged symbol's table holds the members every one of its declarations writes,
|
|
683
|
-
// and each member is kept once, by the declaration that writes it.
|
|
684
|
-
for (const held of own.filter((one) => writtenInside(container.declaration, one.node))) {
|
|
685
|
-
keepMember(container, held.node, seen, areStatic);
|
|
686
|
-
}
|
|
687
|
-
}
|
|
125
|
+
/** Records that a table of `owner` is unknown, which leaves everything under it unknown. */
|
|
126
|
+
unanswered(owner) {
|
|
127
|
+
this.#unansweredOwners.add(owner);
|
|
128
|
+
}
|
|
129
|
+
/** Records that one file writes its exports in a form its table does not model. */
|
|
130
|
+
openTable(file) {
|
|
131
|
+
this.#openTables.add(file);
|
|
688
132
|
}
|
|
689
133
|
/**
|
|
690
|
-
* One container
|
|
691
|
-
*
|
|
692
|
-
*
|
|
134
|
+
* One member of a container. A getter and a setter of one name are one symbol and one
|
|
135
|
+
* reference, so the second declaration widens the first record rather than making a
|
|
136
|
+
* second, and both nodes name that record.
|
|
693
137
|
*/
|
|
694
|
-
|
|
695
|
-
for (const member of container.members) {
|
|
696
|
-
keepMember(container, member, seen, (modifiersOf(member) & ModifierFlags.Static) !== 0);
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
function keepMember(container, node, seen, areStatic) {
|
|
138
|
+
member(container, node, seen, areStatic) {
|
|
700
139
|
const kind = memberKindOf(container, node);
|
|
701
140
|
if (kind === undefined) {
|
|
702
141
|
return;
|
|
@@ -709,61 +148,234 @@ export function inventory(project, host, targetRoot) {
|
|
|
709
148
|
const file = node.getSourceFile();
|
|
710
149
|
const key = memberKey(component, areStatic);
|
|
711
150
|
const held = seen.get(key);
|
|
712
|
-
const endLine =
|
|
151
|
+
const endLine = this.#endOf(file, node);
|
|
713
152
|
if (held !== undefined) {
|
|
714
|
-
// A getter and a setter of one name are one symbol and one reference, so the
|
|
715
|
-
// second declaration widens the first record rather than making a second. Both
|
|
716
|
-
// nodes name that record, so a reading that starts from either one finds it.
|
|
717
153
|
held.endLine = Math.max(held.endLine, endLine);
|
|
718
|
-
byNode.set(nodeKey(file, node), held);
|
|
154
|
+
this.#byNode.set(nodeKey(file, node), held);
|
|
155
|
+
placeAt(held, node);
|
|
719
156
|
return;
|
|
720
157
|
}
|
|
721
|
-
const
|
|
722
|
-
const record = keep({
|
|
723
|
-
file,
|
|
724
|
-
node,
|
|
158
|
+
const record = this.#keep(file, node, (name ?? node).getStart(), {
|
|
725
159
|
module: container.owner.module,
|
|
726
|
-
position: renderPosition(file, targetRoot, at.getStart()),
|
|
727
|
-
endLine,
|
|
728
160
|
kind,
|
|
729
161
|
parentChain: chainOf(container.owner),
|
|
730
162
|
component,
|
|
731
|
-
localName: undefined,
|
|
732
163
|
parent: container.owner,
|
|
733
164
|
visibility: visibilityOf(node, name),
|
|
734
165
|
static: areStatic,
|
|
735
|
-
|
|
736
|
-
typeParameter: undefined,
|
|
166
|
+
holder: isParameterProperty(node) ? container.owner : undefined,
|
|
737
167
|
});
|
|
738
168
|
seen.set(key, record);
|
|
739
|
-
declareTypeParameters(node, record);
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
169
|
+
this.#declareTypeParameters(node, record);
|
|
170
|
+
}
|
|
171
|
+
/** The inventory of everything collected. */
|
|
172
|
+
build(cost) {
|
|
173
|
+
const byId = new Map(this.#records.map((record) => [positionKey(record.position), record]));
|
|
174
|
+
const symbols = this.#records.map(render).sort((a, b) => byPosition(a.position, b.position));
|
|
175
|
+
return {
|
|
176
|
+
symbols,
|
|
177
|
+
declarations: new Map([...this.#byNode].map(([key, record]) => [key, positionKey(record.position)])),
|
|
178
|
+
cost,
|
|
179
|
+
unanswered: symbols
|
|
180
|
+
.filter((symbol) => underUnanswered(byId.get(symbol.id), this.#unansweredOwners))
|
|
181
|
+
.map((symbol) => symbol.id),
|
|
182
|
+
byName: namesOf(this.#records),
|
|
183
|
+
modules: new Map(this.#modules.map(([record, name]) => [positionKey(record.position), name])),
|
|
184
|
+
ambient: new Set(this.#records
|
|
185
|
+
.filter((record) => isAmbient(record.file, record.node))
|
|
186
|
+
.map((record) => positionKey(record.position))),
|
|
187
|
+
dependents: dependentsOf(this.#containers, (node) => this.recordAt(node)),
|
|
188
|
+
placement: placementOf(this.#records),
|
|
189
|
+
openTables: new Set([...this.#openTables].map((file) => positionKey(file.position))),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
#keep(file, node, at, fields) {
|
|
193
|
+
const kept = {
|
|
194
|
+
file,
|
|
195
|
+
node,
|
|
196
|
+
position: renderPosition(file, this.#targetRoot, at),
|
|
197
|
+
endLine: this.#endOf(file, node),
|
|
198
|
+
localName: undefined,
|
|
199
|
+
visibility: "public",
|
|
200
|
+
static: false,
|
|
201
|
+
exported: false,
|
|
202
|
+
typeParameter: undefined,
|
|
203
|
+
holder: undefined,
|
|
204
|
+
...fields,
|
|
205
|
+
startLines: new Set(),
|
|
206
|
+
partLines: new Set(),
|
|
207
|
+
};
|
|
208
|
+
this.#records.push(kept);
|
|
209
|
+
this.#byNode.set(nodeKey(kept.file, kept.node), kept);
|
|
210
|
+
if (kept.kind !== "file") {
|
|
211
|
+
placeAt(kept, kept.node);
|
|
212
|
+
}
|
|
213
|
+
return kept;
|
|
214
|
+
}
|
|
215
|
+
#declareTypeParameters(node, owner) {
|
|
216
|
+
for (const parameter of typeParametersOf(node)) {
|
|
217
|
+
const name = nameNodeOf(parameter);
|
|
218
|
+
if (name === undefined) {
|
|
219
|
+
continue;
|
|
749
220
|
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
221
|
+
this.#keep(owner.file, parameter, name.getStart(), {
|
|
222
|
+
module: owner.module,
|
|
223
|
+
kind: "type-parameter",
|
|
224
|
+
parentChain: owner.parentChain,
|
|
225
|
+
component: owner.component,
|
|
226
|
+
parent: owner,
|
|
227
|
+
static: owner.static,
|
|
228
|
+
typeParameter: name.getText(),
|
|
229
|
+
});
|
|
754
230
|
}
|
|
755
|
-
|
|
756
|
-
|
|
231
|
+
}
|
|
232
|
+
#endOf(file, node) {
|
|
233
|
+
return renderPosition(file, this.#targetRoot, Math.max(node.end - 1, 0)).line;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/** The lines one declaring node binds its declaration on. */
|
|
237
|
+
function placeAt(record, node) {
|
|
238
|
+
const file = record.file;
|
|
239
|
+
record.startLines.add(startLine(file, node.pos));
|
|
240
|
+
for (const parameter of signatureOf(node)?.parameters ?? []) {
|
|
241
|
+
record.startLines.add(startLine(file, parameter.pos));
|
|
242
|
+
}
|
|
243
|
+
const list = node.parent;
|
|
244
|
+
if (node.kind === SyntaxKind.VariableDeclaration &&
|
|
245
|
+
list?.kind === SyntaxKind.VariableDeclarationList &&
|
|
246
|
+
list.parent.kind === SyntaxKind.VariableStatement) {
|
|
247
|
+
record.startLines.add(startLine(file, list.parent.pos));
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/** The modifier flags one node carries, and zero for a node that carries none. */
|
|
251
|
+
export function modifiersOf(node) {
|
|
252
|
+
return node.modifierFlags ?? 0;
|
|
253
|
+
}
|
|
254
|
+
/** The name node of one declaration, for the kinds that carry one. */
|
|
255
|
+
export function nameNodeOf(node) {
|
|
256
|
+
return node.name;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* The reference component one declaration name node spells, and undefined for a name the
|
|
260
|
+
* grammar does not represent: a binding pattern, and a computed key whose source text
|
|
261
|
+
* carries a closing bracket.
|
|
262
|
+
*/
|
|
263
|
+
export function componentOf(name) {
|
|
264
|
+
if (name === undefined) {
|
|
265
|
+
return undefined;
|
|
266
|
+
}
|
|
267
|
+
if (isComputedPropertyName(name)) {
|
|
268
|
+
const text = name.expression.getText();
|
|
269
|
+
return text.includes("]") ? undefined : { text, computed: true };
|
|
270
|
+
}
|
|
271
|
+
if (isIdentifier(name) || isPrivateIdentifier(name)) {
|
|
272
|
+
return { text: name.getText(), computed: false };
|
|
273
|
+
}
|
|
274
|
+
const text = name.getText();
|
|
275
|
+
if (text.startsWith('"') || text.startsWith("'") || text.startsWith("`")) {
|
|
276
|
+
// A string key's own text carries its quotes; the reference carries the value.
|
|
277
|
+
return { text: text.slice(1, -1), computed: false };
|
|
278
|
+
}
|
|
279
|
+
return /^[0-9]/u.test(text) ? { text, computed: false } : undefined;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* The component one declaration's reference carries, and its declared name where the two
|
|
283
|
+
* differ. A declaration its module exports as the default is named `default`, its export
|
|
284
|
+
* name, which a module has at most one of and an anonymous declaration has too.
|
|
285
|
+
*/
|
|
286
|
+
export function exportedAs(node, name) {
|
|
287
|
+
const declared = componentOf(name);
|
|
288
|
+
if ((modifiersOf(node) & ModifierFlags.Default) === 0) {
|
|
289
|
+
return { component: declared, localName: undefined };
|
|
290
|
+
}
|
|
291
|
+
return { component: { text: "default", computed: false }, localName: declared?.text };
|
|
292
|
+
}
|
|
293
|
+
/** One member's identity inside its container: its component, and its side of a class. */
|
|
294
|
+
export function memberKey(component, isStatic) {
|
|
295
|
+
return `${component.computed ? "[" : ""}${component.text}${isStatic ? ":static" : ""}`;
|
|
296
|
+
}
|
|
297
|
+
/** The visibility one member declaration's modifiers and name give it. */
|
|
298
|
+
function visibilityOf(node, name) {
|
|
299
|
+
if (name !== undefined && isPrivateIdentifier(name)) {
|
|
300
|
+
return "private-name";
|
|
301
|
+
}
|
|
302
|
+
const flags = modifiersOf(node);
|
|
303
|
+
if ((flags & ModifierFlags.Private) !== 0) {
|
|
304
|
+
return "private";
|
|
305
|
+
}
|
|
306
|
+
if ((flags & ModifierFlags.Protected) !== 0) {
|
|
307
|
+
return "protected";
|
|
308
|
+
}
|
|
309
|
+
return "public";
|
|
310
|
+
}
|
|
311
|
+
/** Whether a declaration is ambient: in a declaration file, or under a `declare` modifier. */
|
|
312
|
+
export function isAmbient(file, node) {
|
|
313
|
+
if (file.isDeclarationFile) {
|
|
314
|
+
return true;
|
|
315
|
+
}
|
|
316
|
+
for (let at = node; at !== undefined; at = at.parent) {
|
|
317
|
+
if ((modifiersOf(at) & ModifierFlags.Ambient) !== 0) {
|
|
318
|
+
return true;
|
|
757
319
|
}
|
|
758
|
-
|
|
759
|
-
|
|
320
|
+
}
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
/** The type parameters one node declares, and none for a node that declares none. */
|
|
324
|
+
function typeParametersOf(node) {
|
|
325
|
+
if (isFunctionDeclaration(node) ||
|
|
326
|
+
isMethodDeclaration(node) ||
|
|
327
|
+
isMethodSignatureDeclaration(node) ||
|
|
328
|
+
isClassDeclaration(node) ||
|
|
329
|
+
isInterfaceDeclaration(node) ||
|
|
330
|
+
isTypeAliasDeclaration(node)) {
|
|
331
|
+
return node.typeParameters ?? [];
|
|
332
|
+
}
|
|
333
|
+
return [];
|
|
334
|
+
}
|
|
335
|
+
/** `export default`, up to the keyword that stands where an unnamed default export's name would. */
|
|
336
|
+
const DEFAULT_EXPORT = /^export\s+(?=default\b)/u;
|
|
337
|
+
/**
|
|
338
|
+
* Where an unnamed declaration is placed: at `default` when it is the default export, so it
|
|
339
|
+
* never shares the file's own position, else at its first token.
|
|
340
|
+
*/
|
|
341
|
+
function unnamedStart(node) {
|
|
342
|
+
const start = node.getStart();
|
|
343
|
+
const prefix = DEFAULT_EXPORT.exec(node.getText());
|
|
344
|
+
return prefix === null ? start : start + prefix[0].length;
|
|
345
|
+
}
|
|
346
|
+
/** The kind one member of a container takes, and undefined for a node that is no member. */
|
|
347
|
+
function memberKindOf(container, node) {
|
|
348
|
+
if (container.memberKind === "class-member") {
|
|
349
|
+
if (isPropertyDeclaration(node) ||
|
|
350
|
+
isGetAccessorDeclaration(node) ||
|
|
351
|
+
isSetAccessorDeclaration(node) ||
|
|
352
|
+
isParameterProperty(node)) {
|
|
353
|
+
return "class-member";
|
|
760
354
|
}
|
|
761
|
-
return undefined;
|
|
355
|
+
return isMethodDeclaration(node) ? "method" : undefined;
|
|
356
|
+
}
|
|
357
|
+
if (container.memberKind === "enum-member") {
|
|
358
|
+
return isEnumMember(node) ? "enum-member" : undefined;
|
|
762
359
|
}
|
|
360
|
+
if (isMethodSignatureDeclaration(node)) {
|
|
361
|
+
return container.memberKind === "interface-method" ? "interface-method" : "type-member";
|
|
362
|
+
}
|
|
363
|
+
if (isPropertySignatureDeclaration(node) ||
|
|
364
|
+
isGetAccessorDeclaration(node) ||
|
|
365
|
+
isSetAccessorDeclaration(node)) {
|
|
366
|
+
return "type-member";
|
|
367
|
+
}
|
|
368
|
+
return undefined;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Each enum member's dependents: the later members of its declaration with no initializer,
|
|
372
|
+
* up to the first one with an initializer.
|
|
373
|
+
*/
|
|
374
|
+
function dependentsOf(containers, recordAt) {
|
|
763
375
|
const dependents = new Map();
|
|
764
376
|
for (const container of containers.filter((one) => one.memberKind === "enum-member")) {
|
|
765
377
|
const ids = container.members.map((member) => {
|
|
766
|
-
const record =
|
|
378
|
+
const record = recordAt(member);
|
|
767
379
|
return record === undefined ? undefined : positionKey(record.position);
|
|
768
380
|
});
|
|
769
381
|
container.members.forEach((_member, index) => {
|
|
@@ -784,22 +396,21 @@ export function inventory(project, host, targetRoot) {
|
|
|
784
396
|
}
|
|
785
397
|
});
|
|
786
398
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
};
|
|
399
|
+
return dependents;
|
|
400
|
+
}
|
|
401
|
+
/** Each declaration but a file to where a directive binds it. */
|
|
402
|
+
function placementOf(records) {
|
|
403
|
+
const ascending = (lines) => [...lines].sort((a, b) => a - b);
|
|
404
|
+
return new Map(records
|
|
405
|
+
.filter((record) => record.kind !== "file")
|
|
406
|
+
.map((record) => [
|
|
407
|
+
positionKey(record.position),
|
|
408
|
+
{
|
|
409
|
+
startLines: ascending(record.startLines),
|
|
410
|
+
holder: positionKey((record.holder ?? record).position),
|
|
411
|
+
partLines: ascending(record.partLines),
|
|
412
|
+
},
|
|
413
|
+
]));
|
|
803
414
|
}
|
|
804
415
|
/** Whether one declaration is, or is declared under, a scope or container left unanswered. */
|
|
805
416
|
function underUnanswered(record, owners) {
|
|
@@ -811,9 +422,9 @@ function underUnanswered(record, owners) {
|
|
|
811
422
|
return false;
|
|
812
423
|
}
|
|
813
424
|
/** Every declaration but a file, by each name a use may spell it with. */
|
|
814
|
-
function namesOf(
|
|
425
|
+
function namesOf(records) {
|
|
815
426
|
const byName = new Map();
|
|
816
|
-
for (const record of
|
|
427
|
+
for (const record of records) {
|
|
817
428
|
if (record.kind === "file") {
|
|
818
429
|
continue;
|
|
819
430
|
}
|
|
@@ -842,21 +453,17 @@ function chainOf(record) {
|
|
|
842
453
|
}
|
|
843
454
|
/**
|
|
844
455
|
* One declaration as the inventory reports it. The display name is the chain in the
|
|
845
|
-
* spelling a reference gives it, except where the declaration carries a name of its
|
|
846
|
-
*
|
|
847
|
-
* export, whose reference carries its export name.
|
|
456
|
+
* spelling a reference gives it, except where the declaration carries a name of its own
|
|
457
|
+
* the reference does not: a file, whose reference names its module, and a default export.
|
|
848
458
|
*/
|
|
849
459
|
function render(record) {
|
|
850
460
|
const chain = chainOf(record);
|
|
851
|
-
const spelled = chain
|
|
852
|
-
.map((component) => component.computed ? computedComponent(component.text) : nameComponent(component.text))
|
|
853
|
-
.join(".");
|
|
854
|
-
const name = record.localName ??
|
|
855
|
-
(record.typeParameter === undefined ? spelled : `${spelled}<${record.typeParameter}>`);
|
|
461
|
+
const spelled = chain.map(spell).join(".");
|
|
856
462
|
return {
|
|
857
463
|
id: positionKey(record.position),
|
|
858
464
|
ref: refOf(record, chain),
|
|
859
|
-
name
|
|
465
|
+
name: record.localName ??
|
|
466
|
+
(record.typeParameter === undefined ? spelled : `${spelled}<${record.typeParameter}>`),
|
|
860
467
|
kind: record.kind,
|
|
861
468
|
position: record.position,
|
|
862
469
|
endLine: record.endLine,
|
|
@@ -885,11 +492,3 @@ function refOf(record, chain) {
|
|
|
885
492
|
...(record.typeParameter === undefined ? {} : { typeParameter: record.typeParameter }),
|
|
886
493
|
});
|
|
887
494
|
}
|
|
888
|
-
/**
|
|
889
|
-
* Every declaration of an inventory other than a file, by each name a use may spell it
|
|
890
|
-
* with. It is how a reference the checker could not resolve is still counted, as a
|
|
891
|
-
* reference to every declaration that bears the name it spells.
|
|
892
|
-
*/
|
|
893
|
-
export function declarationsByName(held) {
|
|
894
|
-
return held.byName;
|
|
895
|
-
}
|