11/* @internal */
22namespace 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}
0 commit comments