Skip to content

Commit 2f82d02

Browse files
authored
Fix Add all missing imports when ordered alphabetically (microsoft#43453)
* Refactored insertNodeInlistAfter to use next elements position * Consider trivia on insertNodeInListAfter
1 parent d41943e commit 2f82d02

File tree

2 files changed

+39
-41
lines changed

2 files changed

+39
-41
lines changed

src/services/textChanges.ts

Lines changed: 8 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -236,14 +236,6 @@ namespace ts.textChanges {
236236
return !!candidate && !!node.parent && (candidate.kind === SyntaxKind.CommaToken || (candidate.kind === SyntaxKind.SemicolonToken && node.parent.kind === SyntaxKind.ObjectLiteralExpression));
237237
}
238238

239-
function spaces(count: number) {
240-
let s = "";
241-
for (let i = 0; i < count; i++) {
242-
s += " ";
243-
}
244-
return s;
245-
}
246-
247239
export interface TextChangesContext {
248240
host: LanguageServiceHost;
249241
formatContext: formatting.FormatContext;
@@ -727,49 +719,24 @@ namespace ts.textChanges {
727719
// a, b, c
728720
// create change for adding 'e' after 'a' as
729721
// - find start of next element after a (it is b)
730-
// - use this start as start and end position in final change
731-
// - build text of change by formatting the text of node + separator + whitespace trivia of b
722+
// - use next element start as start and end position in final change
723+
// - build text of change by formatting the text of node + whitespace trivia of b
732724

733725
// in multiline case it will work as
734726
// a,
735727
// b,
736728
// c,
737729
// result - '*' denotes leading trivia that will be inserted after new text (displayed as '#')
738-
// a,*
739-
// ***insertedtext<separator>#
730+
// a,
731+
// insertedtext<separator>#
740732
// ###b,
741733
// c,
742-
// find line and character of the next element
743-
const lineAndCharOfNextElement = getLineAndCharacterOfPosition(sourceFile, skipWhitespacesAndLineBreaks(sourceFile.text, containingList[index + 1].getFullStart()));
744-
// find line and character of the token that precedes next element (usually it is separator)
745-
const lineAndCharOfNextToken = getLineAndCharacterOfPosition(sourceFile, nextToken.end);
746-
let prefix: string | undefined;
747-
let startPos: number;
748-
if (lineAndCharOfNextToken.line === lineAndCharOfNextElement.line) {
749-
// next element is located on the same line with separator:
750-
// a,$$$$b
751-
// ^ ^
752-
// | |-next element
753-
// |-separator
754-
// where $$$ is some leading trivia
755-
// for a newly inserted node we'll maintain the same relative position comparing to separator and replace leading trivia with spaces
756-
// a, x,$$$$b
757-
// ^ ^ ^
758-
// | | |-next element
759-
// | |-new inserted node padded with spaces
760-
// |-separator
761-
startPos = nextToken.end;
762-
prefix = spaces(lineAndCharOfNextElement.character - lineAndCharOfNextToken.character);
763-
}
764-
else {
765-
// next element is located on different line that separator
766-
// let insert position be the beginning of the line that contains next element
767-
startPos = getStartPositionOfLine(lineAndCharOfNextElement.line, sourceFile);
768-
}
734+
const nextNode = containingList[index + 1];
735+
const startPos = skipWhitespacesAndLineBreaks(sourceFile.text, nextNode.getFullStart());
769736

770737
// write separator and leading trivia of the next element as suffix
771-
const suffix = `${tokenToString(nextToken.kind)}${sourceFile.text.substring(nextToken.end, containingList[index + 1].getStart(sourceFile))}`;
772-
this.replaceRange(sourceFile, createRange(startPos, containingList[index + 1].getStart(sourceFile)), newNode, { prefix, suffix });
738+
const suffix = `${tokenToString(nextToken.kind)}${sourceFile.text.substring(nextToken.end, startPos)}`;
739+
this.insertNodesAt(sourceFile, startPos, [newNode], { suffix });
773740
}
774741
}
775742
else {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @Filename: file1.ts
4+
//// export interface Test1 {}
5+
//// export interface Test2 {}
6+
//// export interface Test3 {}
7+
//// export interface Test4 {}
8+
9+
// @Filename: file2.ts
10+
//// import { Test1, Test4 } from './file1';
11+
//// interface Testing {
12+
//// test1: Test1;
13+
//// test2: Test2;
14+
//// test3: Test3;
15+
//// test4: Test4;
16+
//// }
17+
18+
goTo.file("file2.ts");
19+
20+
verify.codeFixAll({
21+
fixId: "fixMissingImport",
22+
fixAllDescription: "Add all missing imports",
23+
newFileContent:
24+
`import { Test1, Test2, Test3, Test4 } from './file1';
25+
interface Testing {
26+
test1: Test1;
27+
test2: Test2;
28+
test3: Test3;
29+
test4: Test4;
30+
}`
31+
});

0 commit comments

Comments
 (0)