Add rules for expanding selection to sibling nodes
This commit is contained in:
parent
0f7bc02892
commit
70e2672ab3
2 changed files with 74 additions and 44 deletions
|
@ -13,9 +13,9 @@ namespace ts.SelectionRange {
|
|||
const children = parentNode.getChildren(sourceFile);
|
||||
if (!children.length) break;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const prevNode: Node | undefined = children[i - 1];
|
||||
let prevNode: Node | undefined = children[i - 1];
|
||||
const node: Node = children[i];
|
||||
const nextNode: Node | undefined = children[i + 1];
|
||||
let nextNode: Node | undefined = children[i + 1];
|
||||
if (node.getStart(sourceFile) > pos) {
|
||||
break outer;
|
||||
}
|
||||
|
@ -30,6 +30,26 @@ namespace ts.SelectionRange {
|
|||
break;
|
||||
}
|
||||
|
||||
const siblingExpansionRule = getSiblingExpansionRule(parentNode);
|
||||
let expansionCandidate: SyntaxKind | [SyntaxKind, SyntaxKind] | undefined;
|
||||
while ((prevNode || nextNode) && (expansionCandidate = siblingExpansionRule.shift())) {
|
||||
if (isArray(expansionCandidate)
|
||||
&& prevNode && prevNode.kind === expansionCandidate[0]
|
||||
&& nextNode && nextNode.kind === expansionCandidate[1]) {
|
||||
pushSelectionRange(prevNode.getStart(), nextNode.getEnd());
|
||||
prevNode = children[children.indexOf(prevNode) - 1];
|
||||
nextNode = children[children.indexOf(nextNode) + 1];
|
||||
}
|
||||
else if (prevNode && prevNode.kind === expansionCandidate) {
|
||||
pushSelectionRange(prevNode.getStart(), node.getEnd());
|
||||
prevNode = children[children.indexOf(prevNode) - 1];
|
||||
}
|
||||
else if (nextNode && nextNode.kind === expansionCandidate) {
|
||||
pushSelectionRange(node.getStart(), nextNode.getEnd());
|
||||
nextNode = children[children.indexOf(nextNode) + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// Synthesize a stop for '${ ... }' since '${' and '}' actually belong to siblings.
|
||||
if (isTemplateSpan(parentNode) && nextNode && isTemplateMiddleOrTemplateTail(nextNode)) {
|
||||
const start = node.getFullStart() - "${".length;
|
||||
|
@ -103,15 +123,24 @@ namespace ts.SelectionRange {
|
|||
}
|
||||
}
|
||||
|
||||
// function getSiblingExpansionRule<T extends Node>(parentNode: T): (SyntaxKind | SyntaxKind[])[] | undefined {
|
||||
// switch (parentNode.kind) {
|
||||
// case SyntaxKind.BindingElement: return [SyntaxKind.Identifier, SyntaxKind.DotDotDotToken];
|
||||
// case SyntaxKind.Parameter: return [SyntaxKind.Identifier, SyntaxKind.DotDotDotToken, SyntaxKind.QuestionToken];
|
||||
// case SyntaxKind.PropertySignature: return [SyntaxKind.Identifier, SyntaxKind.QuestionToken, SyntaxKind.SyntaxList];
|
||||
// case SyntaxKind.ElementAccessExpression: return [[SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken]];
|
||||
// case SyntaxKind.IndexedAccessType: return [[SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken]];
|
||||
// }
|
||||
// }
|
||||
function getSiblingExpansionRule<T extends Node>(parentNode: T): (SyntaxKind | [SyntaxKind, SyntaxKind])[] {
|
||||
switch (parentNode.kind) {
|
||||
case SyntaxKind.BindingElement: return [SyntaxKind.Identifier, SyntaxKind.DotDotDotToken];
|
||||
case SyntaxKind.Parameter: return [SyntaxKind.Identifier, SyntaxKind.DotDotDotToken, SyntaxKind.QuestionToken];
|
||||
case SyntaxKind.PropertySignature: return [SyntaxKind.Identifier, SyntaxKind.QuestionToken, SyntaxKind.SyntaxList];
|
||||
case SyntaxKind.ElementAccessExpression: return [[SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken]];
|
||||
case SyntaxKind.MappedType: return [
|
||||
SyntaxKind.TypeParameter,
|
||||
[SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken],
|
||||
SyntaxKind.MinusToken,
|
||||
SyntaxKind.PlusToken,
|
||||
SyntaxKind.ReadonlyKeyword,
|
||||
SyntaxKind.MinusToken,
|
||||
SyntaxKind.PlusToken,
|
||||
];
|
||||
default: return [];
|
||||
}
|
||||
}
|
||||
|
||||
function getGroupBounds<T>(array: ArrayLike<T>, index: number, predicate: (element: T) => boolean): [number, number] {
|
||||
let first = index;
|
||||
|
|
|
@ -231,44 +231,45 @@ type X = {
|
|||
end: { line: 4, offset: 33 } },
|
||||
parent: allMembersUp } };
|
||||
|
||||
assert.deepEqual(locations, [
|
||||
{
|
||||
textSpan: { // foo
|
||||
assert.deepEqual(locations![0], {
|
||||
textSpan: { // foo
|
||||
start: { line: 3, offset: 5 },
|
||||
end: { line: 3, offset: 8 } },
|
||||
parent: {
|
||||
textSpan: { // foo?
|
||||
start: { line: 3, offset: 5 },
|
||||
end: { line: 3, offset: 8 } },
|
||||
end: { line: 3, offset: 9 } },
|
||||
parent: {
|
||||
textSpan: { // foo?
|
||||
textSpan: { // foo?: string;
|
||||
start: { line: 3, offset: 5 },
|
||||
end: { line: 3, offset: 9 } },
|
||||
parent: {
|
||||
textSpan: { // foo?: string;
|
||||
start: { line: 3, offset: 5 },
|
||||
end: { line: 3, offset: 18 } },
|
||||
parent: allMembersUp } } },
|
||||
{
|
||||
textSpan: { // readonly
|
||||
start: { line: 4, offset: 5 },
|
||||
end: { line: 4, offset: 13 } },
|
||||
parent: readonlyBarUp },
|
||||
{
|
||||
textSpan: { // bar
|
||||
start: { line: 4, offset: 14 },
|
||||
end: { line: 4, offset: 17 } },
|
||||
parent: readonlyBarUp },
|
||||
{
|
||||
textSpan: { // number
|
||||
start: { line: 4, offset: 24 },
|
||||
end: { line: 3, offset: 18 } },
|
||||
parent: allMembersUp } } });
|
||||
|
||||
assert.deepEqual(locations![1], {
|
||||
textSpan: { // readonly
|
||||
start: { line: 4, offset: 5 },
|
||||
end: { line: 4, offset: 13 } },
|
||||
parent: readonlyBarUp });
|
||||
|
||||
assert.deepEqual(locations![2], {
|
||||
textSpan: { // bar
|
||||
start: { line: 4, offset: 14 },
|
||||
end: { line: 4, offset: 17 } },
|
||||
parent: readonlyBarUp });
|
||||
|
||||
assert.deepEqual(locations![3], {
|
||||
textSpan: { // number
|
||||
start: { line: 4, offset: 24 },
|
||||
end: { line: 4, offset: 30 } },
|
||||
parent: {
|
||||
textSpan: { // x: number
|
||||
start: { line: 4, offset: 21 },
|
||||
end: { line: 4, offset: 30 } },
|
||||
parent: {
|
||||
textSpan: { // x: number
|
||||
start: { line: 4, offset: 21 },
|
||||
end: { line: 4, offset: 30 } },
|
||||
parent: {
|
||||
textSpan: { // { x: number }
|
||||
start: { line: 4, offset: 19 },
|
||||
end: { line: 4, offset: 32 } },
|
||||
parent: readonlyBarUp } } },
|
||||
]);
|
||||
textSpan: { // { x: number }
|
||||
start: { line: 4, offset: 19 },
|
||||
end: { line: 4, offset: 32 } },
|
||||
parent: readonlyBarUp.parent } } });
|
||||
});
|
||||
|
||||
it("works for string literals and template strings", () => {
|
||||
|
|
Loading…
Reference in a new issue