Skip to content

Commit cd19a89

Browse files
committed
add getListByPosition
1 parent d7f1935 commit cd19a89

File tree

1 file changed

+69
-44
lines changed

1 file changed

+69
-44
lines changed

src/services/formatting/smartIndenter.ts

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -315,60 +315,85 @@ namespace ts.formatting {
315315
return false;
316316
}
317317

318+
function getListIfVisualStartEndIsInListRange(list: NodeArray<Node> | undefined, start: number, end: number, node: Node) {
319+
return list && rangeContainsVisualStartEnd(list) ? list : undefined;
320+
321+
// Assumes a list is wrapped by list tokens
322+
function rangeContainsVisualStartEnd(textRange: TextRange): boolean {
323+
const children = node.getChildren();
324+
for (let i = 1; i < children.length - 1; i++) {
325+
if (children[i].pos === textRange.pos && children[i].end === textRange.end) {
326+
return rangeContainsStartEnd({ pos: children[i - 1].end, end: children[i + 1].end - children[i + 1].getWidth() }, start, end);
327+
}
328+
}
329+
return rangeContainsStartEnd(textRange, start, end);
330+
}
331+
}
332+
318333
function getListIfStartEndIsInListRange(list: NodeArray<Node> | undefined, start: number, end: number) {
319334
return list && rangeContainsStartEnd(list, start, end) ? list : undefined;
320335
}
321336

322337
export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray<Node> | undefined {
323338
if (node.parent) {
324-
const { end } = node;
325-
switch (node.parent.kind) {
326-
case SyntaxKind.TypeReference:
327-
return getListIfStartEndIsInListRange((<TypeReferenceNode>node.parent).typeArguments, node.getStart(sourceFile), end);
328-
case SyntaxKind.ObjectLiteralExpression:
329-
return (<ObjectLiteralExpression>node.parent).properties;
330-
case SyntaxKind.ArrayLiteralExpression:
331-
return (<ArrayLiteralExpression>node.parent).elements;
332-
case SyntaxKind.FunctionDeclaration:
333-
case SyntaxKind.FunctionExpression:
334-
case SyntaxKind.ArrowFunction:
335-
case SyntaxKind.MethodDeclaration:
336-
case SyntaxKind.MethodSignature:
337-
case SyntaxKind.CallSignature:
338-
case SyntaxKind.Constructor:
339-
case SyntaxKind.ConstructorType:
340-
case SyntaxKind.ConstructSignature: {
341-
const start = node.getStart(sourceFile);
342-
return getListIfStartEndIsInListRange((<SignatureDeclaration>node.parent).typeParameters, start, end) ||
343-
getListIfStartEndIsInListRange((<SignatureDeclaration>node.parent).parameters, start, end);
344-
}
345-
case SyntaxKind.ClassDeclaration:
346-
case SyntaxKind.ClassExpression:
347-
case SyntaxKind.InterfaceDeclaration:
348-
case SyntaxKind.TypeAliasDeclaration:
349-
case SyntaxKind.JSDocTemplateTag: {
350-
const { typeParameters } = <ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag>node.parent;
351-
return getListIfStartEndIsInListRange(typeParameters, node.getStart(sourceFile), end);
352-
}
353-
case SyntaxKind.NewExpression:
354-
case SyntaxKind.CallExpression: {
355-
const start = node.getStart(sourceFile);
356-
return getListIfStartEndIsInListRange((<CallExpression | NewExpression>node.parent).typeArguments, start, end) ||
357-
getListIfStartEndIsInListRange((<CallExpression | NewExpression>node.parent).arguments, start, end);
358-
}
359-
case SyntaxKind.VariableDeclarationList:
360-
return getListIfStartEndIsInListRange((<VariableDeclarationList>node.parent).declarations, node.getStart(sourceFile), end);
361-
case SyntaxKind.NamedImports:
362-
case SyntaxKind.NamedExports:
363-
return getListIfStartEndIsInListRange((<NamedImportsOrExports>node.parent).elements, node.getStart(sourceFile), end);
364-
case SyntaxKind.ObjectBindingPattern:
365-
case SyntaxKind.ArrayBindingPattern:
366-
return getListIfStartEndIsInListRange((<ObjectBindingPattern | ArrayBindingPattern>node.parent).elements, node.getStart(sourceFile), end);
367-
}
339+
return getListByRange(node.getStart(sourceFile), node.getEnd(), node.parent);
368340
}
369341
return undefined;
370342
}
371343

344+
function getListByPosition(pos: number, node: Node): NodeArray<Node> | undefined {
345+
if (!node) {
346+
return;
347+
}
348+
return getListByRange(pos, pos, node);
349+
}
350+
351+
function getListByRange(start: number, end: number, node: Node): NodeArray<Node> | undefined {
352+
switch (node.kind) {
353+
case SyntaxKind.TypeReference:
354+
return getListIfVisualStartEndIsInListRange((<TypeReferenceNode>node).typeArguments, start, end, node);
355+
case SyntaxKind.ObjectLiteralExpression:
356+
return getListIfVisualStartEndIsInListRange((<ObjectLiteralExpression>node).properties, start, end, node);
357+
case SyntaxKind.ArrayLiteralExpression:
358+
return getListIfVisualStartEndIsInListRange((<ArrayLiteralExpression>node).elements, start, end, node);
359+
case SyntaxKind.TypeLiteral:
360+
return getListIfVisualStartEndIsInListRange((<TypeLiteralNode>node).members, start, end, node);
361+
case SyntaxKind.FunctionDeclaration:
362+
case SyntaxKind.FunctionExpression:
363+
case SyntaxKind.ArrowFunction:
364+
case SyntaxKind.MethodDeclaration:
365+
case SyntaxKind.MethodSignature:
366+
case SyntaxKind.CallSignature:
367+
case SyntaxKind.Constructor:
368+
case SyntaxKind.ConstructorType:
369+
case SyntaxKind.ConstructSignature: {
370+
return getListIfVisualStartEndIsInListRange((<SignatureDeclaration>node).typeParameters, start, end, node) ||
371+
getListIfVisualStartEndIsInListRange((<SignatureDeclaration>node).parameters, start, end, node);
372+
}
373+
case SyntaxKind.ClassDeclaration:
374+
case SyntaxKind.ClassExpression:
375+
case SyntaxKind.InterfaceDeclaration:
376+
case SyntaxKind.TypeAliasDeclaration:
377+
case SyntaxKind.JSDocTemplateTag: {
378+
const { typeParameters } = <ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag>node;
379+
return getListIfStartEndIsInListRange(typeParameters, start, end);
380+
}
381+
case SyntaxKind.NewExpression:
382+
case SyntaxKind.CallExpression: {
383+
return getListIfVisualStartEndIsInListRange((<CallExpression>node).typeArguments, start, end, node) ||
384+
getListIfVisualStartEndIsInListRange((<CallExpression>node).arguments, start, end, node);
385+
}
386+
case SyntaxKind.VariableDeclarationList:
387+
return getListIfStartEndIsInListRange((<VariableDeclarationList>node).declarations, start, end);
388+
case SyntaxKind.NamedImports:
389+
case SyntaxKind.NamedExports:
390+
return getListIfVisualStartEndIsInListRange((<NamedImportsOrExports>node).elements, start, end, node);
391+
case SyntaxKind.ObjectBindingPattern:
392+
case SyntaxKind.ArrayBindingPattern:
393+
return getListIfVisualStartEndIsInListRange((<ObjectBindingPattern | ArrayBindingPattern>node).elements, start, end, node);
394+
}
395+
}
396+
372397
function getActualIndentationForListItem(node: Node, sourceFile: SourceFile, options: EditorSettings): number {
373398
const containingList = getContainingList(node, sourceFile);
374399
if (containingList) {

0 commit comments

Comments
 (0)