Skip to content

Commit 45c62ac

Browse files
Merge pull request #17709 from uniqueiniquity/objectsInArray
Correct outlining spans for object and array literals in array
2 parents a14aaf4 + e6c1afb commit 45c62ac

File tree

2 files changed

+80
-15
lines changed

2 files changed

+80
-15
lines changed

src/services/outliningElementsCollector.ts

+24-15
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
/* @internal */
22
namespace ts.OutliningElementsCollector {
3+
const collapseText = "...";
4+
const maxDepth = 20;
5+
36
export function collectElements(sourceFile: SourceFile, cancellationToken: CancellationToken): OutliningSpan[] {
47
const elements: OutliningSpan[] = [];
5-
const collapseText = "...";
8+
let depth = 0;
69

7-
function addOutliningSpan(hintSpanNode: Node, startElement: Node, endElement: Node, autoCollapse: boolean) {
10+
walk(sourceFile);
11+
return elements;
12+
13+
/** If useFullStart is true, then the collapsing span includes leading whitespace, including linebreaks. */
14+
function addOutliningSpan(hintSpanNode: Node, startElement: Node, endElement: Node, autoCollapse: boolean, useFullStart: boolean) {
815
if (hintSpanNode && startElement && endElement) {
916
const span: OutliningSpan = {
10-
textSpan: createTextSpanFromBounds(startElement.pos, endElement.end),
17+
textSpan: createTextSpanFromBounds(useFullStart ? startElement.getFullStart() : startElement.getStart(), endElement.getEnd()),
1118
hintSpan: createTextSpanFromNode(hintSpanNode, sourceFile),
1219
bannerText: collapseText,
1320
autoCollapse,
@@ -82,8 +89,6 @@ namespace ts.OutliningElementsCollector {
8289
return isFunctionBlock(node) && node.parent.kind !== SyntaxKind.ArrowFunction;
8390
}
8491

85-
let depth = 0;
86-
const maxDepth = 20;
8792
function walk(n: Node): void {
8893
cancellationToken.throwIfCancellationRequested();
8994
if (depth > maxDepth) {
@@ -113,21 +118,21 @@ namespace ts.OutliningElementsCollector {
113118
parent.kind === SyntaxKind.WithStatement ||
114119
parent.kind === SyntaxKind.CatchClause) {
115120

116-
addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n));
121+
addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true);
117122
break;
118123
}
119124

120125
if (parent.kind === SyntaxKind.TryStatement) {
121126
// Could be the try-block, or the finally-block.
122127
const tryStatement = <TryStatement>parent;
123128
if (tryStatement.tryBlock === n) {
124-
addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n));
129+
addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true);
125130
break;
126131
}
127132
else if (tryStatement.finallyBlock === n) {
128133
const finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile);
129134
if (finallyKeyword) {
130-
addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n));
135+
addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true);
131136
break;
132137
}
133138
}
@@ -151,31 +156,35 @@ namespace ts.OutliningElementsCollector {
151156
case SyntaxKind.ModuleBlock: {
152157
const openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
153158
const closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
154-
addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n));
159+
addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true);
155160
break;
156161
}
157162
case SyntaxKind.ClassDeclaration:
158163
case SyntaxKind.InterfaceDeclaration:
159164
case SyntaxKind.EnumDeclaration:
160-
case SyntaxKind.ObjectLiteralExpression:
161165
case SyntaxKind.CaseBlock: {
162166
const openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
163167
const closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
164-
addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n));
168+
addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true);
165169
break;
166170
}
171+
// If the block has no leading keywords and is inside an array literal,
172+
// we only want to collapse the span of the block.
173+
// Otherwise, the collapsed section will include the end of the previous line.
174+
case SyntaxKind.ObjectLiteralExpression:
175+
const openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile);
176+
const closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile);
177+
addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ !isArrayLiteralExpression(n.parent));
178+
break;
167179
case SyntaxKind.ArrayLiteralExpression:
168180
const openBracket = findChildOfKind(n, SyntaxKind.OpenBracketToken, sourceFile);
169181
const closeBracket = findChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile);
170-
addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n));
182+
addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n), /*useFullStart*/ !isArrayLiteralExpression(n.parent));
171183
break;
172184
}
173185
depth++;
174186
forEachChild(n, walk);
175187
depth--;
176188
}
177-
178-
walk(sourceFile);
179-
return elements;
180189
}
181190
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/// <reference path="fourslash.ts"/>
2+
3+
// objects in x should generate outlining spans that do not render in VS
4+
//// const x =[| [
5+
//// [|{ a: 0 }|],
6+
//// [|{ b: 1 }|],
7+
//// [|{ c: 2 }|]
8+
//// ]|];
9+
////
10+
// objects in y should generate outlining spans that render as expected
11+
//// const y =[| [
12+
//// [|{
13+
//// a: 0
14+
//// }|],
15+
//// [|{
16+
//// b: 1
17+
//// }|],
18+
//// [|{
19+
//// c: 2
20+
//// }|]
21+
//// ]|];
22+
////
23+
// same behavior for nested arrays
24+
//// const w =[| [
25+
//// [|[ 0 ]|],
26+
//// [|[ 1 ]|],
27+
//// [|[ 2 ]|]
28+
//// ]|];
29+
////
30+
//// const z =[| [
31+
//// [|[
32+
//// 0
33+
//// ]|],
34+
//// [|[
35+
//// 1
36+
//// ]|],
37+
//// [|[
38+
//// 2
39+
//// ]|]
40+
//// ]|];
41+
////
42+
// multiple levels of nesting work as expected
43+
//// const z =[| [
44+
//// [|[
45+
//// [|{ hello: 0 }|]
46+
//// ]|],
47+
//// [|[
48+
//// [|{ hello: 3 }|]
49+
//// ]|],
50+
//// [|[
51+
//// [|{ hello: 5 }|],
52+
//// [|{ hello: 7 }|]
53+
//// ]|]
54+
//// ]|];
55+
56+
verify.outliningSpansInCurrentFile(test.ranges());

0 commit comments

Comments
 (0)