6
6
7
7
import { Range , FormattingOptions , Edit , SyntaxKind , ScanError } from '../main' ;
8
8
import { createScanner } from './scanner' ;
9
+ import { cachedSpaces , cachedBreakLinesWithSpaces , supportedEols , SupportedEOL } from './string-intern' ;
9
10
10
11
export function format ( documentText : string , range : Range | undefined , options : FormattingOptions ) : Edit [ ] {
11
12
let initialIndentLevel : number ;
@@ -35,26 +36,38 @@ export function format(documentText: string, range: Range | undefined, options:
35
36
rangeEnd = documentText . length ;
36
37
}
37
38
const eol = getEOL ( options , documentText ) ;
39
+ const eolFastPathSupported = supportedEols . includes ( eol as any ) ;
38
40
39
41
let numberLineBreaks = 0 ;
40
42
41
43
let indentLevel = 0 ;
42
44
let indentValue : string ;
43
45
if ( options . insertSpaces ) {
44
- indentValue = repeat ( ' ' , options . tabSize || 4 ) ;
46
+ indentValue = cachedSpaces [ options . tabSize || 4 ] ?? repeat ( cachedSpaces [ 1 ] , options . tabSize || 4 ) ;
45
47
} else {
46
48
indentValue = '\t' ;
47
49
}
50
+ const indentType = indentValue === '\t' ? '\t' : ' ' ;
48
51
49
52
let scanner = createScanner ( formatText , false ) ;
50
53
let hasError = false ;
51
54
52
55
function newLinesAndIndent ( ) : string {
53
56
if ( numberLineBreaks > 1 ) {
54
57
return repeat ( eol , numberLineBreaks ) + repeat ( indentValue , initialIndentLevel + indentLevel ) ;
55
- } else {
58
+ }
59
+
60
+ const amountOfSpaces = indentValue . length * ( initialIndentLevel + indentLevel ) ;
61
+
62
+ if ( ! eolFastPathSupported || amountOfSpaces > cachedBreakLinesWithSpaces [ indentType ] [ eol as SupportedEOL ] . length ) {
56
63
return eol + repeat ( indentValue , initialIndentLevel + indentLevel ) ;
57
64
}
65
+
66
+ if ( amountOfSpaces <= 0 ) {
67
+ return eol ;
68
+ }
69
+
70
+ return cachedBreakLinesWithSpaces [ indentType ] [ eol as SupportedEOL ] [ amountOfSpaces ] ;
58
71
}
59
72
60
73
function scanNext ( ) : SyntaxKind {
@@ -86,7 +99,9 @@ export function format(documentText: string, range: Range | undefined, options:
86
99
87
100
if ( firstToken !== SyntaxKind . EOF ) {
88
101
let firstTokenStart = scanner . getTokenOffset ( ) + formatTextStart ;
89
- let initialIndent = repeat ( indentValue , initialIndentLevel ) ;
102
+ let initialIndent = ( indentValue . length * initialIndentLevel < 20 ) && options . insertSpaces
103
+ ? cachedSpaces [ indentValue . length * initialIndentLevel ]
104
+ : repeat ( indentValue , initialIndentLevel ) ;
90
105
addEdit ( initialIndent , formatTextStart , firstTokenStart ) ;
91
106
}
92
107
@@ -99,7 +114,7 @@ export function format(documentText: string, range: Range | undefined, options:
99
114
100
115
while ( numberLineBreaks === 0 && ( secondToken === SyntaxKind . LineCommentTrivia || secondToken === SyntaxKind . BlockCommentTrivia ) ) {
101
116
let commentTokenStart = scanner . getTokenOffset ( ) + formatTextStart ;
102
- addEdit ( ' ' , firstTokenEnd , commentTokenStart ) ;
117
+ addEdit ( cachedSpaces [ 1 ] , firstTokenEnd , commentTokenStart ) ;
103
118
firstTokenEnd = scanner . getTokenOffset ( ) + scanner . getTokenLength ( ) + formatTextStart ;
104
119
needsLineBreak = secondToken === SyntaxKind . LineCommentTrivia ;
105
120
replaceContent = needsLineBreak ? newLinesAndIndent ( ) : '' ;
@@ -112,15 +127,15 @@ export function format(documentText: string, range: Range | undefined, options:
112
127
if ( options . keepLines && numberLineBreaks > 0 || ! options . keepLines && firstToken !== SyntaxKind . OpenBraceToken ) {
113
128
replaceContent = newLinesAndIndent ( ) ;
114
129
} else if ( options . keepLines ) {
115
- replaceContent = ' ' ;
130
+ replaceContent = cachedSpaces [ 1 ] ;
116
131
}
117
132
} else if ( secondToken === SyntaxKind . CloseBracketToken ) {
118
133
if ( firstToken !== SyntaxKind . OpenBracketToken ) { indentLevel -- ; } ;
119
134
120
135
if ( options . keepLines && numberLineBreaks > 0 || ! options . keepLines && firstToken !== SyntaxKind . OpenBracketToken ) {
121
136
replaceContent = newLinesAndIndent ( ) ;
122
137
} else if ( options . keepLines ) {
123
- replaceContent = ' ' ;
138
+ replaceContent = cachedSpaces [ 1 ] ;
124
139
}
125
140
} else {
126
141
switch ( firstToken ) {
@@ -130,14 +145,14 @@ export function format(documentText: string, range: Range | undefined, options:
130
145
if ( options . keepLines && numberLineBreaks > 0 || ! options . keepLines ) {
131
146
replaceContent = newLinesAndIndent ( ) ;
132
147
} else {
133
- replaceContent = ' ' ;
148
+ replaceContent = cachedSpaces [ 1 ] ;
134
149
}
135
150
break ;
136
151
case SyntaxKind . CommaToken :
137
152
if ( options . keepLines && numberLineBreaks > 0 || ! options . keepLines ) {
138
153
replaceContent = newLinesAndIndent ( ) ;
139
154
} else {
140
- replaceContent = ' ' ;
155
+ replaceContent = cachedSpaces [ 1 ] ;
141
156
}
142
157
break ;
143
158
case SyntaxKind . LineCommentTrivia :
@@ -147,14 +162,14 @@ export function format(documentText: string, range: Range | undefined, options:
147
162
if ( numberLineBreaks > 0 ) {
148
163
replaceContent = newLinesAndIndent ( ) ;
149
164
} else if ( ! needsLineBreak ) {
150
- replaceContent = ' ' ;
165
+ replaceContent = cachedSpaces [ 1 ] ;
151
166
}
152
167
break ;
153
168
case SyntaxKind . ColonToken :
154
169
if ( options . keepLines && numberLineBreaks > 0 ) {
155
170
replaceContent = newLinesAndIndent ( ) ;
156
171
} else if ( ! needsLineBreak ) {
157
- replaceContent = ' ' ;
172
+ replaceContent = cachedSpaces [ 1 ] ;
158
173
}
159
174
break ;
160
175
case SyntaxKind . StringLiteral :
@@ -174,7 +189,7 @@ export function format(documentText: string, range: Range | undefined, options:
174
189
replaceContent = newLinesAndIndent ( ) ;
175
190
} else {
176
191
if ( ( secondToken === SyntaxKind . LineCommentTrivia || secondToken === SyntaxKind . BlockCommentTrivia ) && ! needsLineBreak ) {
177
- replaceContent = ' ' ;
192
+ replaceContent = cachedSpaces [ 1 ] ;
178
193
} else if ( secondToken !== SyntaxKind . CommaToken && secondToken !== SyntaxKind . EOF ) {
179
194
hasError = true ;
180
195
}
@@ -216,7 +231,7 @@ function computeIndentLevel(content: string, options: FormattingOptions): number
216
231
const tabSize = options . tabSize || 4 ;
217
232
while ( i < content . length ) {
218
233
let ch = content . charAt ( i ) ;
219
- if ( ch === ' ' ) {
234
+ if ( ch === cachedSpaces [ 1 ] ) {
220
235
nChars ++ ;
221
236
} else if ( ch === '\t' ) {
222
237
nChars += tabSize ;
0 commit comments