@flint.fyi/typescript-language 0.18.2 → 0.18.3
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/lib/collectReferencedFilePaths.js +1 -1
- package/lib/convertTypeScriptDiagnosticToLanguageReport.d.ts +2 -2
- package/lib/convertTypeScriptDiagnosticToLanguageReport.js +2 -1
- package/lib/createTypeScriptServerHost.d.ts +1 -1
- package/lib/createTypeScriptServerHost.js +1 -1
- package/lib/directives/parseDirectivesFromTypeScriptFile.js +2 -2
- package/lib/getTSNodeRange.d.ts +1 -1
- package/lib/index.d.ts +8 -3
- package/lib/index.js +5 -1
- package/lib/language.d.ts +392 -198
- package/lib/language.js +2 -2
- package/lib/package.js +1 -1
- package/lib/scope/identifierReferences.d.ts +4 -0
- package/lib/scope/identifierReferences.js +91 -0
- package/lib/scope/scopeManager.d.ts +15 -0
- package/lib/scope/scopeManager.js +149 -0
- package/lib/scope/scopes.d.ts +8 -0
- package/lib/scope/scopes.js +66 -0
- package/lib/scope/types.d.ts +39 -0
- package/lib/types/ast.d.ts +1 -0
- package/lib/utils/forEachChild.d.ts +8 -0
- package/lib/utils/forEachChild.js +7 -0
- package/lib/utils/getModifyingReferences.d.ts +1 -5
- package/lib/utils/getModifyingReferences.js +5 -25
- package/lib/utils/isBuiltinArrayMethod.d.ts +1 -1
- package/lib/utils/isStaticString.d.ts +6 -0
- package/lib/utils/isStaticString.js +9 -0
- package/lib/utils/isStringRawNoSubstitution.d.ts +8 -0
- package/lib/utils/isStringRawNoSubstitution.js +11 -0
- package/package.json +2 -2
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { SyntaxKind } from "typescript";
|
|
2
|
+
import * as tsutils from "ts-api-utils";
|
|
3
|
+
//#region src/scope/identifierReferences.ts
|
|
4
|
+
function isNonReferenceIdentifier(identifier) {
|
|
5
|
+
if (isIdentifierDeclaration(identifier) || isTypeReferenceIdentifier(identifier)) return true;
|
|
6
|
+
const { parent } = identifier;
|
|
7
|
+
switch (parent.kind) {
|
|
8
|
+
case SyntaxKind.BindingElement:
|
|
9
|
+
case SyntaxKind.ImportSpecifier: return parent.propertyName === identifier;
|
|
10
|
+
case SyntaxKind.BreakStatement:
|
|
11
|
+
case SyntaxKind.ContinueStatement:
|
|
12
|
+
case SyntaxKind.LabeledStatement: return parent.label === identifier;
|
|
13
|
+
case SyntaxKind.JsxAttribute:
|
|
14
|
+
case SyntaxKind.MethodDeclaration:
|
|
15
|
+
case SyntaxKind.MethodSignature:
|
|
16
|
+
case SyntaxKind.PropertyAccessExpression:
|
|
17
|
+
case SyntaxKind.PropertyAssignment:
|
|
18
|
+
case SyntaxKind.PropertyDeclaration:
|
|
19
|
+
case SyntaxKind.PropertySignature: return parent.name === identifier;
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
function isWriteReference(identifier) {
|
|
24
|
+
const { parent } = identifier;
|
|
25
|
+
if (isAssignmentTarget(identifier)) return true;
|
|
26
|
+
switch (parent.kind) {
|
|
27
|
+
case SyntaxKind.PostfixUnaryExpression:
|
|
28
|
+
case SyntaxKind.PrefixUnaryExpression: return parent.operand === identifier && (parent.operator === SyntaxKind.PlusPlusToken || parent.operator === SyntaxKind.MinusMinusToken);
|
|
29
|
+
default: return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function isAssignmentTarget(identifier) {
|
|
33
|
+
let current = identifier;
|
|
34
|
+
while (true) {
|
|
35
|
+
const parent = current.parent;
|
|
36
|
+
switch (parent.kind) {
|
|
37
|
+
case SyntaxKind.ArrayLiteralExpression:
|
|
38
|
+
case SyntaxKind.ObjectLiteralExpression:
|
|
39
|
+
case SyntaxKind.ShorthandPropertyAssignment:
|
|
40
|
+
current = parent;
|
|
41
|
+
continue;
|
|
42
|
+
case SyntaxKind.PropertyAssignment:
|
|
43
|
+
if (parent.name === current) return false;
|
|
44
|
+
current = parent;
|
|
45
|
+
continue;
|
|
46
|
+
case SyntaxKind.BinaryExpression: return parent.left === current && tsutils.isAssignmentKind(parent.operatorToken.kind);
|
|
47
|
+
case SyntaxKind.ForInStatement:
|
|
48
|
+
case SyntaxKind.ForOfStatement: return parent.initializer === current;
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function isIdentifierDeclaration(identifier) {
|
|
54
|
+
const { parent } = identifier;
|
|
55
|
+
switch (parent.kind) {
|
|
56
|
+
case SyntaxKind.BindingElement:
|
|
57
|
+
case SyntaxKind.Parameter:
|
|
58
|
+
case SyntaxKind.VariableDeclaration: return isIdentifierWithinParent(identifier, parent.name);
|
|
59
|
+
case SyntaxKind.ClassDeclaration:
|
|
60
|
+
case SyntaxKind.ClassExpression:
|
|
61
|
+
case SyntaxKind.FunctionDeclaration:
|
|
62
|
+
case SyntaxKind.FunctionExpression:
|
|
63
|
+
case SyntaxKind.InterfaceDeclaration:
|
|
64
|
+
case SyntaxKind.ModuleDeclaration:
|
|
65
|
+
case SyntaxKind.TypeAliasDeclaration: return parent.name === identifier;
|
|
66
|
+
case SyntaxKind.ImportClause:
|
|
67
|
+
case SyntaxKind.ImportSpecifier:
|
|
68
|
+
case SyntaxKind.NamespaceImport: return parent.name === identifier;
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
function isIdentifierWithinParent(identifier, parent) {
|
|
73
|
+
let current = identifier;
|
|
74
|
+
while (current !== parent) {
|
|
75
|
+
const next = current.parent;
|
|
76
|
+
if (!next) return false;
|
|
77
|
+
current = next;
|
|
78
|
+
}
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
function isTypeReferenceIdentifier(identifier) {
|
|
82
|
+
let current = identifier;
|
|
83
|
+
while (current.parent.kind === SyntaxKind.QualifiedName) current = current.parent;
|
|
84
|
+
const parent = current.parent;
|
|
85
|
+
if (parent.kind !== SyntaxKind.TypeReference) return false;
|
|
86
|
+
return isIdentifierWithinParent(identifier, parent.typeName);
|
|
87
|
+
}
|
|
88
|
+
//#endregion
|
|
89
|
+
export { isNonReferenceIdentifier, isWriteReference };
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=identifierReferences.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AnyNode, Identifier, SourceFile } from "../types/ast.js";
|
|
2
|
+
import { FunctionWithParameters, Scope, ScopeInternal, ScopeManager, ScopeReference, ScopeVariable } from "./types.js";
|
|
3
|
+
|
|
4
|
+
//#region src/scope/scopeManager.d.ts
|
|
5
|
+
declare function createScopeManager(sourceFile: SourceFile): {
|
|
6
|
+
findVariable(identifier: Identifier): ScopeVariable | undefined;
|
|
7
|
+
getDeclaredVariables(node: AnyNode): ScopeVariable[];
|
|
8
|
+
getReferencesInScope(node: AnyNode): ScopeReference[];
|
|
9
|
+
getScope(node: AnyNode): ScopeInternal;
|
|
10
|
+
globalScope: ScopeInternal;
|
|
11
|
+
};
|
|
12
|
+
declare function getScopeManager(sourceFile: SourceFile): ScopeManager;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { createScopeManager, getScopeManager };
|
|
15
|
+
//# sourceMappingURL=scopeManager.d.ts.map
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { forEachChild } from "../utils/forEachChild.js";
|
|
2
|
+
import { isNonReferenceIdentifier, isWriteReference } from "./identifierReferences.js";
|
|
3
|
+
import { createScope, getReferencesInScope, getVariableDeclarationScope, isScopeBoundary, resolveVariable } from "./scopes.js";
|
|
4
|
+
import { SyntaxKind } from "typescript";
|
|
5
|
+
//#region src/scope/scopeManager.ts
|
|
6
|
+
const scopeManagers = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
function createScopeManager(sourceFile) {
|
|
8
|
+
const declarationVariablesByIdentifier = /* @__PURE__ */ new WeakMap();
|
|
9
|
+
const declaredVariablesByNode = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
const nodeScopes = /* @__PURE__ */ new WeakMap();
|
|
11
|
+
const globalScope = createScope(sourceFile, void 0);
|
|
12
|
+
function addBindingName(scope, name, node) {
|
|
13
|
+
if (name.kind === SyntaxKind.Identifier) return [addVariable(scope, name, node)];
|
|
14
|
+
const variables = [];
|
|
15
|
+
for (const element of name.elements) if (element.kind !== SyntaxKind.OmittedExpression) variables.push(...addBindingName(scope, element.name, node));
|
|
16
|
+
return variables;
|
|
17
|
+
}
|
|
18
|
+
function addImportVariables(scope, node) {
|
|
19
|
+
if (!node.importClause || node.importClause.isTypeOnly) return;
|
|
20
|
+
if (node.importClause.name) addVariable(scope, node.importClause.name, node);
|
|
21
|
+
const { namedBindings } = node.importClause;
|
|
22
|
+
if (!namedBindings) return;
|
|
23
|
+
if (namedBindings.kind === SyntaxKind.NamespaceImport) {
|
|
24
|
+
addVariable(scope, namedBindings.name, node);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
for (const element of namedBindings.elements) {
|
|
28
|
+
if (element.isTypeOnly) continue;
|
|
29
|
+
addVariable(scope, element.name, node);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function addParameters(scope, node) {
|
|
33
|
+
for (const parameter of node.parameters) {
|
|
34
|
+
const variables = addBindingName(scope, parameter.name, node);
|
|
35
|
+
declaredVariablesByNode.set(parameter, variables);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function addVariable(scope, identifier, node) {
|
|
39
|
+
let variable = scope.variablesByName.get(identifier.text);
|
|
40
|
+
if (!variable) {
|
|
41
|
+
variable = {
|
|
42
|
+
declarations: [],
|
|
43
|
+
name: identifier.text,
|
|
44
|
+
references: [],
|
|
45
|
+
scope
|
|
46
|
+
};
|
|
47
|
+
scope.variablesByName.set(identifier.text, variable);
|
|
48
|
+
scope.variables.push(variable);
|
|
49
|
+
}
|
|
50
|
+
variable.declarations.push(identifier);
|
|
51
|
+
declarationVariablesByIdentifier.set(identifier, variable);
|
|
52
|
+
const declaredVariables = declaredVariablesByNode.get(node) ?? [];
|
|
53
|
+
declaredVariables.push(variable);
|
|
54
|
+
declaredVariablesByNode.set(node, declaredVariables);
|
|
55
|
+
return variable;
|
|
56
|
+
}
|
|
57
|
+
function collectDeclarations(node, scope) {
|
|
58
|
+
const nodeScope = node !== sourceFile && isScopeBoundary(node) ? createScope(node, scope) : scope;
|
|
59
|
+
nodeScopes.set(node, nodeScope);
|
|
60
|
+
switch (node.kind) {
|
|
61
|
+
case SyntaxKind.ArrowFunction:
|
|
62
|
+
case SyntaxKind.Constructor:
|
|
63
|
+
case SyntaxKind.GetAccessor:
|
|
64
|
+
case SyntaxKind.MethodDeclaration:
|
|
65
|
+
case SyntaxKind.SetAccessor:
|
|
66
|
+
addParameters(nodeScope, node);
|
|
67
|
+
break;
|
|
68
|
+
case SyntaxKind.CatchClause:
|
|
69
|
+
if (node.variableDeclaration) addBindingName(nodeScope, node.variableDeclaration.name, node);
|
|
70
|
+
break;
|
|
71
|
+
case SyntaxKind.ClassDeclaration:
|
|
72
|
+
if (node.name) addVariable(nodeScope, node.name, node);
|
|
73
|
+
break;
|
|
74
|
+
case SyntaxKind.ClassExpression:
|
|
75
|
+
if (node.name) addVariable(nodeScope, node.name, node);
|
|
76
|
+
break;
|
|
77
|
+
case SyntaxKind.FunctionDeclaration:
|
|
78
|
+
if (node.name) addVariable(scope, node.name, node);
|
|
79
|
+
addParameters(nodeScope, node);
|
|
80
|
+
break;
|
|
81
|
+
case SyntaxKind.FunctionExpression:
|
|
82
|
+
if (node.name) addVariable(nodeScope, node.name, node);
|
|
83
|
+
addParameters(nodeScope, node);
|
|
84
|
+
break;
|
|
85
|
+
case SyntaxKind.ImportDeclaration:
|
|
86
|
+
addImportVariables(nodeScope, node);
|
|
87
|
+
break;
|
|
88
|
+
case SyntaxKind.VariableDeclaration:
|
|
89
|
+
if (node.parent.kind === SyntaxKind.CatchClause) {
|
|
90
|
+
forEachChild(node, (child) => {
|
|
91
|
+
collectDeclarations(child, nodeScope);
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
addBindingName(getVariableDeclarationScope(node, nodeScope), node.name, node);
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
forEachChild(node, (child) => {
|
|
99
|
+
collectDeclarations(child, nodeScope);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function collectReferences(node) {
|
|
103
|
+
if (node.kind === SyntaxKind.Identifier && !isNonReferenceIdentifier(node)) {
|
|
104
|
+
const scope = nodeScopes.get(node) ?? globalScope;
|
|
105
|
+
const variable = resolveVariable(scope, node.text);
|
|
106
|
+
const reference = {
|
|
107
|
+
from: scope,
|
|
108
|
+
identifier: node,
|
|
109
|
+
isWrite: isWriteReference(node),
|
|
110
|
+
text: node.text,
|
|
111
|
+
variable
|
|
112
|
+
};
|
|
113
|
+
scope.references.push(reference);
|
|
114
|
+
variable?.references.push(reference);
|
|
115
|
+
}
|
|
116
|
+
forEachChild(node, collectReferences);
|
|
117
|
+
}
|
|
118
|
+
collectDeclarations(sourceFile, globalScope);
|
|
119
|
+
collectReferences(sourceFile);
|
|
120
|
+
return {
|
|
121
|
+
findVariable(identifier) {
|
|
122
|
+
const declarationVariable = declarationVariablesByIdentifier.get(identifier);
|
|
123
|
+
if (declarationVariable) return declarationVariable;
|
|
124
|
+
return resolveVariable(nodeScopes.get(identifier) ?? globalScope, identifier.text);
|
|
125
|
+
},
|
|
126
|
+
getDeclaredVariables(node) {
|
|
127
|
+
return declaredVariablesByNode.get(node) ?? [];
|
|
128
|
+
},
|
|
129
|
+
getReferencesInScope(node) {
|
|
130
|
+
return getReferencesInScope(nodeScopes.get(node) ?? globalScope);
|
|
131
|
+
},
|
|
132
|
+
getScope(node) {
|
|
133
|
+
return nodeScopes.get(node) ?? globalScope;
|
|
134
|
+
},
|
|
135
|
+
globalScope
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function getScopeManager(sourceFile) {
|
|
139
|
+
let scopeManager = scopeManagers.get(sourceFile);
|
|
140
|
+
if (!scopeManager) {
|
|
141
|
+
scopeManager = createScopeManager(sourceFile);
|
|
142
|
+
scopeManagers.set(sourceFile, scopeManager);
|
|
143
|
+
}
|
|
144
|
+
return scopeManager;
|
|
145
|
+
}
|
|
146
|
+
//#endregion
|
|
147
|
+
export { createScopeManager, getScopeManager };
|
|
148
|
+
|
|
149
|
+
//# sourceMappingURL=scopeManager.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type * as AST from "../types/ast.ts";
|
|
2
|
+
import type { ScopeInternal, ScopeVariable } from "./types.ts";
|
|
3
|
+
export declare function createScope(block: AST.AnyNode, upper: ScopeInternal | undefined): ScopeInternal;
|
|
4
|
+
export declare function getReferencesInScope(scope: ScopeInternal): import("./types.ts").ScopeReference[];
|
|
5
|
+
export declare function getVariableDeclarationScope(node: AST.VariableDeclaration, scope: ScopeInternal): ScopeInternal;
|
|
6
|
+
export declare function isScopeBoundary(node: AST.AnyNode): boolean;
|
|
7
|
+
export declare function resolveVariable(scope: ScopeInternal, name: string): ScopeVariable | undefined;
|
|
8
|
+
//# sourceMappingURL=scopes.d.ts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import ts, { SyntaxKind } from "typescript";
|
|
2
|
+
//#region src/scope/scopes.ts
|
|
3
|
+
function createScope(block, upper) {
|
|
4
|
+
const variablesByName = /* @__PURE__ */ new Map();
|
|
5
|
+
const scope = {
|
|
6
|
+
block,
|
|
7
|
+
childScopes: [],
|
|
8
|
+
references: [],
|
|
9
|
+
upper,
|
|
10
|
+
variables: [],
|
|
11
|
+
variablesByName
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(scope, "variablesByName", {
|
|
14
|
+
enumerable: false,
|
|
15
|
+
value: variablesByName
|
|
16
|
+
});
|
|
17
|
+
upper?.childScopes.push(scope);
|
|
18
|
+
return scope;
|
|
19
|
+
}
|
|
20
|
+
function getReferencesInScope(scope) {
|
|
21
|
+
const references = [...scope.references];
|
|
22
|
+
for (const childScope of scope.childScopes) if (!isFunctionLike(childScope.block)) references.push(...getReferencesInScope(childScope));
|
|
23
|
+
return references;
|
|
24
|
+
}
|
|
25
|
+
function getVariableDeclarationScope(node, scope) {
|
|
26
|
+
if (node.parent.kind === SyntaxKind.VariableDeclarationList && !(node.parent.flags & ts.NodeFlags.BlockScoped)) return findContainingVariableScope(scope);
|
|
27
|
+
return scope;
|
|
28
|
+
}
|
|
29
|
+
function isScopeBoundary(node) {
|
|
30
|
+
return isFunctionLike(node) || node.kind === SyntaxKind.CatchClause || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.ForInStatement || node.kind === SyntaxKind.ForOfStatement || node.kind === SyntaxKind.ForStatement || isBlockScopeBoundary(node);
|
|
31
|
+
}
|
|
32
|
+
function resolveVariable(scope, name) {
|
|
33
|
+
let current = scope;
|
|
34
|
+
while (current) {
|
|
35
|
+
const variable = current.variablesByName.get(name);
|
|
36
|
+
if (variable) return variable;
|
|
37
|
+
current = current.upper;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function findContainingVariableScope(scope) {
|
|
41
|
+
let current = scope;
|
|
42
|
+
while (current.upper && !isVariableScopeBoundary(current.block)) current = current.upper;
|
|
43
|
+
return current;
|
|
44
|
+
}
|
|
45
|
+
function isBlockScopeBoundary(node) {
|
|
46
|
+
return node.kind === SyntaxKind.Block && node.parent.kind !== SyntaxKind.CatchClause && !isFunctionLike(node.parent);
|
|
47
|
+
}
|
|
48
|
+
function isFunctionLike(node) {
|
|
49
|
+
switch (node?.kind) {
|
|
50
|
+
case SyntaxKind.ArrowFunction:
|
|
51
|
+
case SyntaxKind.Constructor:
|
|
52
|
+
case SyntaxKind.FunctionDeclaration:
|
|
53
|
+
case SyntaxKind.FunctionExpression:
|
|
54
|
+
case SyntaxKind.GetAccessor:
|
|
55
|
+
case SyntaxKind.MethodDeclaration:
|
|
56
|
+
case SyntaxKind.SetAccessor: return true;
|
|
57
|
+
default: return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function isVariableScopeBoundary(node) {
|
|
61
|
+
return node.kind === SyntaxKind.SourceFile || isFunctionLike(node);
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { createScope, getReferencesInScope, getVariableDeclarationScope, isScopeBoundary, resolveVariable };
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=scopes.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { AnyNode, ArrowFunction, ConstructorDeclaration, FunctionDeclaration, FunctionExpression, GetAccessorDeclaration, Identifier, MethodDeclaration, SetAccessorDeclaration } from "../types/ast.js";
|
|
2
|
+
|
|
3
|
+
//#region src/scope/types.d.ts
|
|
4
|
+
type FunctionWithParameters = ArrowFunction | ConstructorDeclaration | FunctionDeclaration | FunctionExpression | GetAccessorDeclaration | MethodDeclaration | SetAccessorDeclaration;
|
|
5
|
+
interface Scope {
|
|
6
|
+
block: AnyNode;
|
|
7
|
+
childScopes: Scope[];
|
|
8
|
+
references: ScopeReference[];
|
|
9
|
+
upper: Scope | undefined;
|
|
10
|
+
variables: ScopeVariable[];
|
|
11
|
+
}
|
|
12
|
+
interface ScopeInternal extends Scope {
|
|
13
|
+
childScopes: ScopeInternal[];
|
|
14
|
+
upper: ScopeInternal | undefined;
|
|
15
|
+
variablesByName: Map<string, ScopeVariable>;
|
|
16
|
+
}
|
|
17
|
+
interface ScopeManager {
|
|
18
|
+
findVariable(identifier: Identifier): ScopeVariable | undefined;
|
|
19
|
+
getDeclaredVariables(node: AnyNode): ScopeVariable[];
|
|
20
|
+
getReferencesInScope(node: AnyNode): ScopeReference[];
|
|
21
|
+
getScope(node: AnyNode): Scope;
|
|
22
|
+
globalScope: Scope;
|
|
23
|
+
}
|
|
24
|
+
interface ScopeReference {
|
|
25
|
+
from: Scope;
|
|
26
|
+
identifier: Identifier;
|
|
27
|
+
isWrite: boolean;
|
|
28
|
+
text: string;
|
|
29
|
+
variable: ScopeVariable | undefined;
|
|
30
|
+
}
|
|
31
|
+
interface ScopeVariable {
|
|
32
|
+
declarations: Identifier[];
|
|
33
|
+
name: string;
|
|
34
|
+
references: ScopeReference[];
|
|
35
|
+
scope: Scope;
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { FunctionWithParameters, Scope, ScopeInternal, ScopeManager, ScopeReference, ScopeVariable };
|
|
39
|
+
//# sourceMappingURL=types.d.ts.map
|
package/lib/types/ast.d.ts
CHANGED
|
@@ -1662,6 +1662,7 @@ interface SourceFile extends ts.Node {
|
|
|
1662
1662
|
libReferenceDirectives: readonly ts.FileReference[];
|
|
1663
1663
|
moduleName?: string;
|
|
1664
1664
|
readonly parent: NullNode;
|
|
1665
|
+
path: ts.Path;
|
|
1665
1666
|
referencedFiles: readonly ts.FileReference[];
|
|
1666
1667
|
readonly statements: ts.NodeArray<Statement>;
|
|
1667
1668
|
text: string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AnyNode } from "../types/ast.js";
|
|
2
|
+
import ts from "typescript";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/forEachChild.d.ts
|
|
5
|
+
declare const forEachChild: <T>(node: AnyNode, cbNode: (node: AnyNode) => T | undefined, cbNodes?: (nodes: ts.NodeArray<AnyNode>) => T | undefined) => T | undefined;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { forEachChild };
|
|
8
|
+
//# sourceMappingURL=forEachChild.d.ts.map
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import { Identifier, SourceFile } from "../types/ast.js";
|
|
2
|
-
import { Checker } from "../types/checker.js";
|
|
3
|
-
import ts from "typescript";
|
|
4
2
|
|
|
5
3
|
//#region src/utils/getModifyingReferences.d.ts
|
|
6
4
|
/**
|
|
7
5
|
* Gets all references to a variable that modify it (assignments, increments, decrements).
|
|
8
|
-
*
|
|
9
|
-
* TODO: Replace with a proper scope manager when available (see #400).
|
|
10
6
|
* @returns An array of identifier nodes that modify the variable.
|
|
11
7
|
*/
|
|
12
|
-
declare function getModifyingReferences(identifier: Identifier, sourceFile: SourceFile
|
|
8
|
+
declare function getModifyingReferences(identifier: Identifier, sourceFile: SourceFile): Identifier[];
|
|
13
9
|
//#endregion
|
|
14
10
|
export { getModifyingReferences };
|
|
15
11
|
//# sourceMappingURL=getModifyingReferences.d.ts.map
|
|
@@ -1,33 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as tsutils from "ts-api-utils";
|
|
1
|
+
import { getScopeManager } from "../scope/scopeManager.js";
|
|
3
2
|
//#region src/utils/getModifyingReferences.ts
|
|
4
3
|
/**
|
|
5
4
|
* Gets all references to a variable that modify it (assignments, increments, decrements).
|
|
6
|
-
*
|
|
7
|
-
* TODO: Replace with a proper scope manager when available (see #400).
|
|
8
5
|
* @returns An array of identifier nodes that modify the variable.
|
|
9
6
|
*/
|
|
10
|
-
function getModifyingReferences(identifier, sourceFile
|
|
11
|
-
const
|
|
12
|
-
if (!
|
|
13
|
-
|
|
14
|
-
const modifyingReferences = [];
|
|
15
|
-
function isIdentifierForSameSymbol(node) {
|
|
16
|
-
if (node.kind !== ts.SyntaxKind.Identifier) return false;
|
|
17
|
-
if (typeChecker.getSymbolAtLocation(node)?.valueDeclaration !== valueDeclaration) return false;
|
|
18
|
-
switch (node.parent.kind) {
|
|
19
|
-
case ts.SyntaxKind.BinaryExpression: return tsutils.isAssignmentKind(node.parent.operatorToken.kind) && node.parent.left === node;
|
|
20
|
-
case ts.SyntaxKind.PostfixUnaryExpression:
|
|
21
|
-
case ts.SyntaxKind.PrefixUnaryExpression: return node.parent.operand === node;
|
|
22
|
-
default: return false;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
function visit(node) {
|
|
26
|
-
if (isIdentifierForSameSymbol(node)) modifyingReferences.push(node);
|
|
27
|
-
ts.forEachChild(node, visit);
|
|
28
|
-
}
|
|
29
|
-
visit(sourceFile);
|
|
30
|
-
return modifyingReferences;
|
|
7
|
+
function getModifyingReferences(identifier, sourceFile) {
|
|
8
|
+
const variable = getScopeManager(sourceFile).findVariable(identifier);
|
|
9
|
+
if (!variable || variable.declarations.length > 1) return [];
|
|
10
|
+
return variable.references.filter((reference) => reference.isWrite).map((reference) => reference.identifier);
|
|
31
11
|
}
|
|
32
12
|
//#endregion
|
|
33
13
|
export { getModifyingReferences };
|
|
@@ -10,5 +10,5 @@ type BuiltInArrayMethodNode = CallExpression & {
|
|
|
10
10
|
};
|
|
11
11
|
declare function isBuiltinArrayMethod(name: string, node: CallExpression, typeChecker: Checker): node is BuiltInArrayMethodNode;
|
|
12
12
|
//#endregion
|
|
13
|
-
export { isBuiltinArrayMethod };
|
|
13
|
+
export { BuiltInArrayMethodNode, isBuiltinArrayMethod };
|
|
14
14
|
//# sourceMappingURL=isBuiltinArrayMethod.d.ts.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Expression, NoSubstitutionTemplateLiteral, StringLiteral } from "../types/ast.js";
|
|
2
|
+
//#region src/utils/isStaticString.d.ts
|
|
3
|
+
declare function isStaticString(node: Expression): node is NoSubstitutionTemplateLiteral | StringLiteral;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { isStaticString };
|
|
6
|
+
//# sourceMappingURL=isStaticString.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SyntaxKind } from "typescript";
|
|
2
|
+
//#region src/utils/isStaticString.ts
|
|
3
|
+
function isStaticString(node) {
|
|
4
|
+
return node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
|
|
5
|
+
}
|
|
6
|
+
//#endregion
|
|
7
|
+
export { isStaticString };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=isStaticString.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Expression, NoSubstitutionTemplateLiteral, TaggedTemplateExpression } from "../types/ast.js";
|
|
2
|
+
//#region src/utils/isStringRawNoSubstitution.d.ts
|
|
3
|
+
declare function isStringRawNoSubstitution(node: Expression): node is TaggedTemplateExpression & {
|
|
4
|
+
template: NoSubstitutionTemplateLiteral;
|
|
5
|
+
};
|
|
6
|
+
//#endregion
|
|
7
|
+
export { isStringRawNoSubstitution };
|
|
8
|
+
//# sourceMappingURL=isStringRawNoSubstitution.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SyntaxKind } from "typescript";
|
|
2
|
+
//#region src/utils/isStringRawNoSubstitution.ts
|
|
3
|
+
function isStringRawNoSubstitution(node) {
|
|
4
|
+
if (node.kind !== SyntaxKind.TaggedTemplateExpression) return false;
|
|
5
|
+
const tag = node.tag;
|
|
6
|
+
return tag.kind === SyntaxKind.PropertyAccessExpression && tag.expression.kind === SyntaxKind.Identifier && tag.expression.text === "String" && tag.name.kind === SyntaxKind.Identifier && tag.name.text === "raw" && node.template.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { isStringRawNoSubstitution };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=isStringRawNoSubstitution.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flint.fyi/typescript-language",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.3",
|
|
4
4
|
"description": "[Experimental] TypeScript language for Flint.",
|
|
5
5
|
"homepage": "https://flint.fyi",
|
|
6
6
|
"repository": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"pathe": "^2.0.3",
|
|
29
29
|
"ts-api-utils": "^2.4.0",
|
|
30
30
|
"typescript": "^5.9.0 || ^6.0.0",
|
|
31
|
-
"@flint.fyi/core": "^0.
|
|
31
|
+
"@flint.fyi/core": "^0.23.0",
|
|
32
32
|
"@flint.fyi/utils": "^0.14.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|