@openrewrite/rewrite 8.91.2 → 8.91.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/dist/execution.d.ts +8 -0
- package/dist/execution.d.ts.map +1 -1
- package/dist/execution.js +31 -0
- package/dist/execution.js.map +1 -1
- package/dist/javascript/add-import.d.ts +64 -9
- package/dist/javascript/add-import.d.ts.map +1 -1
- package/dist/javascript/add-import.js +398 -71
- package/dist/javascript/add-import.js.map +1 -1
- package/dist/javascript/amd.d.ts +11 -1
- package/dist/javascript/amd.d.ts.map +1 -1
- package/dist/javascript/amd.js +43 -9
- package/dist/javascript/amd.js.map +1 -1
- package/dist/javascript/binding.d.ts +10 -2
- package/dist/javascript/binding.d.ts.map +1 -1
- package/dist/javascript/binding.js +44 -71
- package/dist/javascript/binding.js.map +1 -1
- package/dist/javascript/comparator.d.ts +2 -0
- package/dist/javascript/comparator.d.ts.map +1 -1
- package/dist/javascript/comparator.js +5 -1
- package/dist/javascript/comparator.js.map +1 -1
- package/dist/javascript/format/format.d.ts +5 -2
- package/dist/javascript/format/format.d.ts.map +1 -1
- package/dist/javascript/format/format.js +51 -11
- package/dist/javascript/format/format.js.map +1 -1
- package/dist/javascript/format/minimum-viable-spacing-visitor.d.ts +19 -0
- package/dist/javascript/format/minimum-viable-spacing-visitor.d.ts.map +1 -1
- package/dist/javascript/format/minimum-viable-spacing-visitor.js +180 -7
- package/dist/javascript/format/minimum-viable-spacing-visitor.js.map +1 -1
- package/dist/javascript/format/prettier-format.d.ts +2 -1
- package/dist/javascript/format/prettier-format.d.ts.map +1 -1
- package/dist/javascript/format/prettier-format.js +33 -23
- package/dist/javascript/format/prettier-format.js.map +1 -1
- package/dist/javascript/index.d.ts +3 -3
- package/dist/javascript/index.d.ts.map +1 -1
- package/dist/javascript/index.js +21 -1
- package/dist/javascript/index.js.map +1 -1
- package/dist/javascript/parser-utils.d.ts.map +1 -1
- package/dist/javascript/parser-utils.js +5 -9
- package/dist/javascript/parser-utils.js.map +1 -1
- package/dist/javascript/parser.d.ts +3 -2
- package/dist/javascript/parser.d.ts.map +1 -1
- package/dist/javascript/parser.js +202 -117
- package/dist/javascript/parser.js.map +1 -1
- package/dist/javascript/print.d.ts +1 -0
- package/dist/javascript/print.d.ts.map +1 -1
- package/dist/javascript/print.js +9 -0
- package/dist/javascript/print.js.map +1 -1
- package/dist/javascript/recipes/change-import.d.ts +6 -3
- package/dist/javascript/recipes/change-import.d.ts.map +1 -1
- package/dist/javascript/recipes/change-import.js +17 -277
- package/dist/javascript/recipes/change-import.js.map +1 -1
- package/dist/javascript/rpc.js +2 -0
- package/dist/javascript/rpc.js.map +1 -1
- package/dist/javascript/scope.d.ts +40 -7
- package/dist/javascript/scope.d.ts.map +1 -1
- package/dist/javascript/scope.js +182 -30
- package/dist/javascript/scope.js.map +1 -1
- package/dist/javascript/templating/bindings.js +2 -20
- package/dist/javascript/templating/bindings.js.map +1 -1
- package/dist/javascript/templating/comparator.d.ts +2 -0
- package/dist/javascript/templating/comparator.d.ts.map +1 -1
- package/dist/javascript/templating/comparator.js +25 -0
- package/dist/javascript/templating/comparator.js.map +1 -1
- package/dist/javascript/templating/engine.d.ts +5 -0
- package/dist/javascript/templating/engine.d.ts.map +1 -1
- package/dist/javascript/templating/engine.js +30 -12
- package/dist/javascript/templating/engine.js.map +1 -1
- package/dist/javascript/templating/template.d.ts.map +1 -1
- package/dist/javascript/templating/template.js +6 -0
- package/dist/javascript/templating/template.js.map +1 -1
- package/dist/javascript/templating/types.d.ts +5 -0
- package/dist/javascript/templating/types.d.ts.map +1 -1
- package/dist/javascript/tree.d.ts +1 -0
- package/dist/javascript/tree.d.ts.map +1 -1
- package/dist/javascript/tree.js.map +1 -1
- package/dist/javascript/tsconfig.d.ts +32 -0
- package/dist/javascript/tsconfig.d.ts.map +1 -0
- package/dist/javascript/tsconfig.js +205 -0
- package/dist/javascript/tsconfig.js.map +1 -0
- package/dist/javascript/type-mapping.d.ts.map +1 -1
- package/dist/javascript/type-mapping.js +14 -0
- package/dist/javascript/type-mapping.js.map +1 -1
- package/dist/javascript/visitor.d.ts.map +1 -1
- package/dist/javascript/visitor.js +1 -0
- package/dist/javascript/visitor.js.map +1 -1
- package/dist/parser.d.ts +6 -0
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +23 -1
- package/dist/parser.js.map +1 -1
- package/dist/print.d.ts.map +1 -1
- package/dist/print.js +5 -2
- package/dist/print.js.map +1 -1
- package/dist/rewrite-javascript-version.txt +1 -1
- package/dist/rpc/request/parse-project.d.ts +11 -1
- package/dist/rpc/request/parse-project.d.ts.map +1 -1
- package/dist/rpc/request/parse-project.js +7 -2
- package/dist/rpc/request/parse-project.js.map +1 -1
- package/dist/rpc/request/parse.d.ts +13 -1
- package/dist/rpc/request/parse.d.ts.map +1 -1
- package/dist/rpc/request/parse.js +8 -2
- package/dist/rpc/request/parse.js.map +1 -1
- package/package.json +1 -1
- package/src/execution.ts +23 -0
- package/src/javascript/add-import.ts +449 -78
- package/src/javascript/amd.ts +49 -10
- package/src/javascript/binding.ts +60 -74
- package/src/javascript/comparator.ts +6 -1
- package/src/javascript/format/format.ts +56 -12
- package/src/javascript/format/minimum-viable-spacing-visitor.ts +196 -7
- package/src/javascript/format/prettier-format.ts +35 -25
- package/src/javascript/index.ts +10 -3
- package/src/javascript/parser-utils.ts +5 -11
- package/src/javascript/parser.ts +167 -62
- package/src/javascript/print.ts +10 -0
- package/src/javascript/recipes/change-import.ts +19 -349
- package/src/javascript/rpc.ts +2 -0
- package/src/javascript/scope.ts +210 -31
- package/src/javascript/templating/bindings.ts +2 -25
- package/src/javascript/templating/comparator.ts +29 -2
- package/src/javascript/templating/engine.ts +41 -14
- package/src/javascript/templating/template.ts +6 -0
- package/src/javascript/templating/types.ts +6 -0
- package/src/javascript/tree.ts +1 -0
- package/src/javascript/tsconfig.ts +177 -0
- package/src/javascript/type-mapping.ts +15 -0
- package/src/javascript/visitor.ts +1 -0
- package/src/parser.ts +24 -1
- package/src/print.ts +5 -2
- package/src/rpc/request/parse-project.ts +6 -2
- package/src/rpc/request/parse.ts +7 -2
|
@@ -86,9 +86,10 @@ export class MinimumViableSpacingVisitor<P> extends JavaScriptVisitor<P> {
|
|
|
86
86
|
// e.g., "class DataTable<Row>" not "class DataTable <Row>"
|
|
87
87
|
// Note: body.prefix spacing (space before '{') is handled by SpacesVisitor, not here.
|
|
88
88
|
|
|
89
|
-
if (c.extends
|
|
89
|
+
if (c.extends) {
|
|
90
90
|
c = produce(c, draft => {
|
|
91
91
|
this.ensureSpace(draft.extends!.before);
|
|
92
|
+
this.ensureSpace(draft.extends!.element.prefix);
|
|
92
93
|
});
|
|
93
94
|
}
|
|
94
95
|
|
|
@@ -156,10 +157,9 @@ export class MinimumViableSpacingVisitor<P> extends JavaScriptVisitor<P> {
|
|
|
156
157
|
protected async visitNewClass(newClass: J.NewClass, p: P): Promise<J | undefined> {
|
|
157
158
|
const ret = await super.visitNewClass(newClass, p) as J.NewClass;
|
|
158
159
|
return produce(ret, draft => {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
160
|
+
// a parenthesized class expression separates itself from `new`
|
|
161
|
+
if (draft.class && draft.class.kind !== J.Kind.Parentheses) {
|
|
162
|
+
this.ensureSpace((draft.class as Draft<J>).prefix);
|
|
163
163
|
}
|
|
164
164
|
});
|
|
165
165
|
}
|
|
@@ -232,12 +232,54 @@ export class MinimumViableSpacingVisitor<P> extends JavaScriptVisitor<P> {
|
|
|
232
232
|
return ret;
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
+
protected async visitAlias(alias: JS.Alias, p: P): Promise<J | undefined> {
|
|
236
|
+
const ret = await super.visitAlias(alias, p) as JS.Alias;
|
|
237
|
+
return produce(ret, draft => {
|
|
238
|
+
this.ensureSpace(draft.propertyName.after);
|
|
239
|
+
this.ensureSpace(draft.alias.prefix);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
protected async visitAs(as_: JS.As, p: P): Promise<J | undefined> {
|
|
244
|
+
const ret = await super.visitAs(as_, p) as JS.As;
|
|
245
|
+
return produce(ret, draft => {
|
|
246
|
+
this.ensureSpace(draft.left.after);
|
|
247
|
+
this.ensureSpace(draft.right.prefix);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
protected async visitBinaryExtensions(jsBinary: JS.Binary, p: P): Promise<J | undefined> {
|
|
252
|
+
const ret = await super.visitBinaryExtensions(jsBinary, p) as JS.Binary;
|
|
253
|
+
// `in` is the only word operator here; the rest are punctuators that need no separation
|
|
254
|
+
if (ret.operator.element !== JS.Binary.Type.In) {
|
|
255
|
+
return ret;
|
|
256
|
+
}
|
|
257
|
+
return produce(ret, draft => {
|
|
258
|
+
this.ensureSpace(draft.operator.before);
|
|
259
|
+
this.ensureSpace(draft.right.prefix);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
protected async visitBreak(breakNode: J.Break, p: P): Promise<J | undefined> {
|
|
264
|
+
const ret = await super.visitBreak(breakNode, p) as J.Break;
|
|
265
|
+
return ret.label ? produce(ret, draft => {
|
|
266
|
+
this.ensureSpace(draft.label!.prefix);
|
|
267
|
+
}) : ret;
|
|
268
|
+
}
|
|
235
269
|
|
|
236
270
|
protected async visitCase(caseNode: J.Case, p: P): Promise<J | undefined> {
|
|
237
|
-
|
|
271
|
+
let c = await super.visitCase(caseNode, p) as J.Case;
|
|
272
|
+
|
|
273
|
+
// `default` prints without the `case` keyword, so its label needs no separator
|
|
274
|
+
const first = c.caseLabels.elements[0]?.element;
|
|
275
|
+
if (first && (first.kind !== J.Kind.Identifier || (first as J.Identifier).simpleName !== "default")) {
|
|
276
|
+
c = produce(c, draft => {
|
|
277
|
+
this.ensureSpace(draft.caseLabels.before);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
238
280
|
|
|
239
281
|
if (c.guard && c.caseLabels.elements.length > 0 && c.caseLabels.elements[c.caseLabels.elements.length - 1].after.whitespace === "") {
|
|
240
|
-
|
|
282
|
+
c = produce(c, draft => {
|
|
241
283
|
const last = draft.caseLabels.elements.length - 1;
|
|
242
284
|
draft.caseLabels.elements[last].after.whitespace = " ";
|
|
243
285
|
});
|
|
@@ -246,6 +288,153 @@ export class MinimumViableSpacingVisitor<P> extends JavaScriptVisitor<P> {
|
|
|
246
288
|
return c;
|
|
247
289
|
}
|
|
248
290
|
|
|
291
|
+
protected async visitContinue(continueNode: J.Continue, p: P): Promise<J | undefined> {
|
|
292
|
+
const ret = await super.visitContinue(continueNode, p) as J.Continue;
|
|
293
|
+
return ret.label ? produce(ret, draft => {
|
|
294
|
+
this.ensureSpace(draft.label!.prefix);
|
|
295
|
+
}) : ret;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
protected async visitDelete(delete_: JS.Delete, p: P): Promise<J | undefined> {
|
|
299
|
+
const ret = await super.visitDelete(delete_, p) as JS.Delete;
|
|
300
|
+
return produce(ret, draft => {
|
|
301
|
+
this.ensureSpace(draft.expression.prefix);
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
protected async visitExportAssignment(exportAssignment: JS.ExportAssignment, p: P): Promise<J | undefined> {
|
|
306
|
+
const ret = await super.visitExportAssignment(exportAssignment, p) as JS.ExportAssignment;
|
|
307
|
+
if (ret.exportEquals) {
|
|
308
|
+
return ret;
|
|
309
|
+
}
|
|
310
|
+
return produce(ret, draft => {
|
|
311
|
+
this.ensureSpace(draft.expression.before);
|
|
312
|
+
this.ensureSpace(draft.expression.element.prefix);
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
protected async visitExportDeclaration(exportDeclaration: JS.ExportDeclaration, p: P): Promise<J | undefined> {
|
|
317
|
+
const ret = await super.visitExportDeclaration(exportDeclaration, p) as JS.ExportDeclaration;
|
|
318
|
+
return produce(ret, draft => {
|
|
319
|
+
if (draft.typeOnly.element) {
|
|
320
|
+
this.ensureSpace(draft.typeOnly.before);
|
|
321
|
+
}
|
|
322
|
+
// a namespace re-export ends its clause with the alias, unlike `}` or a bare `*`
|
|
323
|
+
if (draft.moduleSpecifier && draft.exportClause?.kind === JS.Kind.Alias) {
|
|
324
|
+
this.ensureSpace(draft.moduleSpecifier.before);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
protected async visitForInLoop(forInLoop: JS.ForInLoop, p: P): Promise<J | undefined> {
|
|
330
|
+
const ret = await super.visitForInLoop(forInLoop, p) as JS.ForInLoop;
|
|
331
|
+
return produce(ret, draft => {
|
|
332
|
+
this.ensureSpace(draft.control.variable.after);
|
|
333
|
+
this.ensureSpace(draft.control.iterable.element.prefix);
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
protected async visitForOfLoop(forOfLoop: JS.ForOfLoop, p: P): Promise<J | undefined> {
|
|
338
|
+
const ret = await super.visitForOfLoop(forOfLoop, p) as JS.ForOfLoop;
|
|
339
|
+
return produce(ret, draft => {
|
|
340
|
+
this.ensureSpace(draft.loop.control.variable.after);
|
|
341
|
+
this.ensureSpace(draft.loop.control.iterable.element.prefix);
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
protected async visitImportClause(importClause: JS.ImportClause, p: P): Promise<J | undefined> {
|
|
346
|
+
const ret = await super.visitImportClause(importClause, p) as JS.ImportClause;
|
|
347
|
+
return produce(ret, draft => {
|
|
348
|
+
// named bindings open with a punctuator, which separates itself from `import` and `type`
|
|
349
|
+
if (draft.typeOnly || draft.name) {
|
|
350
|
+
this.ensureSpace(draft.prefix);
|
|
351
|
+
}
|
|
352
|
+
if (draft.typeOnly && draft.name) {
|
|
353
|
+
this.ensureSpace(draft.name.element.prefix);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
protected async visitImportDeclaration(jsImport: JS.Import, p: P): Promise<J | undefined> {
|
|
359
|
+
const ret = await super.visitImportDeclaration(jsImport, p) as JS.Import;
|
|
360
|
+
// `from` prints only with a clause, and not at all in the `= require(...)` form; `}` separates
|
|
361
|
+
// named imports from it, and the specifier after it is always a string literal
|
|
362
|
+
const bindings = ret.importClause?.namedBindings;
|
|
363
|
+
if (!ret.importClause || !ret.moduleSpecifier || bindings?.kind === JS.Kind.NamedImports) {
|
|
364
|
+
return ret;
|
|
365
|
+
}
|
|
366
|
+
return produce(ret, draft => {
|
|
367
|
+
this.ensureSpace(draft.moduleSpecifier!.before);
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
protected async visitInstanceOf(instanceOf: J.InstanceOf, p: P): Promise<J | undefined> {
|
|
372
|
+
const ret = await super.visitInstanceOf(instanceOf, p) as J.InstanceOf;
|
|
373
|
+
return produce(ret, draft => {
|
|
374
|
+
this.ensureSpace(draft.expression.after);
|
|
375
|
+
this.ensureSpace(draft.class.prefix);
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
protected async visitSatisfiesExpression(satisfies: JS.SatisfiesExpression, p: P): Promise<J | undefined> {
|
|
380
|
+
const ret = await super.visitSatisfiesExpression(satisfies, p) as JS.SatisfiesExpression;
|
|
381
|
+
return produce(ret, draft => {
|
|
382
|
+
this.ensureSpace(draft.satisfiesType.before);
|
|
383
|
+
this.ensureSpace(draft.satisfiesType.element.prefix);
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
protected async visitScopedVariableDeclarations(scoped: JS.ScopedVariableDeclarations, p: P): Promise<J | undefined> {
|
|
388
|
+
const ret = await super.visitScopedVariableDeclarations(scoped, p) as JS.ScopedVariableDeclarations;
|
|
389
|
+
if (ret.modifiers.length === 0 || ret.variables.length === 0) {
|
|
390
|
+
return ret;
|
|
391
|
+
}
|
|
392
|
+
return produce(ret, draft => {
|
|
393
|
+
for (let i = 1; i < draft.modifiers.length; i++) {
|
|
394
|
+
this.ensureSpace(draft.modifiers[i].prefix);
|
|
395
|
+
}
|
|
396
|
+
this.ensureSpace(draft.variables[0].element.prefix);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
protected async visitTypeOperator(typeOperator: JS.TypeOperator, p: P): Promise<J | undefined> {
|
|
401
|
+
const ret = await super.visitTypeOperator(typeOperator, p) as JS.TypeOperator;
|
|
402
|
+
return produce(ret, draft => {
|
|
403
|
+
this.ensureSpace(draft.expression.before);
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
protected async visitTypePredicate(typePredicate: JS.TypePredicate, p: P): Promise<J | undefined> {
|
|
408
|
+
const ret = await super.visitTypePredicate(typePredicate, p) as JS.TypePredicate;
|
|
409
|
+
return produce(ret, draft => {
|
|
410
|
+
if (draft.asserts.element) {
|
|
411
|
+
this.ensureSpace(draft.parameterName.prefix);
|
|
412
|
+
}
|
|
413
|
+
if (draft.expression) {
|
|
414
|
+
this.ensureSpace(draft.expression.before);
|
|
415
|
+
this.ensureSpace(draft.expression.element.prefix);
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
protected async visitVoid(void_: JS.Void, p: P): Promise<J | undefined> {
|
|
421
|
+
const ret = await super.visitVoid(void_, p) as JS.Void;
|
|
422
|
+
return produce(ret, draft => {
|
|
423
|
+
this.ensureSpace(draft.expression.prefix);
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
protected async visitYield(aYield: J.Yield, p: P): Promise<J | undefined> {
|
|
428
|
+
const ret = await super.visitYield(aYield, p) as J.Yield;
|
|
429
|
+
// `yield*` separates itself from the value
|
|
430
|
+
if (!ret.value || findMarker(ret, JS.Markers.DelegatedYield)) {
|
|
431
|
+
return ret;
|
|
432
|
+
}
|
|
433
|
+
return produce(ret, draft => {
|
|
434
|
+
this.ensureSpace(draft.value!.prefix);
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
249
438
|
private ensureSpace(spaceDraft: Draft<J.Space>) {
|
|
250
439
|
if (spaceDraft.whitespace.length === 0 && spaceDraft.comments.length === 0) {
|
|
251
440
|
spaceDraft.whitespace = " ";
|
|
@@ -357,6 +357,15 @@ function pruneNode(node: any, path: PathSegment[], pathIndex: number, target: an
|
|
|
357
357
|
return node;
|
|
358
358
|
}
|
|
359
359
|
|
|
360
|
+
// A compilation unit's statements are laid out at column 0, so nothing beside the target bears
|
|
361
|
+
// on how Prettier lays it out and the printed program can be the target alone.
|
|
362
|
+
if (node.kind === JS.Kind.CompilationUnit && segment.property === 'statements' && segment.index !== undefined) {
|
|
363
|
+
const statements = value as J.RightPadded<Statement>[];
|
|
364
|
+
return updateIfChanged(node, {
|
|
365
|
+
statements: [pruneNode(statements[segment.index], path, pathIndex + 1, target)]
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
360
369
|
// Handle J.Block#statements specially - prune siblings
|
|
361
370
|
if (node.kind === J.Kind.Block && segment.property === 'statements' && segment.index !== undefined) {
|
|
362
371
|
const statements = value as J.RightPadded<Statement>[];
|
|
@@ -430,10 +439,10 @@ function findByPath(tree: any, path: PathSegment[]): any {
|
|
|
430
439
|
if (value == null) return undefined;
|
|
431
440
|
|
|
432
441
|
if (Array.isArray(value) && segment.index !== undefined) {
|
|
433
|
-
//
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
const index =
|
|
442
|
+
// In pruned statement lists the target is last, following siblings having been omitted
|
|
443
|
+
const isPrunedStatements = segment.property === 'statements' &&
|
|
444
|
+
(current.kind === J.Kind.Block || current.kind === JS.Kind.CompilationUnit);
|
|
445
|
+
const index = isPrunedStatements ? value.length - 1 : segment.index;
|
|
437
446
|
const item = value[index];
|
|
438
447
|
if (item == null) return undefined;
|
|
439
448
|
current = item;
|
|
@@ -474,6 +483,12 @@ export async function prettierFormatSubtree<T extends J>(
|
|
|
474
483
|
return undefined;
|
|
475
484
|
}
|
|
476
485
|
|
|
486
|
+
// Whatever stands between a statement and the top of its file is the file's business, so a whole
|
|
487
|
+
// statement keeps the prefix it came with. Prettier sees it, for the directives — a leading
|
|
488
|
+
// `prettier-ignore` — that a statement's own layout answers to.
|
|
489
|
+
const wholeStatement = path.length === 2 && path[0].property === 'statements' &&
|
|
490
|
+
path[0].index !== undefined && path[1].property === 'element';
|
|
491
|
+
|
|
477
492
|
// Prune the tree for efficient formatting and substitute the (potentially modified) target.
|
|
478
493
|
// This ensures that if the visitor modified the target before calling autoFormat,
|
|
479
494
|
// we format the modified content, not the original from the cursor.
|
|
@@ -492,7 +507,12 @@ export async function prettierFormatSubtree<T extends J>(
|
|
|
492
507
|
const reconciler = new WhitespaceReconciler();
|
|
493
508
|
const reconciled = reconciler.reconcile(target as J, formattedTarget as J, undefined, stopAfter);
|
|
494
509
|
|
|
495
|
-
|
|
510
|
+
// The walk that carries whitespace back pairs the two trees node for node, which a change to
|
|
511
|
+
// the code itself — Prettier dropping redundant parentheses, say — makes impossible
|
|
512
|
+
if (!reconciler.isCompatible()) {
|
|
513
|
+
return undefined;
|
|
514
|
+
}
|
|
515
|
+
return (wholeStatement ? {...reconciled as T, prefix: target.prefix} : reconciled as T);
|
|
496
516
|
}
|
|
497
517
|
|
|
498
518
|
/**
|
|
@@ -554,7 +574,8 @@ export function getPrettierStyle(
|
|
|
554
574
|
* @param p The visitor parameter
|
|
555
575
|
* @param cursor Optional cursor for subtree formatting
|
|
556
576
|
* @param stopAfter Optional tree to stop after
|
|
557
|
-
* @returns The formatted tree
|
|
577
|
+
* @returns The formatted tree, or `undefined` where Prettier's result cannot be carried back,
|
|
578
|
+
* leaving the caller to lay the tree out itself
|
|
558
579
|
*/
|
|
559
580
|
export async function applyPrettierFormatting<R extends J, P>(
|
|
560
581
|
tree: R,
|
|
@@ -589,31 +610,20 @@ export async function applyPrettierFormatting<R extends J, P>(
|
|
|
589
610
|
prettierVersion: prettierStyle.prettierVersion,
|
|
590
611
|
};
|
|
591
612
|
|
|
613
|
+
const wholeFile = t.kind === JS.Kind.CompilationUnit;
|
|
592
614
|
try {
|
|
593
|
-
if (
|
|
615
|
+
if (wholeFile) {
|
|
594
616
|
// Format and reconcile the entire compilation unit
|
|
595
617
|
const formatted = await prettierFormat(t as unknown as JS.CompilationUnit, prettierOpts, stopAfter as J | undefined);
|
|
596
618
|
return formatted as unknown as R;
|
|
597
619
|
}
|
|
598
620
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
console.warn('Prettier formatting: No cursor provided for subtree, returning with essential formatting only');
|
|
602
|
-
return t;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
// Use prettierFormatSubtree for subtree formatting
|
|
606
|
-
const formatted = await prettierFormatSubtree(t, cursor, prettierOpts, stopAfter as J | undefined);
|
|
607
|
-
if (formatted) {
|
|
608
|
-
return formatted as R;
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
// Subtree formatting failed, return with essential formatting applied
|
|
612
|
-
console.warn('Prettier formatting: Subtree formatting failed, returning with essential formatting only');
|
|
613
|
-
return t;
|
|
621
|
+
// Pruning and reconciling a subtree both go by where it sits in its file
|
|
622
|
+
return cursor && await prettierFormatSubtree(t, cursor, prettierOpts, stopAfter as J | undefined) as R | undefined;
|
|
614
623
|
} catch (e) {
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
624
|
+
console.warn('Prettier formatting failed:', e);
|
|
625
|
+
// The built-in visitors lay out every line they are given, so a whole file — the author's
|
|
626
|
+
// layout rather than a recipe's — keeps the one it came with; a subtree is handed on.
|
|
627
|
+
return wholeFile ? t : undefined;
|
|
618
628
|
}
|
|
619
629
|
}
|
package/src/javascript/index.ts
CHANGED
|
@@ -32,13 +32,20 @@ export * from "./tree-debug";
|
|
|
32
32
|
export * from "./project-parser";
|
|
33
33
|
|
|
34
34
|
export type {Scope} from "./scope";
|
|
35
|
-
|
|
35
|
+
// `cursorOf` is deliberately absent: a visitor of one's own reaches `this.cursor` directly, and
|
|
36
|
+
// the free functions that have no visitor to reach it through are already in this list.
|
|
37
|
+
export {
|
|
38
|
+
scopeOf, namesDeclaredIn, namesDeclaredWithin, namesUsedIn, bindingNames, deconflict,
|
|
39
|
+
isValueReference, declarationsOf, compilationUnitOf, walk
|
|
40
|
+
} from "./scope";
|
|
36
41
|
export type {QuoteChar, AddImportOptions} from "./add-import";
|
|
37
42
|
export {ImportStyle, moduleNameOf, AddImport} from "./add-import";
|
|
38
43
|
// AMD mechanics `recipes-ui5` builds on directly, beyond the `maybeBind` surface below.
|
|
39
|
-
export type {AmdBlock} from "./amd";
|
|
44
|
+
export type {AmdBlock, AmdCalleeOptions} from "./amd";
|
|
40
45
|
export {
|
|
41
|
-
DEFAULT_AMD_CALLEES, amdBlockOf,
|
|
46
|
+
DEFAULT_AMD_CALLEES, amdBlockOf, enclosingAmdBlock, present, elementsOf, parametersOf, identifierOf,
|
|
47
|
+
dependencyNames, parameterNames, bodyOf, references, namesUsed, lastSegment, derivedBindingName,
|
|
48
|
+
withDependency, withUnboundDependency, withoutDependencyAt,
|
|
42
49
|
RemoveAmdDependency, removeNewlyUnusedAmdBindings
|
|
43
50
|
} from "./amd";
|
|
44
51
|
export type {MaybeBindOptions, MaybeUnbindOptions, MaybeRebindOptions, ModuleBindings} from "./binding";
|
|
@@ -351,8 +351,9 @@ export function hasFlowAnnotation(sourceFile: ts.SourceFile) {
|
|
|
351
351
|
}
|
|
352
352
|
|
|
353
353
|
export function checkSyntaxErrors(program: ts.Program, sourceFile: ts.SourceFile) {
|
|
354
|
-
|
|
355
|
-
//
|
|
354
|
+
// Only parse diagnostics decide whether a file gets an LST, so the visitor has to map every slot the
|
|
355
|
+
// parser fills — including ones the checker would reject — or the file loses text on print.
|
|
356
|
+
const diagnostics = program.getSyntacticDiagnostics(sourceFile);
|
|
356
357
|
let syntaxErrors : [errorMsg: string, errorCode: number][] = [];
|
|
357
358
|
if (diagnostics.length > 0) {
|
|
358
359
|
const errors = diagnostics.filter(d => (d.category === ts.DiagnosticCategory.Error) && isCriticalDiagnostic(d.code, sourceFile));
|
|
@@ -373,18 +374,11 @@ export function checkSyntaxErrors(program: ts.Program, sourceFile: ts.SourceFile
|
|
|
373
374
|
return syntaxErrors;
|
|
374
375
|
}
|
|
375
376
|
|
|
376
|
-
const additionalCriticalCodes = new Set([
|
|
377
|
-
// Syntax errors
|
|
378
|
-
17019, // "'{0}' at the end of a type is not valid TypeScript syntax. Did you mean to write '{1}'?"
|
|
379
|
-
17020, // "'{0}' at the start of a type is not valid TypeScript syntax. Did you mean to write '{1}'?"
|
|
380
|
-
|
|
381
|
-
// Other critical errors
|
|
382
|
-
]);
|
|
383
|
-
|
|
384
377
|
// errors code description available at https://github.com/microsoft/TypeScript/blob/main/src/compiler/diagnosticMessages.json
|
|
385
378
|
const excludedCodes = new Set([
|
|
386
379
|
1039, // Initializers are not allowed in ambient contexts.
|
|
387
380
|
1064, // The return type of an async function or method must be the global Promise<T> type. Did you mean to write 'Promise<{0}>'?
|
|
381
|
+
1101, // 'with' statements are not allowed in strict mode.
|
|
388
382
|
1107, // Jump target cannot cross function boundary.
|
|
389
383
|
1111, // Private field '{0}' must be declared in an enclosing class.
|
|
390
384
|
1117, // An object literal cannot have multiple properties with the same name.
|
|
@@ -446,7 +440,7 @@ function isCriticalDiagnostic(code: number, sourceFile: ts.SourceFile): boolean
|
|
|
446
440
|
}
|
|
447
441
|
}
|
|
448
442
|
|
|
449
|
-
return
|
|
443
|
+
return code > 1000 && code < 2000 && !excludedCodes.has(code);
|
|
450
444
|
}
|
|
451
445
|
|
|
452
446
|
export function isValidSurrogateRange(unicodeString: string): boolean {
|