@@ -9,7 +9,35 @@ namespace ts.OutliningElementsCollector {
9
9
10
10
function addNodeOutliningSpans ( sourceFile : SourceFile , cancellationToken : CancellationToken , out : Push < OutliningSpan > ) : void {
11
11
let depthRemaining = 40 ;
12
- sourceFile . forEachChild ( function walk ( n ) {
12
+ let current = 0 ;
13
+ const statements = sourceFile . statements ;
14
+ const n = statements . length ;
15
+ while ( current < n ) {
16
+ while ( current < n && ! isAnyImportSyntax ( statements [ current ] ) ) {
17
+ visitNonImportNode ( statements [ current ] ) ;
18
+ current ++ ;
19
+ }
20
+ if ( current === n ) break ;
21
+ const firstImport = statements [ current ] ;
22
+ while ( current < n && isAnyImportSyntax ( statements [ current ] ) ) {
23
+ visitImportNode ( statements [ current ] as AnyImportSyntax , sourceFile , cancellationToken , out ) ;
24
+ current ++ ;
25
+ }
26
+ const lastImport = current < n ? statements [ current - 1 ] : statements [ n - 1 ] ;
27
+ if ( lastImport !== firstImport ) {
28
+ out . push ( createOutliningSpanFromBounds ( findChildOfKind ( firstImport , SyntaxKind . ImportKeyword , sourceFile ) ! . getStart ( sourceFile ) , lastImport . getEnd ( ) , OutliningSpanKind . Import ) ) ;
29
+ }
30
+ }
31
+
32
+ function visitImportNode ( node : AnyImportSyntax , sourceFile : SourceFile , cancellationToken : CancellationToken , out : Push < OutliningSpan > ) {
33
+ // Add outlining spans for comments if they exist
34
+ addOutliningForLeadingCommentsForNode ( node , sourceFile , cancellationToken , out ) ;
35
+ // Add outlining spans for the import statement itself if applicable
36
+ const span = getOutliningSpanForNode ( node , sourceFile ) ;
37
+ if ( span ) out . push ( span ) ;
38
+ }
39
+
40
+ function visitNonImportNode ( n : Node ) {
13
41
if ( depthRemaining === 0 ) return ;
14
42
cancellationToken . throwIfCancellationRequested ( ) ;
15
43
@@ -23,17 +51,17 @@ namespace ts.OutliningElementsCollector {
23
51
depthRemaining -- ;
24
52
if ( isIfStatement ( n ) && n . elseStatement && isIfStatement ( n . elseStatement ) ) {
25
53
// Consider an 'else if' to be on the same depth as the 'if'.
26
- walk ( n . expression ) ;
27
- walk ( n . thenStatement ) ;
54
+ visitNonImportNode ( n . expression ) ;
55
+ visitNonImportNode ( n . thenStatement ) ;
28
56
depthRemaining ++ ;
29
- walk ( n . elseStatement ) ;
57
+ visitNonImportNode ( n . elseStatement ) ;
30
58
depthRemaining -- ;
31
59
}
32
60
else {
33
- n . forEachChild ( walk ) ;
61
+ n . forEachChild ( visitNonImportNode ) ;
34
62
}
35
63
depthRemaining ++ ;
36
- } ) ;
64
+ }
37
65
}
38
66
39
67
function addRegionOutliningSpans ( sourceFile : SourceFile , out : Push < OutliningSpan > ) : void {
@@ -149,6 +177,9 @@ namespace ts.OutliningElementsCollector {
149
177
return spanForObjectOrArrayLiteral ( n ) ;
150
178
case SyntaxKind . ArrayLiteralExpression :
151
179
return spanForObjectOrArrayLiteral ( n , SyntaxKind . OpenBracketToken ) ;
180
+ case SyntaxKind . ImportDeclaration :
181
+ const importClause = ( n as ImportDeclaration ) . importClause ;
182
+ return importClause && importClause . namedBindings && importClause . namedBindings . kind !== SyntaxKind . NamespaceImport ? spanForNode ( importClause . namedBindings ) : undefined ;
152
183
}
153
184
154
185
function spanForObjectOrArrayLiteral ( node : Node , open : SyntaxKind . OpenBraceToken | SyntaxKind . OpenBracketToken = SyntaxKind . OpenBraceToken ) : OutliningSpan | undefined {
0 commit comments