In insertNodeAfter, handle file with no trailing newline (#23814)
This commit is contained in:
parent
94d94f6335
commit
bad3a44bb2
|
@ -2662,10 +2662,10 @@ Actual: ${stringify(fullActual)}`);
|
|||
public verifyImportFixAtPosition(expectedTextArray: string[], errorCode: number | undefined, preferences: ts.UserPreferences | undefined) {
|
||||
const { fileName } = this.activeFile;
|
||||
const ranges = this.getRanges().filter(r => r.fileName === fileName);
|
||||
if (ranges.length !== 1) {
|
||||
if (ranges.length > 1) {
|
||||
this.raiseError("Exactly one range should be specified in the testfile.");
|
||||
}
|
||||
const range = ts.first(ranges);
|
||||
const range = ts.firstOrUndefined(ranges);
|
||||
|
||||
const codeFixes = this.getCodeFixes(fileName, errorCode, preferences).filter(f => f.fixId === undefined); // TODO: GH#20315 filter out those that use the import fix ID;
|
||||
|
||||
|
@ -2684,7 +2684,7 @@ Actual: ${stringify(fullActual)}`);
|
|||
const change = ts.first(codeFix.changes);
|
||||
ts.Debug.assert(change.fileName === fileName);
|
||||
this.applyEdits(change.fileName, change.textChanges, /*isFormattingEdit*/ false);
|
||||
const text = this.rangeText(range);
|
||||
const text = range ? this.rangeText(range) : this.getFileContent(this.activeFile.fileName);
|
||||
actualTextArray.push(text);
|
||||
scriptInfo.updateContent(originalContent);
|
||||
}
|
||||
|
|
|
@ -177,10 +177,10 @@ namespace ts.textChanges {
|
|||
}
|
||||
|
||||
function getAdjustedEndPosition(sourceFile: SourceFile, node: Node, options: ConfigurableEnd) {
|
||||
const { end } = node;
|
||||
if (options.useNonAdjustedEndPosition || isExpression(node)) {
|
||||
return node.getEnd();
|
||||
return end;
|
||||
}
|
||||
const end = node.getEnd();
|
||||
const newEnd = skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true);
|
||||
return newEnd !== end && isLineBreak(sourceFile.text.charCodeAt(newEnd - 1))
|
||||
? newEnd
|
||||
|
@ -466,7 +466,11 @@ namespace ts.textChanges {
|
|||
}
|
||||
}
|
||||
const endPosition = getAdjustedEndPosition(sourceFile, after, {});
|
||||
return this.replaceRange(sourceFile, createTextRange(endPosition), newNode, this.getInsertNodeAfterOptions(after));
|
||||
const options = this.getInsertNodeAfterOptions(after);
|
||||
return this.replaceRange(sourceFile, createTextRange(endPosition), newNode, {
|
||||
...options,
|
||||
prefix: after.end === sourceFile.end && isStatement(after) ? (options.prefix ? `\n${options.prefix}` : "\n") : options.prefix,
|
||||
});
|
||||
}
|
||||
|
||||
private getInsertNodeAfterOptions(node: Node): InsertNodeOptions {
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace M {
|
|||
// comment 6
|
||||
var a = 4; // comment 7
|
||||
}
|
||||
|
||||
public class class1 implements interface1
|
||||
{
|
||||
property1: boolean;
|
||||
|
|
|
@ -18,6 +18,7 @@ verify.codeFix({
|
|||
()=>{ this.foo === 10 };
|
||||
}
|
||||
}
|
||||
|
||||
C.foo = undefined;
|
||||
`
|
||||
});
|
||||
|
|
|
@ -14,6 +14,7 @@ verify.codeFix({
|
|||
newFileContent: `class C {
|
||||
static p = ()=>{ this.foo === 10 };
|
||||
}
|
||||
|
||||
C.foo = undefined;
|
||||
`
|
||||
});
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
verify.codeFix({
|
||||
description: "Convert function to an ES2015 class",
|
||||
newFileContent:
|
||||
`/** Doc */
|
||||
`
|
||||
/** Doc */
|
||||
class C {
|
||||
constructor() { this.x = 0; }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @Filename: /a.ts
|
||||
////export const foo = 0;
|
||||
|
||||
// @Filename: /b.ts
|
||||
////export const bar = 0;
|
||||
|
||||
// @Filename: /c.ts
|
||||
////foo;
|
||||
////import { bar } from "./b";
|
||||
|
||||
goTo.file("/c.ts");
|
||||
verify.importFixAtPosition([
|
||||
`foo;
|
||||
import { bar } from "./b";
|
||||
import { foo } from "./a";
|
||||
`,
|
||||
]);
|
|
@ -13,10 +13,13 @@
|
|||
////import * as g from "global"; // Global imports skipped
|
||||
////import { a } from "./a.js";
|
||||
////import { a as a2 } from "./a"; // Ignored, only the first relative import is considered
|
||||
////[|b;|]
|
||||
////b;
|
||||
|
||||
goTo.file("/c.ts");
|
||||
verify.importFixAtPosition([
|
||||
`import { b } from "./b.js";
|
||||
`import * as g from "global"; // Global imports skipped
|
||||
import { a } from "./a.js";
|
||||
import { a as a2 } from "./a"; // Ignored, only the first relative import is considered
|
||||
import { b } from "./b.js";
|
||||
b;`,
|
||||
]);
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
|
||||
// @Filename: /c.tsx
|
||||
////import { React } from "react";
|
||||
////[|<Foo />;|]
|
||||
////<Foo />;
|
||||
|
||||
// @Filename: /d.tsx
|
||||
////[|import { Foo } from "./Foo";
|
||||
////<Foo />;|]
|
||||
////import { Foo } from "./Foo";
|
||||
////<Foo />;
|
||||
|
||||
// Tests that we don't crash at non-identifier location.
|
||||
goTo.file("/a.tsx");
|
||||
|
@ -26,7 +26,8 @@ verify.importFixAtPosition([]);
|
|||
// When constructor is missing, provide fix for that
|
||||
goTo.file("/c.tsx");
|
||||
verify.importFixAtPosition([
|
||||
`import { Foo } from "./Foo";
|
||||
`import { React } from "react";
|
||||
import { Foo } from "./Foo";
|
||||
<Foo />;`]);
|
||||
|
||||
// When JSX namespace is missing, provide fix for that
|
||||
|
|
Loading…
Reference in a new issue