Skip to content

Commit 26a70df

Browse files
author
aiday-mar
committed
An additional parameter keepLines has been added into the formatting options which allows to keep the original line formatting
1 parent 35d94cd commit 26a70df

File tree

6 files changed

+324
-28
lines changed

6 files changed

+324
-28
lines changed

.vscode/extensions.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
3+
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
4+
5+
// List of extensions which should be recommended for users of this workspace.
6+
"recommendations": [
7+
8+
],
9+
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
10+
"unwantedRecommendations": [
11+
12+
]
13+
}

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
3.1.0 2022-07-07
2+
==================
3+
* Added the possibility to have multi-line formatting
4+
15
3.0.0 2020-11-13
26
==================
37
* fixed API spec for `parseTree`. Can return `undefine` for empty input.

src/impl/format.ts

Lines changed: 110 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export function format(documentText: string, range: Range | undefined, options:
3636
}
3737
let eol = getEOL(options, documentText);
3838

39+
let numberLineBreaks = 0;
3940
let lineBreak = false;
4041
let indentLevel = 0;
4142
let indentValue: string;
@@ -48,14 +49,23 @@ export function format(documentText: string, range: Range | undefined, options:
4849
let scanner = createScanner(formatText, false);
4950
let hasError = false;
5051

51-
function newLineAndIndent(): string {
52-
return eol + repeat(indentValue, initialIndentLevel + indentLevel);
52+
function newLinesAndIndent(): string {
53+
if (numberLineBreaks > 0) {
54+
return repeat(eol, numberLineBreaks) + repeat(indentValue, initialIndentLevel + indentLevel);
55+
} else {
56+
return eol + repeat(indentValue, initialIndentLevel + indentLevel);
57+
}
5358
}
59+
5460
function scanNext(): SyntaxKind {
5561
let token = scanner.scan();
62+
numberLineBreaks = 0;
5663
lineBreak = false;
5764
while (token === SyntaxKind.Trivia || token === SyntaxKind.LineBreakTrivia) {
5865
lineBreak = lineBreak || (token === SyntaxKind.LineBreakTrivia);
66+
if (token === SyntaxKind.LineBreakTrivia && options.keepLines) {
67+
numberLineBreaks += 1;
68+
}
5969
token = scanner.scan();
6070
}
6171
hasError = token === SyntaxKind.Unknown || scanner.getTokenError() !== ScanError.None;
@@ -88,76 +98,151 @@ export function format(documentText: string, range: Range | undefined, options:
8898
addEdit(' ', firstTokenEnd, commentTokenStart);
8999
firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
90100
needsLineBreak = secondToken === SyntaxKind.LineCommentTrivia;
91-
replaceContent = needsLineBreak ? newLineAndIndent() : '';
101+
replaceContent = needsLineBreak ? newLinesAndIndent() : '';
92102
secondToken = scanNext();
93103
}
94104

95105
if (secondToken === SyntaxKind.CloseBraceToken) {
96-
if (firstToken !== SyntaxKind.OpenBraceToken) {
106+
if (options.keepLines) {
107+
if (firstToken !== SyntaxKind.OpenBraceToken) { indentLevel--; };
108+
if (lineBreak) {
109+
replaceContent = newLinesAndIndent();
110+
} else {
111+
replaceContent = ' ';
112+
}
113+
} else if (!options.keepLines && firstToken !== SyntaxKind.OpenBraceToken){
97114
indentLevel--;
98-
replaceContent = newLineAndIndent();
115+
replaceContent = newLinesAndIndent();
99116
}
100117
} else if (secondToken === SyntaxKind.CloseBracketToken) {
101-
if (firstToken !== SyntaxKind.OpenBracketToken) {
118+
if (options.keepLines) {
119+
if(firstToken !== SyntaxKind.OpenBracketToken) {indentLevel--;};
120+
if (lineBreak) {
121+
replaceContent = newLinesAndIndent();
122+
} else {
123+
replaceContent = ' ';
124+
}
125+
}
126+
else if (firstToken !== SyntaxKind.OpenBracketToken) {
102127
indentLevel--;
103-
replaceContent = newLineAndIndent();
128+
replaceContent = newLinesAndIndent();
104129
}
105130
} else {
131+
106132
switch (firstToken) {
107133
case SyntaxKind.OpenBracketToken:
108134
case SyntaxKind.OpenBraceToken:
109135
indentLevel++;
110-
replaceContent = newLineAndIndent();
136+
if (options.keepLines) {
137+
if (lineBreak) {
138+
replaceContent = newLinesAndIndent();
139+
} else {
140+
replaceContent = " ";
141+
}
142+
} else {
143+
replaceContent = newLinesAndIndent();
144+
}
111145
break;
112146
case SyntaxKind.CommaToken:
147+
if(options.keepLines) {
148+
if (lineBreak) {
149+
replaceContent = newLinesAndIndent();
150+
} else {
151+
replaceContent = " ";
152+
}
153+
} else {
154+
replaceContent = newLinesAndIndent();
155+
}
156+
break;
113157
case SyntaxKind.LineCommentTrivia:
114-
replaceContent = newLineAndIndent();
158+
replaceContent = newLinesAndIndent();
115159
break;
116160
case SyntaxKind.BlockCommentTrivia:
117161
if (lineBreak) {
118-
replaceContent = newLineAndIndent();
162+
replaceContent = newLinesAndIndent();
119163
} else if (!needsLineBreak) {
120-
// symbol following comment on the same line: keep on same line, separate with ' '
121164
replaceContent = ' ';
122165
}
123166
break;
124167
case SyntaxKind.ColonToken:
125-
if (!needsLineBreak) {
126-
replaceContent = ' ';
168+
if (options.keepLines) {
169+
if (lineBreak) {
170+
replaceContent = newLinesAndIndent();
171+
} else if (!needsLineBreak) {
172+
replaceContent = ' ';
173+
}
174+
} else {
175+
if (!needsLineBreak) {
176+
replaceContent = ' ';
177+
}
127178
}
128179
break;
129180
case SyntaxKind.StringLiteral:
130-
if (secondToken === SyntaxKind.ColonToken) {
131-
if (!needsLineBreak) {
132-
replaceContent = '';
181+
if (options.keepLines) {
182+
if (lineBreak) {
183+
replaceContent = newLinesAndIndent();
184+
} else {
185+
if (secondToken === SyntaxKind.ColonToken) {
186+
if (!needsLineBreak) {
187+
replaceContent = '';
188+
}
189+
}
190+
}
191+
} else {
192+
if (secondToken === SyntaxKind.ColonToken) {
193+
if (!needsLineBreak) {
194+
replaceContent = '';
195+
}
133196
}
134-
break;
135197
}
136-
// fall through
198+
break;
137199
case SyntaxKind.NullKeyword:
138200
case SyntaxKind.TrueKeyword:
139201
case SyntaxKind.FalseKeyword:
140202
case SyntaxKind.NumericLiteral:
141203
case SyntaxKind.CloseBraceToken:
142204
case SyntaxKind.CloseBracketToken:
143-
if (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia) {
144-
if (!needsLineBreak) {
145-
replaceContent = ' ';
205+
if (options.keepLines) {
206+
if (lineBreak) {
207+
replaceContent = newLinesAndIndent();
208+
} else {
209+
if (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia) {
210+
if (!needsLineBreak) {
211+
replaceContent = ' ';
212+
}
213+
} else if (secondToken !== SyntaxKind.CommaToken && secondToken !== SyntaxKind.EOF) {
214+
hasError = true;
215+
}
216+
}
217+
} else {
218+
if (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia) {
219+
if (!needsLineBreak) {
220+
replaceContent = ' ';
221+
}
222+
} else if (secondToken !== SyntaxKind.CommaToken && secondToken !== SyntaxKind.EOF) {
223+
hasError = true;
146224
}
147-
} else if (secondToken !== SyntaxKind.CommaToken && secondToken !== SyntaxKind.EOF) {
148-
hasError = true;
149225
}
150226
break;
151227
case SyntaxKind.Unknown:
152228
hasError = true;
153229
break;
154230
}
231+
155232
if (lineBreak && (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia)) {
156-
replaceContent = newLineAndIndent();
233+
replaceContent = newLinesAndIndent();
157234
}
158235
}
159236
if (secondToken === SyntaxKind.EOF) {
160-
replaceContent = options.insertFinalNewline ? eol : '';
237+
if (options.keepLines) {
238+
if (lineBreak) {
239+
replaceContent = newLinesAndIndent();
240+
} else {
241+
replaceContent = options.insertFinalNewline ? eol : '';
242+
}
243+
} else {
244+
replaceContent = options.insertFinalNewline ? eol : '';
245+
}
161246
}
162247
let secondTokenStart = scanner.getTokenOffset() + formatTextStart;
163248
addEdit(replaceContent, firstTokenEnd, secondTokenStart);

src/main.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,10 @@ export interface FormattingOptions {
357357
* If set, will add a new line at the end of the document.
358358
*/
359359
insertFinalNewline?: boolean;
360+
/**
361+
* If true, will keep line positions as is in the formatting
362+
*/
363+
keepLines?: boolean;
360364
}
361365

362366
/**

src/test/edit.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ suite('JSON - edits', () => {
2626
let formattingOptions: FormattingOptions = {
2727
insertSpaces: true,
2828
tabSize: 2,
29-
eol: '\n'
29+
eol: '\n',
30+
keepLines: false
3031
};
3132

3233
let options: ModificationOptions = {

0 commit comments

Comments
 (0)