Skip to content

Commit a4b981a

Browse files
author
Arthur Ozga
committed
Merge branch 'master' into createTypeNode
2 parents 4b97893 + 4b3cd6a commit a4b981a

10 files changed

+203
-6
lines changed

src/harness/unittests/textChanges.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,5 +709,83 @@ class A {
709709
changeTracker.deleteNode(sourceFile, findChild("x", sourceFile));
710710
});
711711
}
712+
{
713+
const text = `
714+
class A {
715+
x = foo
716+
}
717+
`
718+
runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
719+
const newNode = createProperty(
720+
/*decorators*/ undefined,
721+
/*modifiers*/ undefined,
722+
createComputedPropertyName(createLiteral(1)),
723+
/*questionToken*/ undefined,
724+
createKeywordTypeNode(SyntaxKind.AnyKeyword),
725+
/*initializer*/ undefined);
726+
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
727+
});
728+
}
729+
{
730+
const text = `
731+
class A {
732+
x() {
733+
}
734+
}
735+
`
736+
runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
737+
const newNode = createProperty(
738+
/*decorators*/ undefined,
739+
/*modifiers*/ undefined,
740+
createComputedPropertyName(createLiteral(1)),
741+
/*questionToken*/ undefined,
742+
createKeywordTypeNode(SyntaxKind.AnyKeyword),
743+
/*initializer*/ undefined);
744+
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
745+
});
746+
}
747+
{
748+
const text = `
749+
interface A {
750+
x
751+
}
752+
`
753+
runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
754+
const newNode = createProperty(
755+
/*decorators*/ undefined,
756+
/*modifiers*/ undefined,
757+
createComputedPropertyName(createLiteral(1)),
758+
/*questionToken*/ undefined,
759+
createKeywordTypeNode(SyntaxKind.AnyKeyword),
760+
/*initializer*/ undefined);
761+
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
762+
});
763+
}
764+
{
765+
const text = `
766+
interface A {
767+
x()
768+
}
769+
`
770+
runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
771+
const newNode = createProperty(
772+
/*decorators*/ undefined,
773+
/*modifiers*/ undefined,
774+
createComputedPropertyName(createLiteral(1)),
775+
/*questionToken*/ undefined,
776+
createKeywordTypeNode(SyntaxKind.AnyKeyword),
777+
/*initializer*/ undefined);
778+
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
779+
});
780+
}
781+
{
782+
const text = `
783+
let x = foo
784+
`
785+
runSingleFileTest("insertNodeInStatementListAfterNodeWithoutSeparator1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
786+
const newNode = createStatement(createParen(createLiteral(1)));
787+
changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), newNode, { suffix: newLineCharacter });
788+
});
789+
}
712790
});
713791
}

src/lib/dom.iterable.d.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,53 @@ interface DOMTokenList {
55
}
66

77
interface NodeList {
8+
9+
10+
/**
11+
* Returns an array of key, value pairs for every entry in the list
12+
*/
13+
entries(): IterableIterator<[number, Node]>;
14+
/**
15+
* Performs the specified action for each node in an list.
16+
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the list.
17+
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
18+
*/
19+
forEach(callbackfn: (value: Node, index: number, listObj: NodeList) => void, thisArg?: any): void;
20+
/**
21+
* Returns an list of keys in the list
22+
*/
23+
keys(): IterableIterator<number>;
24+
25+
/**
26+
* Returns an list of values in the list
27+
*/
28+
values(): IterableIterator<Node>;
29+
30+
831
[Symbol.iterator](): IterableIterator<Node>
932
}
1033

1134
interface NodeListOf<TNode extends Node> {
35+
36+
/**
37+
* Returns an array of key, value pairs for every entry in the list
38+
*/
39+
entries(): IterableIterator<[number, TNode]>;
40+
41+
/**
42+
* Performs the specified action for each node in an list.
43+
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the list.
44+
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
45+
*/
46+
forEach(callbackfn: (value: TNode, index: number, listObj: NodeListOf<TNode>) => void, thisArg?: any): void;
47+
/**
48+
* Returns an list of keys in the list
49+
*/
50+
keys(): IterableIterator<number>;
51+
/**
52+
* Returns an list of values in the list
53+
*/
54+
values(): IterableIterator<TNode>;
55+
1256
[Symbol.iterator](): IterableIterator<TNode>
1357
}

src/services/textChanges.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,31 @@ namespace ts.textChanges {
253253
}
254254

255255
public insertNodeAfter(sourceFile: SourceFile, after: Node, newNode: Node, options: InsertNodeOptions & ConfigurableEnd = {}) {
256+
if ((isStatementButNotDeclaration(after)) ||
257+
after.kind === SyntaxKind.PropertyDeclaration ||
258+
after.kind === SyntaxKind.PropertySignature ||
259+
after.kind === SyntaxKind.MethodSignature) {
260+
// check if previous statement ends with semicolon
261+
// if not - insert semicolon to preserve the code from changing the meaning due to ASI
262+
if (sourceFile.text.charCodeAt(after.end - 1) !== CharacterCodes.semicolon) {
263+
this.changes.push({
264+
sourceFile,
265+
options: {},
266+
range: { pos: after.end, end: after.end },
267+
node: createToken(SyntaxKind.SemicolonToken)
268+
})
269+
}
270+
}
256271
const endPosition = getAdjustedEndPosition(sourceFile, after, options);
257272
this.changes.push({ sourceFile, options, useIndentationFromFile: true, node: newNode, range: { pos: endPosition, end: endPosition } });
258273
return this;
259274
}
260275

276+
/**
277+
* This function should be used to insert nodes in lists when nodes don't carry separators as the part of the node range,
278+
* i.e. arguments in arguments lists, parameters in parameter lists etc. Statements or class elements are different in sense that
279+
* for them separators are treated as the part of the node.
280+
*/
261281
public insertNodeInListAfter(sourceFile: SourceFile, after: Node, newNode: Node) {
262282
const containingList = formatting.SmartIndenter.getContainingList(after, sourceFile);
263283
if (!containingList) {
@@ -463,10 +483,7 @@ namespace ts.textChanges {
463483

464484
private static normalize(changes: Change[]) {
465485
// order changes by start position
466-
const normalized = changes
467-
.map((c, i) => ({ c, i }))
468-
.sort(({ c: a, i: i1 }, { c: b, i: i2 }) => (a.range.pos - b.range.pos) || i1 - i2)
469-
.map(({ c }) => c);
486+
const normalized = stableSort(changes, (a, b) => a.range.pos - b.range.pos);
470487
// verify that end position of the change is less than start position of the next change
471488
for (let i = 0; i < normalized.length - 2; i++) {
472489
Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos);

src/services/utilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1384,7 +1384,7 @@ namespace ts {
13841384
// First token is the open curly, this is where we want to put the 'super' call.
13851385
return constructor.body.getFirstToken(sourceFile);
13861386
}
1387-
1387+
13881388
export function getOpenBraceOfClassLike(declaration: ClassLikeDeclaration, sourceFile: SourceFile) {
13891389
return getTokenAtPosition(sourceFile, declaration.members.pos - 1);
13901390
}

tests/baselines/reference/textChanges/insertNodeAfterInClass1.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ class A {
77
===MODIFIED===
88

99
class A {
10-
x
10+
x;
1111
a: boolean;
1212
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
===ORIGINAL===
2+
3+
class A {
4+
x = foo
5+
}
6+
7+
===MODIFIED===
8+
9+
class A {
10+
x = foo;
11+
[1]: any;
12+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
===ORIGINAL===
2+
3+
class A {
4+
x() {
5+
}
6+
}
7+
8+
===MODIFIED===
9+
10+
class A {
11+
x() {
12+
}
13+
[1]: any;
14+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
===ORIGINAL===
2+
3+
interface A {
4+
x
5+
}
6+
7+
===MODIFIED===
8+
9+
interface A {
10+
x;
11+
[1]: any;
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
===ORIGINAL===
2+
3+
interface A {
4+
x()
5+
}
6+
7+
===MODIFIED===
8+
9+
interface A {
10+
x();
11+
[1]: any;
12+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
===ORIGINAL===
2+
3+
let x = foo
4+
5+
===MODIFIED===
6+
7+
let x = foo;
8+
(1);

0 commit comments

Comments
 (0)