Skip to content

Commit bc4e1ea

Browse files
committed
feat(formatGenerator): added support for format using generators
1 parent 6e702e4 commit bc4e1ea

File tree

2 files changed

+40
-12
lines changed

2 files changed

+40
-12
lines changed

src/impl/format.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ import { createScanner } from './scanner';
99
import { cachedSpaces, cachedBreakLinesWithSpaces, supportedEols, SupportedEOL } from './string-intern';
1010

1111
export function format(documentText: string, range: Range | undefined, options: FormattingOptions): Edit[] {
12+
const operations: Edit[] = [];
13+
14+
for (const edit of formatGenerator(documentText, range, options)) {
15+
operations.push(edit);
16+
}
17+
18+
return operations;
19+
}
20+
21+
export function* formatGenerator(documentText: string, range: Range | undefined, options: FormattingOptions): Generator<Edit, void, void> {
1222
let initialIndentLevel: number;
1323
let formatText: string;
1424
let formatTextStart: number;
@@ -85,24 +95,22 @@ export function format(documentText: string, range: Range | undefined, options:
8595
hasError = token === SyntaxKind.Unknown || scanner.getTokenError() !== ScanError.None;
8696
return token;
8797
}
88-
const editOperations: Edit[] = [];
89-
function addEdit(text: string, startOffset: number, endOffset: number) {
90-
if (!hasError && (!range || (startOffset < rangeEnd && endOffset > rangeStart)) && documentText.substring(startOffset, endOffset) !== text) {
91-
editOperations.push({ offset: startOffset, length: endOffset - startOffset, content: text });
92-
}
93-
}
94-
98+
const shouldAddEdit = (text: string, startOffset: number, endOffset: number) => !hasError && (!range || (startOffset < rangeEnd && endOffset > rangeStart)) && documentText.substring(startOffset, endOffset) !== text
99+
// { offset: startOffset, length: endOffset - startOffset, content: text }
95100
let firstToken = scanNext();
96101
if (options.keepLines && numberLineBreaks > 0) {
97-
addEdit(repeat(eol, numberLineBreaks), 0, 0);
102+
const text = repeat(eol, numberLineBreaks);
103+
if (shouldAddEdit(text, 0, 0))
104+
yield { offset: 0, length: 0, content: text };
98105
}
99106

100107
if (firstToken !== SyntaxKind.EOF) {
101108
let firstTokenStart = scanner.getTokenOffset() + formatTextStart;
102109
let initialIndent = (indentValue.length * initialIndentLevel < 20) && options.insertSpaces
103110
? cachedSpaces[indentValue.length * initialIndentLevel]
104111
: repeat(indentValue, initialIndentLevel);
105-
addEdit(initialIndent, formatTextStart, firstTokenStart);
112+
if (shouldAddEdit(initialIndent, formatTextStart, firstTokenStart))
113+
yield { offset: formatTextStart, length: firstTokenStart - formatTextStart, content: initialIndent };
106114
}
107115

108116
while (firstToken !== SyntaxKind.EOF) {
@@ -114,7 +122,9 @@ export function format(documentText: string, range: Range | undefined, options:
114122

115123
while (numberLineBreaks === 0 && (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia)) {
116124
let commentTokenStart = scanner.getTokenOffset() + formatTextStart;
117-
addEdit(cachedSpaces[1], firstTokenEnd, commentTokenStart);
125+
if (shouldAddEdit(cachedSpaces[1], firstTokenEnd, commentTokenStart))
126+
yield { offset: firstTokenEnd, length: commentTokenStart - firstTokenEnd, content: cachedSpaces[1] };
127+
118128
firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
119129
needsLineBreak = secondToken === SyntaxKind.LineCommentTrivia;
120130
replaceContent = needsLineBreak ? newLinesAndIndent() : '';
@@ -211,10 +221,10 @@ export function format(documentText: string, range: Range | undefined, options:
211221
}
212222
}
213223
const secondTokenStart = scanner.getTokenOffset() + formatTextStart;
214-
addEdit(replaceContent, firstTokenEnd, secondTokenStart);
224+
if (shouldAddEdit(replaceContent, firstTokenEnd, secondTokenStart))
225+
yield { offset: firstTokenEnd, length: secondTokenStart - firstTokenEnd, content: replaceContent };
215226
firstToken = secondToken;
216227
}
217-
return editOperations;
218228
}
219229

220230
function repeat(s: string, count: number): string {

src/main.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,11 @@ export interface JSONVisitor {
305305
*/
306306
export type EditResult = Edit[];
307307

308+
/**
309+
* See more {@link EditResult}
310+
*/
311+
export type EditGeneratorResult = Generator<Edit, void, void>;
312+
308313
/**
309314
* Represents a text modification
310315
*/
@@ -376,6 +381,19 @@ export function format(documentText: string, range: Range | undefined, options:
376381
return formatter.format(documentText, range, options);
377382
}
378383

384+
/**
385+
* Computes the edit operations needed to format a JSON document.
386+
*
387+
* @param documentText The input text
388+
* @param range The range to format or `undefined` to format the full content
389+
* @param options The formatting options
390+
* @returns The edit operations describing the formatting changes to the original document following the format described in {@linkcode EditResult}.
391+
* To apply the edit operations to the input, use {@linkcode applyEdits}.
392+
*/
393+
export function formatGenerator(documentText: string, range: Range | undefined, options: FormattingOptions): EditGeneratorResult {
394+
return formatter.formatGenerator(documentText, range, options);
395+
}
396+
379397
/**
380398
* Options used by {@linkcode modify} when computing the modification edit operations
381399
*/

0 commit comments

Comments
 (0)