Skip to content

Commit 5215977

Browse files
committed
Fix organize imports by looking at the nodes positions
1 parent 67ad6b4 commit 5215977

File tree

4 files changed

+61
-22
lines changed

4 files changed

+61
-22
lines changed

src/compiler/emitter.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,7 @@ namespace ts {
919919
let containerEnd = -1;
920920
let declarationListContainerEnd = -1;
921921
let currentLineMap: readonly number[] | undefined;
922-
let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[] | undefined;
922+
let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number }[] | undefined;
923923
let hasWrittenComment = false;
924924
let commentsDisabled = !!printerOptions.removeComments;
925925
let lastNode: Node | undefined;
@@ -1245,25 +1245,25 @@ namespace ts {
12451245
if (onEmitNode !== noEmitNotification && (!isEmitNotificationEnabled || isEmitNotificationEnabled(node))) {
12461246
return pipelineEmitWithNotification;
12471247
}
1248-
// falls through
1248+
// falls through
12491249

12501250
case PipelinePhase.Substitution:
12511251
if (substituteNode !== noEmitSubstitution && (lastSubstitution = substituteNode(emitHint, node)) !== node) {
12521252
return pipelineEmitWithSubstitution;
12531253
}
1254-
// falls through
1254+
// falls through
12551255

12561256
case PipelinePhase.Comments:
12571257
if (!commentsDisabled && node.kind !== SyntaxKind.SourceFile) {
12581258
return pipelineEmitWithComments;
12591259
}
1260-
// falls through
1260+
// falls through
12611261

12621262
case PipelinePhase.SourceMaps:
12631263
if (!sourceMapsDisabled && node.kind !== SyntaxKind.SourceFile && !isInJsonFile(node)) {
12641264
return pipelineEmitWithSourceMap;
12651265
}
1266-
// falls through
1266+
// falls through
12671267

12681268
case PipelinePhase.Emit:
12691269
return pipelineEmitWithHint;
@@ -4517,6 +4517,12 @@ namespace ts {
45174517
return false;
45184518
}
45194519

4520+
// Get the position next node and compare against nextNode. If they are not equal, nodes have been rearranged and positions cannot be compared.
4521+
const originalNextNode = getNodeAtPosition(currentSourceFile!, previousNode.end + 1);
4522+
if (originalNextNode.pos !== nextNode.pos) {
4523+
return false;
4524+
}
4525+
45204526
if (!previousNode.parent || !nextNode.parent) {
45214527
const previousParent = getOriginalNode(previousNode).parent;
45224528
return previousParent && previousParent === getOriginalNode(nextNode).parent;
@@ -4675,7 +4681,7 @@ namespace ts {
46754681
const text = isNumericLiteral(textSourceNode) ? textSourceNode.text : getTextOfNode(textSourceNode);
46764682
return jsxAttributeEscape ? `"${escapeJsxAttributeString(text)}"` :
46774683
neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? `"${escapeString(text)}"` :
4678-
`"${escapeNonAsciiString(text)}"`;
4684+
`"${escapeNonAsciiString(text)}"`;
46794685
}
46804686
else {
46814687
return getLiteralTextOfNode(textSourceNode, neverAsciiEscape, jsxAttributeEscape);

src/compiler/program.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2354,22 +2354,6 @@ namespace ts {
23542354
}
23552355
}
23562356

2357-
/** Returns a token if position is in [start-of-leading-trivia, end), includes JSDoc only in JS files */
2358-
function getNodeAtPosition(sourceFile: SourceFile, position: number): Node {
2359-
let current: Node = sourceFile;
2360-
const getContainingChild = (child: Node) => {
2361-
if (child.pos <= position && (position < child.end || (position === child.end && (child.kind === SyntaxKind.EndOfFileToken)))) {
2362-
return child;
2363-
}
2364-
};
2365-
while (true) {
2366-
const child = isJavaScriptFile && hasJSDocNodes(current) && forEach(current.jsDoc, getContainingChild) || forEachChild(current, getContainingChild);
2367-
if (!child) {
2368-
return current;
2369-
}
2370-
current = child;
2371-
}
2372-
}
23732357
}
23742358

23752359
function getLibFileFromReference(ref: FileReference) {

src/compiler/utilities.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7081,4 +7081,21 @@ namespace ts {
70817081
return false;
70827082
}
70837083
}
7084+
7085+
/** Returns a token if position is in [start-of-leading-trivia, end), includes JSDoc only in JS files */
7086+
export function getNodeAtPosition(sourceFile: SourceFile, position: number): Node {
7087+
let current: Node = sourceFile;
7088+
const getContainingChild = (child: Node) => {
7089+
if (child.pos <= position && (position < child.end || (position === child.end && (child.kind === SyntaxKind.EndOfFileToken)))) {
7090+
return child;
7091+
}
7092+
};
7093+
while (true) {
7094+
const child = isSourceFileJS(sourceFile) && hasJSDocNodes(current) && forEach(current.jsDoc, getContainingChild) || forEachChild(current, getContainingChild);
7095+
if (!child) {
7096+
return current;
7097+
}
7098+
current = child;
7099+
}
7100+
}
70847101
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// Regression test for bug #41417
4+
5+
//// import {
6+
//// d, d as D,
7+
//// c,
8+
//// c as C, b,
9+
//// b as B, a
10+
//// } from './foo';
11+
//// import {
12+
//// h, h as H,
13+
//// g,
14+
//// g as G, f,
15+
//// f as F, e
16+
//// } from './foo';
17+
////
18+
//// console.log(a, B, b, c, C, d, D);
19+
//// console.log(e, f, F, g, G, H, h);
20+
21+
verify.organizeImports(
22+
`import {
23+
a, b,
24+
b as B, c,
25+
c as C, d, d as D, e, f,
26+
f as F, g,
27+
g as G, h, h as H
28+
} from './foo';
29+
30+
console.log(a, B, b, c, C, d, D);
31+
console.log(e, f, F, g, G, H, h);`
32+
);

0 commit comments

Comments
 (0)