Skip to content

Commit c40b579

Browse files
committed
Make sibling node comparison work for all lists
1 parent aaf353e commit c40b579

File tree

2 files changed

+44
-16
lines changed

2 files changed

+44
-16
lines changed

src/compiler/emitter.ts

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4514,23 +4514,18 @@ namespace ts {
45144514
return false;
45154515
}
45164516

4517-
if (isImportSpecifier(previousNode)) {
4518-
const getNextSpecifier = (node: ImportSpecifier): ImportSpecifier | undefined => {
4519-
if (!node.parent) {
4520-
return;
4521-
}
4522-
for (const sibling of node.parent.elements) {
4523-
if (node.pos < sibling.pos) {
4524-
return sibling;
4525-
}
4526-
}
4527-
};
4517+
if (nextNode.pos < previousNode.end) {
4518+
return false;
4519+
}
45284520

4529-
// Get the next specifier and compare against nextNode. If they are not equal, nodes have been rearranged and positions cannot be compared.
4530-
const nextSpecifier = getNextSpecifier(previousNode);
4531-
if (nextSpecifier && nextSpecifier !== nextNode) {
4532-
return false;
4533-
}
4521+
if (!previousNode.parent || !nextNode.parent) {
4522+
const previousParent = getOriginalNode(previousNode).parent;
4523+
return previousParent && previousParent === getOriginalNode(nextNode).parent;
4524+
}
4525+
4526+
// Get the next specifier and compare against nextNode. If they are not equal, nodes have been rearranged and positions cannot be compared.
4527+
if (!nodeIsFirstNodeAtOrAfterPosition(currentSourceFile!, getOriginalNode(nextNode), previousNode.end)) {
4528+
return false;
45344529
}
45354530

45364531
return true;

src/compiler/utilities.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7098,4 +7098,37 @@ namespace ts {
70987098
current = child;
70997099
}
71007100
}
7101+
7102+
export function nodeIsFirstNodeAtOrAfterPosition(sourceFile: SourceFile, node: Node, position: number): boolean {
7103+
if (node.pos === position) return true;
7104+
if (node.pos < position) return false;
7105+
let current: Node = sourceFile;
7106+
let next: Node | undefined;
7107+
const getContainingChild = (child: Node) => {
7108+
if (child.pos <= position && (position < child.end || (position === child.end && (child.kind === SyntaxKind.EndOfFileToken)))) {
7109+
return child;
7110+
}
7111+
else if (!next && child.pos > position) {
7112+
next = child;
7113+
}
7114+
};
7115+
while (true) {
7116+
const child = isSourceFileJS(sourceFile) && hasJSDocNodes(current) && forEach(current.jsDoc, getContainingChild) || forEachChild(current, getContainingChild);
7117+
if (child === node || next === node) {
7118+
return true;
7119+
}
7120+
if (!child) {
7121+
if (next) {
7122+
// 'position' fell between two nodes (e.g., the comma between
7123+
// two ImportSpecifiers). Instead of stopping at the parent node,
7124+
// shift forward to the next node and continue searching there.
7125+
position = next.pos;
7126+
next = undefined;
7127+
continue;
7128+
}
7129+
return false;
7130+
}
7131+
current = child;
7132+
}
7133+
}
71017134
}

0 commit comments

Comments
 (0)