@opensip-tools/lang-typescript 1.0.4
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/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/LICENSE +21 -0
- package/dist/__tests__/adapter.test.d.ts +2 -0
- package/dist/__tests__/adapter.test.d.ts.map +1 -0
- package/dist/__tests__/adapter.test.js +56 -0
- package/dist/__tests__/adapter.test.js.map +1 -0
- package/dist/__tests__/ast-utilities.test.d.ts +2 -0
- package/dist/__tests__/ast-utilities.test.d.ts.map +1 -0
- package/dist/__tests__/ast-utilities.test.js +237 -0
- package/dist/__tests__/ast-utilities.test.js.map +1 -0
- package/dist/adapter.d.ts +6 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +15 -0
- package/dist/adapter.js.map +1 -0
- package/dist/ast-utilities.d.ts +74 -0
- package/dist/ast-utilities.d.ts.map +1 -0
- package/dist/ast-utilities.js +217 -0
- package/dist/ast-utilities.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/parse.d.ts +10 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +18 -0
- package/dist/parse.js.map +1 -0
- package/dist/query.d.ts +4 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +74 -0
- package/dist/query.js.map +1 -0
- package/dist/strip.d.ts +19 -0
- package/dist/strip.d.ts.map +1 -0
- package/dist/strip.js +26 -0
- package/dist/strip.js.map +1 -0
- package/package.json +41 -0
- package/src/__tests__/adapter.test.ts +67 -0
- package/src/__tests__/ast-utilities.test.ts +252 -0
- package/src/adapter.ts +21 -0
- package/src/ast-utilities.ts +238 -0
- package/src/index.ts +26 -0
- package/src/parse.ts +22 -0
- package/src/query.ts +76 -0
- package/src/strip.ts +30 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// @fitness-ignore-file batch-operation-limits -- iterates bounded collections (config entries, registry items, or small analysis results)
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Shared AST utilities for fitness checks.
|
|
4
|
+
*
|
|
5
|
+
* Common TypeScript AST operations for source parsing, tree walking,
|
|
6
|
+
* and node inspection. Used by AST-based fitness checks. Lives in
|
|
7
|
+
* @opensip-tools/lang-typescript so the dependency on `typescript` is
|
|
8
|
+
* isolated to the language pack.
|
|
9
|
+
*/
|
|
10
|
+
import { getParseTree } from '@opensip-tools/core/languages/parse-cache.js';
|
|
11
|
+
import * as ts from 'typescript';
|
|
12
|
+
import { typescriptAdapter } from './adapter.js';
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// SOURCE PARSING
|
|
15
|
+
// =============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Parse TypeScript/JavaScript source into an AST SourceFile.
|
|
18
|
+
* Returns null on parse failure.
|
|
19
|
+
*/
|
|
20
|
+
export function parseSource(content, filePath) {
|
|
21
|
+
try {
|
|
22
|
+
return ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Cached parse — uses the language-aware parse cache via the registered
|
|
30
|
+
* TS adapter. Falls back to a direct parse when no cache is active.
|
|
31
|
+
*/
|
|
32
|
+
export function getSharedSourceFile(filePath, content) {
|
|
33
|
+
return getParseTree(typescriptAdapter, filePath, content);
|
|
34
|
+
}
|
|
35
|
+
// =============================================================================
|
|
36
|
+
// TREE WALKING
|
|
37
|
+
// =============================================================================
|
|
38
|
+
/**
|
|
39
|
+
* Depth-first walk of all nodes in a SourceFile or subtree.
|
|
40
|
+
*/
|
|
41
|
+
export function walkNodes(root, visitor) {
|
|
42
|
+
function visit(node) {
|
|
43
|
+
visitor(node);
|
|
44
|
+
ts.forEachChild(node, visit);
|
|
45
|
+
}
|
|
46
|
+
ts.forEachChild(root, visit);
|
|
47
|
+
}
|
|
48
|
+
// =============================================================================
|
|
49
|
+
// NODE INSPECTION
|
|
50
|
+
// =============================================================================
|
|
51
|
+
/**
|
|
52
|
+
* Get the leaf identifier text from an expression node.
|
|
53
|
+
*/
|
|
54
|
+
export function getIdentifierName(node) {
|
|
55
|
+
if (ts.isIdentifier(node))
|
|
56
|
+
return node.text;
|
|
57
|
+
if (ts.isPropertyAccessExpression(node))
|
|
58
|
+
return node.name.text;
|
|
59
|
+
return '';
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get the full dotted path of a property access chain.
|
|
63
|
+
*/
|
|
64
|
+
export function getPropertyChain(node) {
|
|
65
|
+
if (ts.isIdentifier(node))
|
|
66
|
+
return node.text;
|
|
67
|
+
if (ts.isPropertyAccessExpression(node)) {
|
|
68
|
+
return `${getPropertyChain(node.expression)}.${node.name.text}`;
|
|
69
|
+
}
|
|
70
|
+
return '';
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get the 1-indexed line number for a node.
|
|
74
|
+
*/
|
|
75
|
+
export function getLineNumber(node, sourceFile) {
|
|
76
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
77
|
+
return line + 1;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get the column number (0-indexed) for a node.
|
|
81
|
+
*/
|
|
82
|
+
export function getColumn(node, sourceFile) {
|
|
83
|
+
const { character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
84
|
+
return character;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if a node is a property access matching a specific property name.
|
|
88
|
+
*/
|
|
89
|
+
export function isPropertyAccess(node, propertyName) {
|
|
90
|
+
return ts.isPropertyAccessExpression(node) && node.name.text === propertyName;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if a node is a literal value.
|
|
94
|
+
*/
|
|
95
|
+
export function isLiteral(node) {
|
|
96
|
+
if (ts.isStringLiteral(node) || ts.isNumericLiteral(node))
|
|
97
|
+
return true;
|
|
98
|
+
if (ts.isNoSubstitutionTemplateLiteral(node))
|
|
99
|
+
return true;
|
|
100
|
+
if (node.kind === ts.SyntaxKind.TrueKeyword || node.kind === ts.SyntaxKind.FalseKeyword)
|
|
101
|
+
return true;
|
|
102
|
+
if (node.kind === ts.SyntaxKind.NullKeyword)
|
|
103
|
+
return true;
|
|
104
|
+
if (ts.isIdentifier(node) && node.text === 'undefined')
|
|
105
|
+
return true;
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if a node is inside a string literal or template literal.
|
|
110
|
+
*/
|
|
111
|
+
export function isInStringLiteral(node) {
|
|
112
|
+
let current = node.parent;
|
|
113
|
+
while (!ts.isSourceFile(current)) {
|
|
114
|
+
if (ts.isStringLiteral(current) ||
|
|
115
|
+
ts.isNoSubstitutionTemplateLiteral(current) ||
|
|
116
|
+
ts.isTemplateExpression(current)) {
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
current = current.parent;
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
// =============================================================================
|
|
124
|
+
// NODE FINDERS
|
|
125
|
+
// =============================================================================
|
|
126
|
+
/**
|
|
127
|
+
* Find all call expressions matching `object.method()` pattern.
|
|
128
|
+
*/
|
|
129
|
+
export function findCallExpressions(root, objectName, methodName) {
|
|
130
|
+
const results = [];
|
|
131
|
+
walkNodes(root, (node) => {
|
|
132
|
+
if (!ts.isCallExpression(node))
|
|
133
|
+
return;
|
|
134
|
+
const expr = node.expression;
|
|
135
|
+
if (!ts.isPropertyAccessExpression(expr))
|
|
136
|
+
return;
|
|
137
|
+
if (expr.name.text !== methodName)
|
|
138
|
+
return;
|
|
139
|
+
const chain = getPropertyChain(expr.expression);
|
|
140
|
+
if (chain === objectName || chain.endsWith(`.${objectName}`)) {
|
|
141
|
+
results.push(node);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
return results;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Find all binary expressions with a specific operator.
|
|
148
|
+
*/
|
|
149
|
+
export function findBinaryExpressions(root, operator) {
|
|
150
|
+
const results = [];
|
|
151
|
+
walkNodes(root, (node) => {
|
|
152
|
+
if (ts.isBinaryExpression(node) && node.operatorToken.kind === operator) {
|
|
153
|
+
results.push(node);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
return results;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Find all template literal expressions (with substitutions).
|
|
160
|
+
*/
|
|
161
|
+
export function findTemplateLiterals(root) {
|
|
162
|
+
const results = [];
|
|
163
|
+
walkNodes(root, (node) => {
|
|
164
|
+
if (ts.isTemplateExpression(node)) {
|
|
165
|
+
results.push(node);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
return results;
|
|
169
|
+
}
|
|
170
|
+
// =============================================================================
|
|
171
|
+
// COMMENT DETECTION
|
|
172
|
+
// =============================================================================
|
|
173
|
+
function isPositionInRanges(position, ranges) {
|
|
174
|
+
if (!ranges)
|
|
175
|
+
return false;
|
|
176
|
+
for (const range of ranges) {
|
|
177
|
+
if (position >= range.pos && position < range.end)
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Check if a position in the source falls inside a comment.
|
|
184
|
+
*/
|
|
185
|
+
export function isInComment(position, sourceFile) {
|
|
186
|
+
const text = sourceFile.getFullText();
|
|
187
|
+
const lineStarts = sourceFile.getLineStarts();
|
|
188
|
+
for (let i = 0; i < lineStarts.length; i++) {
|
|
189
|
+
const lineStart = lineStarts[i] ?? 0;
|
|
190
|
+
const lineEnd = i + 1 < lineStarts.length ? (lineStarts[i + 1] ?? text.length) : text.length;
|
|
191
|
+
if (position < lineStart || position >= lineEnd)
|
|
192
|
+
continue;
|
|
193
|
+
if (isPositionInRanges(position, ts.getLeadingCommentRanges(text, lineStart)))
|
|
194
|
+
return true;
|
|
195
|
+
if (isPositionInRanges(position, ts.getTrailingCommentRanges(text, lineStart)))
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
// =============================================================================
|
|
201
|
+
// STRING UTILITIES
|
|
202
|
+
// =============================================================================
|
|
203
|
+
/**
|
|
204
|
+
* Count unescaped backtick characters in a line.
|
|
205
|
+
*/
|
|
206
|
+
export function countUnescapedBackticks(line) {
|
|
207
|
+
let count = 0;
|
|
208
|
+
for (let ci = 0; ci < line.length; ci++) {
|
|
209
|
+
if (line[ci] === '`' && (ci === 0 || line[ci - 1] !== '\\'))
|
|
210
|
+
count++;
|
|
211
|
+
}
|
|
212
|
+
return count;
|
|
213
|
+
}
|
|
214
|
+
/** Re-export TypeScript namespace for check authors */
|
|
215
|
+
// eslint-disable-next-line unicorn/prefer-export-from -- `export * as from 'typescript'` is invalid (typescript uses `export =`); the namespace import + named export form is the only working shape
|
|
216
|
+
export { ts };
|
|
217
|
+
//# sourceMappingURL=ast-utilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-utilities.js","sourceRoot":"","sources":["../src/ast-utilities.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { typescriptAdapter, adapters } from './adapter.js';
|
|
2
|
+
export { parseSource } from './parse.js';
|
|
3
|
+
export { typescriptQuery } from './query.js';
|
|
4
|
+
export { stripStrings, stripComments, filterContent, clearFilterCache } from './strip.js';
|
|
5
|
+
export type { FilteredContent } from './strip.js';
|
|
6
|
+
export { getSharedSourceFile, walkNodes, getIdentifierName, getPropertyChain, getLineNumber, getColumn, isPropertyAccess, isLiteral, isInStringLiteral, findCallExpressions, findBinaryExpressions, findTemplateLiterals, isInComment, countUnescapedBackticks, ts, } from './ast-utilities.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACzF,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAIjD,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,WAAW,EACX,uBAAuB,EACvB,EAAE,GACH,MAAM,oBAAoB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// TypeScript LanguageAdapter for opensip-tools
|
|
2
|
+
export { typescriptAdapter, adapters } from './adapter.js';
|
|
3
|
+
export { parseSource } from './parse.js';
|
|
4
|
+
export { typescriptQuery } from './query.js';
|
|
5
|
+
export { stripStrings, stripComments, filterContent, clearFilterCache } from './strip.js';
|
|
6
|
+
// Legacy AST helpers — re-exported so existing TS checks can keep their imports
|
|
7
|
+
// pointing at @opensip-tools/lang-typescript instead of @opensip-tools/core/framework/*
|
|
8
|
+
export { getSharedSourceFile, walkNodes, getIdentifierName, getPropertyChain, getLineNumber, getColumn, isPropertyAccess, isLiteral, isInStringLiteral, findCallExpressions, findBinaryExpressions, findTemplateLiterals, isInComment, countUnescapedBackticks, ts, } from './ast-utilities.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAGzF,gFAAgF;AAChF,wFAAwF;AACxF,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,WAAW,EACX,uBAAuB,EACvB,EAAE,GACH,MAAM,oBAAoB,CAAA"}
|
package/dist/parse.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Parse TypeScript/JavaScript source into a SourceFile.
|
|
4
|
+
* Returns null on parse failure.
|
|
5
|
+
*
|
|
6
|
+
* Uses ts.ScriptKind.TSX so the same parse path handles .ts and .tsx
|
|
7
|
+
* (and is permissive enough for .js / .jsx).
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseSource(content: string, filePath: string): ts.SourceFile | null;
|
|
10
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAE3B;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,EAAE,CAAC,UAAU,GAAG,IAAI,CAYnF"}
|
package/dist/parse.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Parse TypeScript/JavaScript source into a SourceFile.
|
|
4
|
+
* Returns null on parse failure.
|
|
5
|
+
*
|
|
6
|
+
* Uses ts.ScriptKind.TSX so the same parse path handles .ts and .tsx
|
|
7
|
+
* (and is permissive enough for .js / .jsx).
|
|
8
|
+
*/
|
|
9
|
+
export function parseSource(content, filePath) {
|
|
10
|
+
try {
|
|
11
|
+
return ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest,
|
|
12
|
+
/* setParentNodes */ true, ts.ScriptKind.TSX);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAE3B;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,QAAgB;IAC3D,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,gBAAgB,CACxB,QAAQ,EACR,OAAO,EACP,EAAE,CAAC,YAAY,CAAC,MAAM;QACtB,oBAAoB,CAAC,IAAI,EACzB,EAAE,CAAC,UAAU,CAAC,GAAG,CAClB,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
|
package/dist/query.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAE3B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAA;AAahF,eAAO,MAAM,eAAe,EAAE,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,CA4DpE,CAAA"}
|
package/dist/query.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
function locationOf(sourceFile, node) {
|
|
3
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
|
|
4
|
+
return { file: sourceFile.fileName, line: line + 1, column: character };
|
|
5
|
+
}
|
|
6
|
+
function walk(node, visit) {
|
|
7
|
+
visit(node);
|
|
8
|
+
ts.forEachChild(node, (child) => walk(child, visit));
|
|
9
|
+
}
|
|
10
|
+
export const typescriptQuery = {
|
|
11
|
+
findFunctions(tree) {
|
|
12
|
+
const out = [];
|
|
13
|
+
walk(tree, (n) => {
|
|
14
|
+
if (ts.isFunctionDeclaration(n) ||
|
|
15
|
+
ts.isFunctionExpression(n) ||
|
|
16
|
+
ts.isArrowFunction(n) ||
|
|
17
|
+
ts.isMethodDeclaration(n)) {
|
|
18
|
+
const name = n.name?.text ?? null;
|
|
19
|
+
out.push({ name, location: locationOf(tree, n), node: n });
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
return out;
|
|
23
|
+
},
|
|
24
|
+
findImports(tree) {
|
|
25
|
+
const out = [];
|
|
26
|
+
walk(tree, (n) => {
|
|
27
|
+
if (ts.isImportDeclaration(n) && ts.isStringLiteral(n.moduleSpecifier)) {
|
|
28
|
+
const specifier = n.moduleSpecifier.text;
|
|
29
|
+
const names = [];
|
|
30
|
+
const clause = n.importClause;
|
|
31
|
+
if (clause?.name)
|
|
32
|
+
names.push(clause.name.text);
|
|
33
|
+
if (clause?.namedBindings && ts.isNamedImports(clause.namedBindings)) {
|
|
34
|
+
for (const elem of clause.namedBindings.elements)
|
|
35
|
+
names.push(elem.name.text);
|
|
36
|
+
}
|
|
37
|
+
out.push({ specifier, names, location: locationOf(tree, n) });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return out;
|
|
41
|
+
},
|
|
42
|
+
findCallsTo(tree, name) {
|
|
43
|
+
const out = [];
|
|
44
|
+
walk(tree, (n) => {
|
|
45
|
+
if (ts.isCallExpression(n)) {
|
|
46
|
+
const expr = n.expression;
|
|
47
|
+
let target = '';
|
|
48
|
+
if (ts.isIdentifier(expr))
|
|
49
|
+
target = expr.text;
|
|
50
|
+
else if (ts.isPropertyAccessExpression(expr))
|
|
51
|
+
target = expr.name.text;
|
|
52
|
+
if (target === name)
|
|
53
|
+
out.push(n);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
return out;
|
|
57
|
+
},
|
|
58
|
+
findStringLiterals(tree) {
|
|
59
|
+
const out = [];
|
|
60
|
+
walk(tree, (n) => {
|
|
61
|
+
if (ts.isStringLiteralLike(n)) {
|
|
62
|
+
out.push({ value: n.text, location: locationOf(tree, n) });
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return out;
|
|
66
|
+
},
|
|
67
|
+
getLocation(tree, node) {
|
|
68
|
+
return locationOf(tree, node);
|
|
69
|
+
},
|
|
70
|
+
getText(tree, node) {
|
|
71
|
+
return node.getText(tree);
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
package/dist/strip.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TypeScript string and comment stripping.
|
|
3
|
+
*
|
|
4
|
+
* Implements the LanguageAdapter contract methods stripStrings/stripComments
|
|
5
|
+
* by re-using the rich filterContent implementation in core. Both functions
|
|
6
|
+
* preserve byte length so line/column positions remain stable.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Replace string literal content with whitespace of equal length.
|
|
10
|
+
* Quote/backtick delimiters are preserved; only the inside is blanked.
|
|
11
|
+
*/
|
|
12
|
+
export declare function stripStrings(content: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Replace string literals AND comments with whitespace of equal length.
|
|
15
|
+
*/
|
|
16
|
+
export declare function stripComments(content: string): string;
|
|
17
|
+
export { filterContent, clearFilterCache } from '@opensip-tools/fitness';
|
|
18
|
+
export type { FilteredContent } from '@opensip-tools/fitness';
|
|
19
|
+
//# sourceMappingURL=strip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strip.d.ts","sourceRoot":"","sources":["../src/strip.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAErD;AAKD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACxE,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA"}
|
package/dist/strip.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TypeScript string and comment stripping.
|
|
3
|
+
*
|
|
4
|
+
* Implements the LanguageAdapter contract methods stripStrings/stripComments
|
|
5
|
+
* by re-using the rich filterContent implementation in core. Both functions
|
|
6
|
+
* preserve byte length so line/column positions remain stable.
|
|
7
|
+
*/
|
|
8
|
+
import { filterContent } from '@opensip-tools/fitness';
|
|
9
|
+
/**
|
|
10
|
+
* Replace string literal content with whitespace of equal length.
|
|
11
|
+
* Quote/backtick delimiters are preserved; only the inside is blanked.
|
|
12
|
+
*/
|
|
13
|
+
export function stripStrings(content) {
|
|
14
|
+
return filterContent(content).code;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Replace string literals AND comments with whitespace of equal length.
|
|
18
|
+
*/
|
|
19
|
+
export function stripComments(content) {
|
|
20
|
+
return filterContent(content).codeNoComments;
|
|
21
|
+
}
|
|
22
|
+
// Re-export filterContent and the FilteredContent type for richer
|
|
23
|
+
// position-aware needs. The clearFilterCache helper is also re-exported
|
|
24
|
+
// for compatibility with any callers that managed it directly.
|
|
25
|
+
export { filterContent, clearFilterCache } from '@opensip-tools/fitness';
|
|
26
|
+
//# sourceMappingURL=strip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strip.js","sourceRoot":"","sources":["../src/strip.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAEtD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC,IAAI,CAAA;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC,cAAc,CAAA;AAC9C,CAAC;AAED,kEAAkE;AAClE,wEAAwE;AACxE,+DAA+D;AAC/D,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@opensip-tools/lang-typescript",
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "TypeScript/JavaScript language adapter for opensip-tools",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/opensip-ai/opensip-tools.git",
|
|
9
|
+
"directory": "packages/languages/lang-typescript"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/opensip-ai/opensip-tools",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/opensip-ai/opensip-tools/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": "./dist/index.js",
|
|
20
|
+
"./adapter": "./dist/adapter.js",
|
|
21
|
+
"./parse": "./dist/parse.js",
|
|
22
|
+
"./query": "./dist/query.js",
|
|
23
|
+
"./strip": "./dist/strip.js",
|
|
24
|
+
"./ast-utilities": "./dist/ast-utilities.js"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"typescript": "~5.7.0",
|
|
28
|
+
"@opensip-tools/core": "1.0.4",
|
|
29
|
+
"@opensip-tools/fitness": "1.0.4"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^22.0.0",
|
|
33
|
+
"vitest": "^2.1.0"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc",
|
|
37
|
+
"test": "vitest run --passWithNoTests",
|
|
38
|
+
"typecheck": "tsc --noEmit",
|
|
39
|
+
"clean": "rm -rf dist"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { typescriptAdapter } from '../adapter.js'
|
|
4
|
+
|
|
5
|
+
describe('typescriptAdapter', () => {
|
|
6
|
+
it('declares the expected identity and extensions', () => {
|
|
7
|
+
expect(typescriptAdapter.id).toBe('typescript')
|
|
8
|
+
expect(typescriptAdapter.fileExtensions).toContain('.ts')
|
|
9
|
+
expect(typescriptAdapter.fileExtensions).toContain('.tsx')
|
|
10
|
+
expect(typescriptAdapter.fileExtensions).toContain('.js')
|
|
11
|
+
expect(typescriptAdapter.fileExtensions).toContain('.jsx')
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
it('parse() returns a non-null SourceFile for valid input', () => {
|
|
15
|
+
const tree = typescriptAdapter.parse('const x = 1;', 'foo.ts')
|
|
16
|
+
expect(tree).not.toBeNull()
|
|
17
|
+
expect(tree?.fileName).toBe('foo.ts')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('parse() handles broken input by returning a SourceFile (TS is forgiving)', () => {
|
|
21
|
+
const tree = typescriptAdapter.parse('let x =;', 'broken.ts')
|
|
22
|
+
expect(tree).not.toBeNull()
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('query.findFunctions returns named and anonymous functions', () => {
|
|
26
|
+
const tree = typescriptAdapter.parse('function a(){} const b = () => {}', 'foo.ts')!
|
|
27
|
+
const fns = typescriptAdapter.query!.findFunctions(tree)
|
|
28
|
+
expect(fns.length).toBe(2)
|
|
29
|
+
const names = fns.map((f) => f.name).sort()
|
|
30
|
+
expect(names).toEqual([null, 'a'].sort())
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('query.findImports returns named imports and specifier', () => {
|
|
34
|
+
const tree = typescriptAdapter.parse(
|
|
35
|
+
"import { x, y } from './foo'",
|
|
36
|
+
'foo.ts',
|
|
37
|
+
)!
|
|
38
|
+
const imports = typescriptAdapter.query!.findImports(tree)
|
|
39
|
+
expect(imports.length).toBe(1)
|
|
40
|
+
expect(imports[0].specifier).toBe('./foo')
|
|
41
|
+
expect([...imports[0].names].sort()).toEqual(['x', 'y'])
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('query.findCallsTo matches the leaf call name', () => {
|
|
45
|
+
const tree = typescriptAdapter.parse('foo(); bar.baz();', 'foo.ts')!
|
|
46
|
+
expect(typescriptAdapter.query!.findCallsTo(tree, 'foo').length).toBe(1)
|
|
47
|
+
expect(typescriptAdapter.query!.findCallsTo(tree, 'baz').length).toBe(1)
|
|
48
|
+
expect(typescriptAdapter.query!.findCallsTo(tree, 'absent').length).toBe(0)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('stripStrings replaces string content but preserves length', () => {
|
|
52
|
+
const original = 'const x = "abc"; const y = 1'
|
|
53
|
+
const stripped = typescriptAdapter.stripStrings(original)
|
|
54
|
+
expect(stripped.length).toBe(original.length)
|
|
55
|
+
expect(stripped).not.toContain('abc')
|
|
56
|
+
expect(stripped).toContain('const x =')
|
|
57
|
+
expect(stripped).toContain('const y = 1')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('stripComments replaces comment content', () => {
|
|
61
|
+
const original = '// hello\nconst x = 1'
|
|
62
|
+
const stripped = typescriptAdapter.stripComments(original)
|
|
63
|
+
expect(stripped.length).toBe(original.length)
|
|
64
|
+
expect(stripped).not.toContain('hello')
|
|
65
|
+
expect(stripped).toContain('const x = 1')
|
|
66
|
+
})
|
|
67
|
+
})
|