Skip to content

Commit df1820e

Browse files
committed
4 errors left
1 parent ebe3123 commit df1820e

7 files changed

Lines changed: 210 additions & 15 deletions

File tree

src/harness/unittests/textChanges.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,5 +565,90 @@ const /*x*/ x = 1,
565565
changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
566566
});
567567
}
568+
{
569+
const text = `
570+
import {
571+
x
572+
} from "bar"`;
573+
runSingleFileTest("insertNodeInListAfter10", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
574+
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
575+
})
576+
}
577+
{
578+
const text = `
579+
import {
580+
x // this is x
581+
} from "bar"`;
582+
runSingleFileTest("insertNodeInListAfter11", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
583+
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
584+
})
585+
}
586+
{
587+
const text = `
588+
import {
589+
x
590+
} from "bar"`;
591+
runSingleFileTest("insertNodeInListAfter12", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
592+
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
593+
})
594+
}
595+
{
596+
const text = `
597+
import {
598+
x // this is x
599+
} from "bar"`;
600+
runSingleFileTest("insertNodeInListAfter13", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
601+
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
602+
})
603+
}
604+
{
605+
const text = `
606+
import {
607+
x0,
608+
x
609+
} from "bar"`;
610+
runSingleFileTest("insertNodeInListAfter14", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
611+
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
612+
})
613+
}
614+
{
615+
const text = `
616+
import {
617+
x0,
618+
x // this is x
619+
} from "bar"`;
620+
runSingleFileTest("insertNodeInListAfter15", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
621+
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
622+
})
623+
}
624+
{
625+
const text = `
626+
import {
627+
x0,
628+
x
629+
} from "bar"`;
630+
runSingleFileTest("insertNodeInListAfter16", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
631+
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
632+
})
633+
}
634+
{
635+
const text = `
636+
import {
637+
x0,
638+
x // this is x
639+
} from "bar"`;
640+
runSingleFileTest("insertNodeInListAfter17", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
641+
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
642+
})
643+
}
644+
{
645+
const text = `
646+
import {
647+
x0, x
648+
} from "bar"`;
649+
runSingleFileTest("insertNodeInListAfter18", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
650+
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
651+
})
652+
}
568653
});
569654
}

src/services/textChanges.ts

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,19 @@ namespace ts.textChanges {
3838
return skipTrivia(text, start, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
3939
}
4040

41+
function hasCommentsBeforeLineBreak(text: string, start: number) {
42+
let i = start;
43+
while (i < text.length) {
44+
const ch = text.charCodeAt(i);
45+
if (isWhiteSpaceSingleLine(ch)) {
46+
i++;
47+
continue;
48+
}
49+
return ch === CharacterCodes.slash;
50+
}
51+
return false;
52+
}
53+
4154
function getPosition(node: Node, sourceFile: SourceFile, position: Position) {
4255
switch (position) {
4356
case Position.FullStart:
@@ -269,16 +282,39 @@ namespace ts.textChanges {
269282
if (index < 0) {
270283
return this;
271284
}
285+
const end = after.getEnd();
272286
if (containingList.length === 1) {
273-
// list with one element - format as single line
274-
const endPosition = getAdjustedEndPosition(sourceFile, after, options);
275-
this.changes.push({
276-
sourceFile,
277-
range: { pos: endPosition, end: endPosition },
278-
node: newNode,
279-
useIndentationFromFile: true,
280-
options: { prefix: ", " }
281-
});
287+
// list with one element
288+
// check if element has non-whitespace only trailing trivia
289+
// if yes - format list as multiline
290+
// if no - format as singleline
291+
if (!hasCommentsBeforeLineBreak(sourceFile.text, end)) {
292+
// format as single line
293+
this.changes.push({
294+
sourceFile,
295+
range: { pos: end, end },
296+
node: newNode,
297+
useIndentationFromFile: true,
298+
options: { prefix: ", " }
299+
});
300+
}
301+
else {
302+
const adjustedEndPosition = getAdjustedEndPosition(sourceFile, after, options);
303+
// format as multiline
304+
// 1. insert comma after 'after' node
305+
this.changes.push({
306+
sourceFile,
307+
range: { pos: end, end },
308+
node: createToken(SyntaxKind.CommaToken),
309+
options: {}
310+
});
311+
this.changes.push({
312+
sourceFile,
313+
range: { pos: adjustedEndPosition, end: adjustedEndPosition },
314+
node: newNode,
315+
options: {}
316+
});
317+
}
282318
}
283319
else if (index !== containingList.length - 1) {
284320
// any element except the last one
@@ -335,29 +371,47 @@ namespace ts.textChanges {
335371
// - determine if list is a multiline
336372
const afterMinusOne = containingList[index - 1];
337373
const separatorBefore = <Token<SyntaxKind.CommaToken | SyntaxKind.SemicolonToken>>getSeparator(sourceFile, afterMinusOne);
338-
const endPosition = getAdjustedEndPosition(sourceFile, after, options);
339-
const range = { pos: endPosition, end: endPosition };
374+
const end = after.getEnd();
340375
const afterMinusOneStartLinePosition = getLineStartPositionForPosition(afterMinusOne.getStart(sourceFile), sourceFile);
341376
const afterStart = after.getStart(sourceFile);
342377
const afterStartLinePosition = getLineStartPositionForPosition(afterStart, sourceFile);
378+
let prefix = "";
379+
// insert separator following 'after item' if 'after' has some trailing trivia
380+
if (hasCommentsBeforeLineBreak(sourceFile.text, after.end)) {
381+
this.changes.push({
382+
sourceFile,
383+
range: { pos: end, end },
384+
node: separatorBefore,
385+
options: {}
386+
});
387+
}
388+
else {
389+
// prepend separtor to prefix
390+
prefix = getSeparatorCharacter(separatorBefore);
391+
}
343392
if (afterMinusOneStartLinePosition !== afterStartLinePosition) {
344393
// multiline list
345394
// use the same indentation as 'after' item
395+
let p = skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ false);
396+
if (p !== end && isLineBreak(sourceFile.text.charCodeAt(p - 1))) {
397+
p--
398+
}
346399
const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, this.rulesProvider.getFormatOptions());
347400
this.changes.push({
348401
sourceFile,
349-
range,
402+
range: { pos: p, end: p },
350403
node: newNode,
351-
options: { prefix: `${getSeparatorCharacter(separatorBefore)}${this.newLineCharacter}`, indentation },
404+
options: { prefix: `${prefix}${this.newLineCharacter}`, indentation },
352405
});
353406
}
354407
else {
408+
//const adjustedEndPosition = getAdjustedEndPosition(sourceFile, after, options);
355409
// single line list
356410
this.changes.push({
357411
sourceFile,
358-
range,
412+
range: { pos: end, end: end },
359413
node: newNode,
360-
options: { prefix: `${getSeparatorCharacter(separatorBefore)} ` }, // ensure that new item is separate from previous item by one whitespace
414+
options: { prefix: `${prefix} ` }, // ensure that new item is separate from previous item by one whitespace
361415
})
362416
}
363417
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
===ORIGINAL===
2+
3+
import {
4+
x
5+
} from "bar"
6+
===MODIFIED===
7+
8+
import {
9+
x, b as a
10+
} from "bar"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
===ORIGINAL===
2+
3+
import {
4+
x
5+
} from "bar"
6+
===MODIFIED===
7+
8+
import {
9+
x, a
10+
} from "bar"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
===ORIGINAL===
2+
3+
import {
4+
x0,
5+
x
6+
} from "bar"
7+
===MODIFIED===
8+
9+
import {
10+
x0,
11+
x,
12+
b as a
13+
} from "bar"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
===ORIGINAL===
2+
3+
import {
4+
x0,
5+
x // this is x
6+
} from "bar"
7+
===MODIFIED===
8+
9+
import {
10+
x0,
11+
x, // this is x
12+
b as a
13+
} from "bar"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
===ORIGINAL===
2+
3+
import {
4+
x0, x
5+
} from "bar"
6+
===MODIFIED===
7+
8+
import {
9+
x0, x, a
10+
} from "bar"

0 commit comments

Comments
 (0)