1
1
/* @internal */
2
2
namespace ts . OutliningElementsCollector {
3
+ const collapseText = "..." ;
4
+ const maxDepth = 20 ;
5
+
3
6
export function collectElements ( sourceFile : SourceFile , cancellationToken : CancellationToken ) : OutliningSpan [ ] {
4
7
const elements : OutliningSpan [ ] = [ ] ;
5
- const collapseText = "..." ;
8
+ let depth = 0 ;
6
9
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 ) {
8
15
if ( hintSpanNode && startElement && endElement ) {
9
16
const span : OutliningSpan = {
10
- textSpan : createTextSpanFromBounds ( startElement . pos , endElement . end ) ,
17
+ textSpan : createTextSpanFromBounds ( useFullStart ? startElement . getFullStart ( ) : startElement . getStart ( ) , endElement . getEnd ( ) ) ,
11
18
hintSpan : createTextSpanFromNode ( hintSpanNode , sourceFile ) ,
12
19
bannerText : collapseText ,
13
20
autoCollapse,
@@ -82,8 +89,6 @@ namespace ts.OutliningElementsCollector {
82
89
return isFunctionBlock ( node ) && node . parent . kind !== SyntaxKind . ArrowFunction ;
83
90
}
84
91
85
- let depth = 0 ;
86
- const maxDepth = 20 ;
87
92
function walk ( n : Node ) : void {
88
93
cancellationToken . throwIfCancellationRequested ( ) ;
89
94
if ( depth > maxDepth ) {
@@ -113,21 +118,21 @@ namespace ts.OutliningElementsCollector {
113
118
parent . kind === SyntaxKind . WithStatement ||
114
119
parent . kind === SyntaxKind . CatchClause ) {
115
120
116
- addOutliningSpan ( parent , openBrace , closeBrace , autoCollapse ( n ) ) ;
121
+ addOutliningSpan ( parent , openBrace , closeBrace , autoCollapse ( n ) , /*useFullStart*/ true ) ;
117
122
break ;
118
123
}
119
124
120
125
if ( parent . kind === SyntaxKind . TryStatement ) {
121
126
// Could be the try-block, or the finally-block.
122
127
const tryStatement = < TryStatement > parent ;
123
128
if ( tryStatement . tryBlock === n ) {
124
- addOutliningSpan ( parent , openBrace , closeBrace , autoCollapse ( n ) ) ;
129
+ addOutliningSpan ( parent , openBrace , closeBrace , autoCollapse ( n ) , /*useFullStart*/ true ) ;
125
130
break ;
126
131
}
127
132
else if ( tryStatement . finallyBlock === n ) {
128
133
const finallyKeyword = findChildOfKind ( tryStatement , SyntaxKind . FinallyKeyword , sourceFile ) ;
129
134
if ( finallyKeyword ) {
130
- addOutliningSpan ( finallyKeyword , openBrace , closeBrace , autoCollapse ( n ) ) ;
135
+ addOutliningSpan ( finallyKeyword , openBrace , closeBrace , autoCollapse ( n ) , /*useFullStart*/ true ) ;
131
136
break ;
132
137
}
133
138
}
@@ -151,31 +156,35 @@ namespace ts.OutliningElementsCollector {
151
156
case SyntaxKind . ModuleBlock : {
152
157
const openBrace = findChildOfKind ( n , SyntaxKind . OpenBraceToken , sourceFile ) ;
153
158
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 ) ;
155
160
break ;
156
161
}
157
162
case SyntaxKind . ClassDeclaration :
158
163
case SyntaxKind . InterfaceDeclaration :
159
164
case SyntaxKind . EnumDeclaration :
160
- case SyntaxKind . ObjectLiteralExpression :
161
165
case SyntaxKind . CaseBlock : {
162
166
const openBrace = findChildOfKind ( n , SyntaxKind . OpenBraceToken , sourceFile ) ;
163
167
const closeBrace = findChildOfKind ( n , SyntaxKind . CloseBraceToken , sourceFile ) ;
164
- addOutliningSpan ( n , openBrace , closeBrace , autoCollapse ( n ) ) ;
168
+ addOutliningSpan ( n , openBrace , closeBrace , autoCollapse ( n ) , /*useFullStart*/ true ) ;
165
169
break ;
166
170
}
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 ;
167
179
case SyntaxKind . ArrayLiteralExpression :
168
180
const openBracket = findChildOfKind ( n , SyntaxKind . OpenBracketToken , sourceFile ) ;
169
181
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 ) ) ;
171
183
break ;
172
184
}
173
185
depth ++ ;
174
186
forEachChild ( n , walk ) ;
175
187
depth -- ;
176
188
}
177
-
178
- walk ( sourceFile ) ;
179
- return elements ;
180
189
}
181
190
}
0 commit comments