@apifuse/provider-sdk 2.2.0-beta.50 → 2.2.0-beta.51
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/CHANGELOG.md +4 -0
- package/dist/cli/migrate-operation-declaration.js +81 -10
- package/package.json +1 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-hoisted-array-spread.ts.txt +15 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-imported-array-spread.ts.txt +9 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-mixed-array-spread.ts.txt +24 -0
- package/src/cli/migrate-operation-declaration.ts +103 -6
package/CHANGELOG.md
CHANGED
|
@@ -62,6 +62,7 @@ export function migrateOperationDeclaration(sourceText, fileName, options = {})
|
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
64
|
const constObjects = collectModuleConstObjects(source);
|
|
65
|
+
const constArrays = collectModuleConstArrays(source);
|
|
65
66
|
const discovery = discoverOperationSites(source, fileName, constObjects, options.operationIds);
|
|
66
67
|
if (discovery.refusals.length > 0) {
|
|
67
68
|
return { status: "refused", refusals: discovery.refusals };
|
|
@@ -70,7 +71,7 @@ export function migrateOperationDeclaration(sourceText, fileName, options = {})
|
|
|
70
71
|
const todos = [];
|
|
71
72
|
const refusals = [];
|
|
72
73
|
for (const site of discovery.sites) {
|
|
73
|
-
const plan = planOperationMigration(source, fileName, site, constObjects, options.localeFiles ?? []);
|
|
74
|
+
const plan = planOperationMigration(source, fileName, site, constObjects, constArrays, options.localeFiles ?? []);
|
|
74
75
|
if ("refusal" in plan) {
|
|
75
76
|
refusals.push(plan.refusal);
|
|
76
77
|
continue;
|
|
@@ -87,7 +88,11 @@ export function migrateOperationDeclaration(sourceText, fileName, options = {})
|
|
|
87
88
|
operations: discovery.sites.length,
|
|
88
89
|
};
|
|
89
90
|
}
|
|
90
|
-
const
|
|
91
|
+
const normalizedEdits = normalizeEdits(edits, fileName);
|
|
92
|
+
if ("refusal" in normalizedEdits) {
|
|
93
|
+
return { status: "refused", refusals: [normalizedEdits.refusal] };
|
|
94
|
+
}
|
|
95
|
+
const code = applyEdits(sourceText, normalizedEdits.edits);
|
|
91
96
|
const outputRefusal = verifyOperationDeclarationRewrite(code, fileName);
|
|
92
97
|
if (outputRefusal !== undefined) {
|
|
93
98
|
return {
|
|
@@ -109,7 +114,7 @@ export function verifyOperationDeclarationRewrite(code, fileName) {
|
|
|
109
114
|
return undefined;
|
|
110
115
|
return refusal(fileName, "<file>", "codemod_syntax", `Transform output did not parse: ${outputError}`);
|
|
111
116
|
}
|
|
112
|
-
function planOperationMigration(source, fileName, site, constObjects, localeFiles) {
|
|
117
|
+
function planOperationMigration(source, fileName, site, constObjects, constArrays, localeFiles) {
|
|
113
118
|
if (site.object.properties.some(ts.isSpreadAssignment)) {
|
|
114
119
|
return {
|
|
115
120
|
refusal: refusal(fileName, site.operationKey, "non_literal", "Top-level operation spreads cannot be rewritten without changing their shared declaration."),
|
|
@@ -216,7 +221,7 @@ function planOperationMigration(source, fileName, site, constObjects, localeFile
|
|
|
216
221
|
if (merged.insert !== undefined)
|
|
217
222
|
addInsertion(insertions, "docs", merged.insert);
|
|
218
223
|
}
|
|
219
|
-
const examples = planExamples(top.byName.get("inputExamples"), top.byName.get("examples"), fileName, site, source, localeFiles);
|
|
224
|
+
const examples = planExamples(top.byName.get("inputExamples"), top.byName.get("examples"), fileName, site, source, constArrays, localeFiles);
|
|
220
225
|
if ("refusal" in examples)
|
|
221
226
|
return examples;
|
|
222
227
|
const edits = [...examples.edits];
|
|
@@ -376,7 +381,7 @@ function mergeFlatAndNested(field, flat, nested, fileName, operationKey, source,
|
|
|
376
381
|
}
|
|
377
382
|
return {};
|
|
378
383
|
}
|
|
379
|
-
function planExamples(inputExamples, existingExamples, fileName, site, source, localeFiles) {
|
|
384
|
+
function planExamples(inputExamples, existingExamples, fileName, site, source, constArrays, localeFiles) {
|
|
380
385
|
if (inputExamples === undefined)
|
|
381
386
|
return { edits: [], localeTodos: [] };
|
|
382
387
|
if (existingExamples !== undefined) {
|
|
@@ -388,12 +393,15 @@ function planExamples(inputExamples, existingExamples, fileName, site, source, l
|
|
|
388
393
|
if (array === undefined || !ts.isArrayLiteralExpression(array)) {
|
|
389
394
|
return nonLiteral(fileName, site.operationKey, "inputExamples must be an array literal.");
|
|
390
395
|
}
|
|
391
|
-
|
|
396
|
+
const expanded = expandArrayElements(array, constArrays, fileName, site.operationKey);
|
|
397
|
+
if ("refusal" in expanded)
|
|
398
|
+
return expanded;
|
|
399
|
+
if (expanded.elements.length > 0 && !site.operationIdProven) {
|
|
392
400
|
return {
|
|
393
401
|
refusal: refusal(fileName, site.operationKey, "operation_id_unresolved", "inputExamples requires an exact operation id proven from a static operations map."),
|
|
394
402
|
};
|
|
395
403
|
}
|
|
396
|
-
if (
|
|
404
|
+
if (expanded.elements.length > 0 && !localeFiles.includes("locales/en.json")) {
|
|
397
405
|
return {
|
|
398
406
|
refusal: refusal(fileName, site.operationKey, "missing_english_locale", "inputExamples cannot be migrated because locales/en.json does not exist."),
|
|
399
407
|
};
|
|
@@ -409,8 +417,8 @@ function planExamples(inputExamples, existingExamples, fileName, site, source, l
|
|
|
409
417
|
end: propertyNameNode.getEnd(),
|
|
410
418
|
text: "examples",
|
|
411
419
|
});
|
|
412
|
-
for (let index = 0; index <
|
|
413
|
-
const element =
|
|
420
|
+
for (let index = 0; index < expanded.elements.length; index += 1) {
|
|
421
|
+
const element = expanded.elements[index];
|
|
414
422
|
const object = element === undefined ? undefined : unwrapExpression(element);
|
|
415
423
|
if (object === undefined || !ts.isObjectLiteralExpression(object)) {
|
|
416
424
|
return nonLiteral(fileName, site.operationKey, `inputExamples[${index}] must be an object literal.`);
|
|
@@ -696,6 +704,51 @@ function collectModuleConstObjects(source) {
|
|
|
696
704
|
}
|
|
697
705
|
return objects;
|
|
698
706
|
}
|
|
707
|
+
function collectModuleConstArrays(source) {
|
|
708
|
+
const arrays = new Map();
|
|
709
|
+
for (const statement of source.statements) {
|
|
710
|
+
if (!ts.isVariableStatement(statement))
|
|
711
|
+
continue;
|
|
712
|
+
if ((statement.declarationList.flags & ts.NodeFlags.Const) === 0)
|
|
713
|
+
continue;
|
|
714
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
715
|
+
if (!ts.isIdentifier(declaration.name) || declaration.initializer === undefined)
|
|
716
|
+
continue;
|
|
717
|
+
const expression = unwrapExpression(declaration.initializer);
|
|
718
|
+
if (expression !== undefined && ts.isArrayLiteralExpression(expression)) {
|
|
719
|
+
arrays.set(declaration.name.text, expression);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
return arrays;
|
|
724
|
+
}
|
|
725
|
+
function expandArrayElements(array, constArrays, fileName, operationKey, seen = new Set()) {
|
|
726
|
+
if (seen.has(array)) {
|
|
727
|
+
return nonLiteral(fileName, operationKey, "A module-level array spread is recursive.");
|
|
728
|
+
}
|
|
729
|
+
seen.add(array);
|
|
730
|
+
const elements = [];
|
|
731
|
+
for (const element of array.elements) {
|
|
732
|
+
if (!ts.isSpreadElement(element)) {
|
|
733
|
+
elements.push(element);
|
|
734
|
+
continue;
|
|
735
|
+
}
|
|
736
|
+
const expression = unwrapExpression(element.expression);
|
|
737
|
+
const spreadArray = expression !== undefined && ts.isArrayLiteralExpression(expression)
|
|
738
|
+
? expression
|
|
739
|
+
: expression !== undefined && ts.isIdentifier(expression)
|
|
740
|
+
? constArrays.get(expression.text)
|
|
741
|
+
: undefined;
|
|
742
|
+
if (spreadArray === undefined) {
|
|
743
|
+
return nonLiteral(fileName, operationKey, "inputExamples contains an unresolved array spread.");
|
|
744
|
+
}
|
|
745
|
+
const expanded = expandArrayElements(spreadArray, constArrays, fileName, operationKey, new Set(seen));
|
|
746
|
+
if ("refusal" in expanded)
|
|
747
|
+
return expanded;
|
|
748
|
+
elements.push(...expanded.elements);
|
|
749
|
+
}
|
|
750
|
+
return { elements };
|
|
751
|
+
}
|
|
699
752
|
function expandMembers(object, constObjects, fileName, operationKey, seen = new Set()) {
|
|
700
753
|
if (seen.has(object)) {
|
|
701
754
|
return nonLiteral(fileName, operationKey, "A module-level object spread is recursive.");
|
|
@@ -929,6 +982,21 @@ function applyEdits(sourceText, edits) {
|
|
|
929
982
|
}
|
|
930
983
|
return code;
|
|
931
984
|
}
|
|
985
|
+
function normalizeEdits(edits, fileName) {
|
|
986
|
+
const unique = new Map();
|
|
987
|
+
for (const edit of edits) {
|
|
988
|
+
const key = `${edit.start}:${edit.end}`;
|
|
989
|
+
const previous = unique.get(key);
|
|
990
|
+
if (previous === undefined) {
|
|
991
|
+
unique.set(key, edit);
|
|
992
|
+
continue;
|
|
993
|
+
}
|
|
994
|
+
if (previous.text !== edit.text) {
|
|
995
|
+
return nonLiteral(fileName, "<shared>", "A module-level input examples array is shared by operations that need different locale keys.");
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
return { edits: [...unique.values()] };
|
|
999
|
+
}
|
|
932
1000
|
function indentationAt(text, position) {
|
|
933
1001
|
const lineStart = text.lastIndexOf("\n", position - 1) + 1;
|
|
934
1002
|
return text.slice(lineStart, position).match(/^\s*/)?.[0] ?? "";
|
|
@@ -1075,7 +1143,10 @@ function collectSourceFiles(root) {
|
|
|
1075
1143
|
if (entry.isDirectory()) {
|
|
1076
1144
|
if (SOURCE_SKIP_DIRECTORIES.has(entry.name))
|
|
1077
1145
|
continue;
|
|
1078
|
-
|
|
1146
|
+
const child = join(directory, entry.name);
|
|
1147
|
+
if (existsSync(join(child, ".git")))
|
|
1148
|
+
continue;
|
|
1149
|
+
walk(child);
|
|
1079
1150
|
continue;
|
|
1080
1151
|
}
|
|
1081
1152
|
if (!entry.name.endsWith(".ts"))
|
package/package.json
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const LIST_INPUT_EXAMPLES = [
|
|
2
|
+
{
|
|
3
|
+
scenario: "List a full year",
|
|
4
|
+
rationale: "Shows the common calendar query",
|
|
5
|
+
input: { year: 2026 },
|
|
6
|
+
},
|
|
7
|
+
] as const;
|
|
8
|
+
|
|
9
|
+
const listOperation = defineOperation<ProviderContext>()({
|
|
10
|
+
annotations: { readOnly: true },
|
|
11
|
+
inputExamples: [...LIST_INPUT_EXAMPLES],
|
|
12
|
+
input: InputSchema,
|
|
13
|
+
output: OutputSchema,
|
|
14
|
+
handler,
|
|
15
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { LIST_INPUT_EXAMPLES } from "./shared.js";
|
|
2
|
+
|
|
3
|
+
const importedExamplesOperation = defineOperation<ProviderContext>()({
|
|
4
|
+
annotations: { readOnly: true },
|
|
5
|
+
inputExamples: [...LIST_INPUT_EXAMPLES],
|
|
6
|
+
input: InputSchema,
|
|
7
|
+
output: OutputSchema,
|
|
8
|
+
handler,
|
|
9
|
+
});
|
package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-mixed-array-spread.ts.txt
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const SHARED_INPUT_EXAMPLES = [
|
|
2
|
+
{
|
|
3
|
+
scenario: "Shared middle example",
|
|
4
|
+
input: { page: 2 },
|
|
5
|
+
},
|
|
6
|
+
] as const;
|
|
7
|
+
|
|
8
|
+
const mixedOperation = defineOperation<ProviderContext>()({
|
|
9
|
+
annotations: { readOnly: true },
|
|
10
|
+
inputExamples: [
|
|
11
|
+
{
|
|
12
|
+
scenario: "Literal first example",
|
|
13
|
+
input: { page: 1 },
|
|
14
|
+
},
|
|
15
|
+
...SHARED_INPUT_EXAMPLES,
|
|
16
|
+
{
|
|
17
|
+
scenario: "Literal last example",
|
|
18
|
+
input: { page: 3 },
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
input: InputSchema,
|
|
22
|
+
output: OutputSchema,
|
|
23
|
+
handler,
|
|
24
|
+
});
|
|
@@ -154,6 +154,7 @@ export function migrateOperationDeclaration(
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
const constObjects = collectModuleConstObjects(source);
|
|
157
|
+
const constArrays = collectModuleConstArrays(source);
|
|
157
158
|
const discovery = discoverOperationSites(source, fileName, constObjects, options.operationIds);
|
|
158
159
|
if (discovery.refusals.length > 0) {
|
|
159
160
|
return { status: "refused", refusals: discovery.refusals };
|
|
@@ -168,6 +169,7 @@ export function migrateOperationDeclaration(
|
|
|
168
169
|
fileName,
|
|
169
170
|
site,
|
|
170
171
|
constObjects,
|
|
172
|
+
constArrays,
|
|
171
173
|
options.localeFiles ?? [],
|
|
172
174
|
);
|
|
173
175
|
if ("refusal" in plan) {
|
|
@@ -187,7 +189,12 @@ export function migrateOperationDeclaration(
|
|
|
187
189
|
};
|
|
188
190
|
}
|
|
189
191
|
|
|
190
|
-
const
|
|
192
|
+
const normalizedEdits = normalizeEdits(edits, fileName);
|
|
193
|
+
if ("refusal" in normalizedEdits) {
|
|
194
|
+
return { status: "refused", refusals: [normalizedEdits.refusal] };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const code = applyEdits(sourceText, normalizedEdits.edits);
|
|
191
198
|
const outputRefusal = verifyOperationDeclarationRewrite(code, fileName);
|
|
192
199
|
if (outputRefusal !== undefined) {
|
|
193
200
|
return {
|
|
@@ -224,6 +231,7 @@ function planOperationMigration(
|
|
|
224
231
|
fileName: string,
|
|
225
232
|
site: OperationSite,
|
|
226
233
|
constObjects: ReadonlyMap<string, TS.ObjectLiteralExpression>,
|
|
234
|
+
constArrays: ReadonlyMap<string, TS.ArrayLiteralExpression>,
|
|
227
235
|
localeFiles: readonly string[],
|
|
228
236
|
): PlannedOperation | { readonly refusal: OperationDeclarationRefusal } {
|
|
229
237
|
if (site.object.properties.some(ts.isSpreadAssignment)) {
|
|
@@ -398,6 +406,7 @@ function planOperationMigration(
|
|
|
398
406
|
fileName,
|
|
399
407
|
site,
|
|
400
408
|
source,
|
|
409
|
+
constArrays,
|
|
401
410
|
localeFiles,
|
|
402
411
|
);
|
|
403
412
|
if ("refusal" in examples) return examples;
|
|
@@ -653,6 +662,7 @@ function planExamples(
|
|
|
653
662
|
fileName: string,
|
|
654
663
|
site: OperationSite,
|
|
655
664
|
source: TS.SourceFile,
|
|
665
|
+
constArrays: ReadonlyMap<string, TS.ArrayLiteralExpression>,
|
|
656
666
|
localeFiles: readonly string[],
|
|
657
667
|
):
|
|
658
668
|
| { readonly edits: readonly TextEdit[]; readonly localeTodos: readonly LocaleTodo[] }
|
|
@@ -672,7 +682,9 @@ function planExamples(
|
|
|
672
682
|
if (array === undefined || !ts.isArrayLiteralExpression(array)) {
|
|
673
683
|
return nonLiteral(fileName, site.operationKey, "inputExamples must be an array literal.");
|
|
674
684
|
}
|
|
675
|
-
|
|
685
|
+
const expanded = expandArrayElements(array, constArrays, fileName, site.operationKey);
|
|
686
|
+
if ("refusal" in expanded) return expanded;
|
|
687
|
+
if (expanded.elements.length > 0 && !site.operationIdProven) {
|
|
676
688
|
return {
|
|
677
689
|
refusal: refusal(
|
|
678
690
|
fileName,
|
|
@@ -682,7 +694,7 @@ function planExamples(
|
|
|
682
694
|
),
|
|
683
695
|
};
|
|
684
696
|
}
|
|
685
|
-
if (
|
|
697
|
+
if (expanded.elements.length > 0 && !localeFiles.includes("locales/en.json")) {
|
|
686
698
|
return {
|
|
687
699
|
refusal: refusal(
|
|
688
700
|
fileName,
|
|
@@ -709,8 +721,8 @@ function planExamples(
|
|
|
709
721
|
text: "examples",
|
|
710
722
|
});
|
|
711
723
|
|
|
712
|
-
for (let index = 0; index <
|
|
713
|
-
const element =
|
|
724
|
+
for (let index = 0; index < expanded.elements.length; index += 1) {
|
|
725
|
+
const element = expanded.elements[index];
|
|
714
726
|
const object = element === undefined ? undefined : unwrapExpression(element);
|
|
715
727
|
if (object === undefined || !ts.isObjectLiteralExpression(object)) {
|
|
716
728
|
return nonLiteral(
|
|
@@ -1070,6 +1082,66 @@ function collectModuleConstObjects(source: TS.SourceFile): Map<string, TS.Object
|
|
|
1070
1082
|
return objects;
|
|
1071
1083
|
}
|
|
1072
1084
|
|
|
1085
|
+
function collectModuleConstArrays(source: TS.SourceFile): Map<string, TS.ArrayLiteralExpression> {
|
|
1086
|
+
const arrays = new Map<string, TS.ArrayLiteralExpression>();
|
|
1087
|
+
for (const statement of source.statements) {
|
|
1088
|
+
if (!ts.isVariableStatement(statement)) continue;
|
|
1089
|
+
if ((statement.declarationList.flags & ts.NodeFlags.Const) === 0) continue;
|
|
1090
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
1091
|
+
if (!ts.isIdentifier(declaration.name) || declaration.initializer === undefined) continue;
|
|
1092
|
+
const expression = unwrapExpression(declaration.initializer);
|
|
1093
|
+
if (expression !== undefined && ts.isArrayLiteralExpression(expression)) {
|
|
1094
|
+
arrays.set(declaration.name.text, expression);
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
return arrays;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
function expandArrayElements(
|
|
1102
|
+
array: TS.ArrayLiteralExpression,
|
|
1103
|
+
constArrays: ReadonlyMap<string, TS.ArrayLiteralExpression>,
|
|
1104
|
+
fileName: string,
|
|
1105
|
+
operationKey: string,
|
|
1106
|
+
seen = new Set<TS.ArrayLiteralExpression>(),
|
|
1107
|
+
): { readonly elements: TS.Expression[] } | { readonly refusal: OperationDeclarationRefusal } {
|
|
1108
|
+
if (seen.has(array)) {
|
|
1109
|
+
return nonLiteral(fileName, operationKey, "A module-level array spread is recursive.");
|
|
1110
|
+
}
|
|
1111
|
+
seen.add(array);
|
|
1112
|
+
const elements: TS.Expression[] = [];
|
|
1113
|
+
for (const element of array.elements) {
|
|
1114
|
+
if (!ts.isSpreadElement(element)) {
|
|
1115
|
+
elements.push(element);
|
|
1116
|
+
continue;
|
|
1117
|
+
}
|
|
1118
|
+
const expression = unwrapExpression(element.expression);
|
|
1119
|
+
const spreadArray =
|
|
1120
|
+
expression !== undefined && ts.isArrayLiteralExpression(expression)
|
|
1121
|
+
? expression
|
|
1122
|
+
: expression !== undefined && ts.isIdentifier(expression)
|
|
1123
|
+
? constArrays.get(expression.text)
|
|
1124
|
+
: undefined;
|
|
1125
|
+
if (spreadArray === undefined) {
|
|
1126
|
+
return nonLiteral(
|
|
1127
|
+
fileName,
|
|
1128
|
+
operationKey,
|
|
1129
|
+
"inputExamples contains an unresolved array spread.",
|
|
1130
|
+
);
|
|
1131
|
+
}
|
|
1132
|
+
const expanded = expandArrayElements(
|
|
1133
|
+
spreadArray,
|
|
1134
|
+
constArrays,
|
|
1135
|
+
fileName,
|
|
1136
|
+
operationKey,
|
|
1137
|
+
new Set(seen),
|
|
1138
|
+
);
|
|
1139
|
+
if ("refusal" in expanded) return expanded;
|
|
1140
|
+
elements.push(...expanded.elements);
|
|
1141
|
+
}
|
|
1142
|
+
return { elements };
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1073
1145
|
function expandMembers(
|
|
1074
1146
|
object: TS.ObjectLiteralExpression,
|
|
1075
1147
|
constObjects: ReadonlyMap<string, TS.ObjectLiteralExpression>,
|
|
@@ -1357,6 +1429,29 @@ function applyEdits(sourceText: string, edits: readonly TextEdit[]): string {
|
|
|
1357
1429
|
return code;
|
|
1358
1430
|
}
|
|
1359
1431
|
|
|
1432
|
+
function normalizeEdits(
|
|
1433
|
+
edits: readonly TextEdit[],
|
|
1434
|
+
fileName: string,
|
|
1435
|
+
): { readonly edits: readonly TextEdit[] } | { readonly refusal: OperationDeclarationRefusal } {
|
|
1436
|
+
const unique = new Map<string, TextEdit>();
|
|
1437
|
+
for (const edit of edits) {
|
|
1438
|
+
const key = `${edit.start}:${edit.end}`;
|
|
1439
|
+
const previous = unique.get(key);
|
|
1440
|
+
if (previous === undefined) {
|
|
1441
|
+
unique.set(key, edit);
|
|
1442
|
+
continue;
|
|
1443
|
+
}
|
|
1444
|
+
if (previous.text !== edit.text) {
|
|
1445
|
+
return nonLiteral(
|
|
1446
|
+
fileName,
|
|
1447
|
+
"<shared>",
|
|
1448
|
+
"A module-level input examples array is shared by operations that need different locale keys.",
|
|
1449
|
+
);
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
return { edits: [...unique.values()] };
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1360
1455
|
function indentationAt(text: string, position: number): string {
|
|
1361
1456
|
const lineStart = text.lastIndexOf("\n", position - 1) + 1;
|
|
1362
1457
|
return text.slice(lineStart, position).match(/^\s*/)?.[0] ?? "";
|
|
@@ -1548,7 +1643,9 @@ function collectSourceFiles(root: string): string[] {
|
|
|
1548
1643
|
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
1549
1644
|
if (entry.isDirectory()) {
|
|
1550
1645
|
if (SOURCE_SKIP_DIRECTORIES.has(entry.name)) continue;
|
|
1551
|
-
|
|
1646
|
+
const child = join(directory, entry.name);
|
|
1647
|
+
if (existsSync(join(child, ".git"))) continue;
|
|
1648
|
+
walk(child);
|
|
1552
1649
|
continue;
|
|
1553
1650
|
}
|
|
1554
1651
|
if (!entry.name.endsWith(".ts")) continue;
|