Skip to content

Commit

Permalink
An additional parameter keepLines has been added into the formatting …
Browse files Browse the repository at this point in the history
…options which allows to keep the original line formatting
  • Loading branch information
aiday-mar committed Jul 7, 2022
1 parent 35d94cd commit 26a70df
Show file tree
Hide file tree
Showing 6 changed files with 324 additions and 28 deletions.
13 changes: 13 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp

// List of extensions which should be recommended for users of this workspace.
"recommendations": [

],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": [

]
}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
3.1.0 2022-07-07
==================
* Added the possibility to have multi-line formatting

3.0.0 2020-11-13
==================
* fixed API spec for `parseTree`. Can return `undefine` for empty input.
Expand Down
135 changes: 110 additions & 25 deletions src/impl/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export function format(documentText: string, range: Range | undefined, options:
}
let eol = getEOL(options, documentText);

let numberLineBreaks = 0;
let lineBreak = false;
let indentLevel = 0;
let indentValue: string;
Expand All @@ -48,14 +49,23 @@ export function format(documentText: string, range: Range | undefined, options:
let scanner = createScanner(formatText, false);
let hasError = false;

function newLineAndIndent(): string {
return eol + repeat(indentValue, initialIndentLevel + indentLevel);
function newLinesAndIndent(): string {
if (numberLineBreaks > 0) {
return repeat(eol, numberLineBreaks) + repeat(indentValue, initialIndentLevel + indentLevel);
} else {
return eol + repeat(indentValue, initialIndentLevel + indentLevel);
}
}

function scanNext(): SyntaxKind {
let token = scanner.scan();
numberLineBreaks = 0;
lineBreak = false;
while (token === SyntaxKind.Trivia || token === SyntaxKind.LineBreakTrivia) {
lineBreak = lineBreak || (token === SyntaxKind.LineBreakTrivia);
if (token === SyntaxKind.LineBreakTrivia && options.keepLines) {
numberLineBreaks += 1;
}
token = scanner.scan();
}
hasError = token === SyntaxKind.Unknown || scanner.getTokenError() !== ScanError.None;
Expand Down Expand Up @@ -88,76 +98,151 @@ export function format(documentText: string, range: Range | undefined, options:
addEdit(' ', firstTokenEnd, commentTokenStart);
firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
needsLineBreak = secondToken === SyntaxKind.LineCommentTrivia;
replaceContent = needsLineBreak ? newLineAndIndent() : '';
replaceContent = needsLineBreak ? newLinesAndIndent() : '';
secondToken = scanNext();
}

if (secondToken === SyntaxKind.CloseBraceToken) {
if (firstToken !== SyntaxKind.OpenBraceToken) {
if (options.keepLines) {
if (firstToken !== SyntaxKind.OpenBraceToken) { indentLevel--; };
if (lineBreak) {
replaceContent = newLinesAndIndent();
} else {
replaceContent = ' ';
}
} else if (!options.keepLines && firstToken !== SyntaxKind.OpenBraceToken){
indentLevel--;
replaceContent = newLineAndIndent();
replaceContent = newLinesAndIndent();
}
} else if (secondToken === SyntaxKind.CloseBracketToken) {
if (firstToken !== SyntaxKind.OpenBracketToken) {
if (options.keepLines) {
if(firstToken !== SyntaxKind.OpenBracketToken) {indentLevel--;};
if (lineBreak) {
replaceContent = newLinesAndIndent();
} else {
replaceContent = ' ';
}
}
else if (firstToken !== SyntaxKind.OpenBracketToken) {
indentLevel--;
replaceContent = newLineAndIndent();
replaceContent = newLinesAndIndent();
}
} else {

switch (firstToken) {
case SyntaxKind.OpenBracketToken:
case SyntaxKind.OpenBraceToken:
indentLevel++;
replaceContent = newLineAndIndent();
if (options.keepLines) {
if (lineBreak) {
replaceContent = newLinesAndIndent();
} else {
replaceContent = " ";
}
} else {
replaceContent = newLinesAndIndent();
}
break;
case SyntaxKind.CommaToken:
if(options.keepLines) {
if (lineBreak) {
replaceContent = newLinesAndIndent();
} else {
replaceContent = " ";
}
} else {
replaceContent = newLinesAndIndent();
}
break;
case SyntaxKind.LineCommentTrivia:
replaceContent = newLineAndIndent();
replaceContent = newLinesAndIndent();
break;
case SyntaxKind.BlockCommentTrivia:
if (lineBreak) {
replaceContent = newLineAndIndent();
replaceContent = newLinesAndIndent();
} else if (!needsLineBreak) {
// symbol following comment on the same line: keep on same line, separate with ' '
replaceContent = ' ';
}
break;
case SyntaxKind.ColonToken:
if (!needsLineBreak) {
replaceContent = ' ';
if (options.keepLines) {
if (lineBreak) {
replaceContent = newLinesAndIndent();
} else if (!needsLineBreak) {
replaceContent = ' ';
}
} else {
if (!needsLineBreak) {
replaceContent = ' ';
}
}
break;
case SyntaxKind.StringLiteral:
if (secondToken === SyntaxKind.ColonToken) {
if (!needsLineBreak) {
replaceContent = '';
if (options.keepLines) {
if (lineBreak) {
replaceContent = newLinesAndIndent();
} else {
if (secondToken === SyntaxKind.ColonToken) {
if (!needsLineBreak) {
replaceContent = '';
}
}
}
} else {
if (secondToken === SyntaxKind.ColonToken) {
if (!needsLineBreak) {
replaceContent = '';
}
}
break;
}
// fall through
break;
case SyntaxKind.NullKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.NumericLiteral:
case SyntaxKind.CloseBraceToken:
case SyntaxKind.CloseBracketToken:
if (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia) {
if (!needsLineBreak) {
replaceContent = ' ';
if (options.keepLines) {
if (lineBreak) {
replaceContent = newLinesAndIndent();
} else {
if (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia) {
if (!needsLineBreak) {
replaceContent = ' ';
}
} else if (secondToken !== SyntaxKind.CommaToken && secondToken !== SyntaxKind.EOF) {
hasError = true;
}
}
} else {
if (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia) {
if (!needsLineBreak) {
replaceContent = ' ';
}
} else if (secondToken !== SyntaxKind.CommaToken && secondToken !== SyntaxKind.EOF) {
hasError = true;
}
} else if (secondToken !== SyntaxKind.CommaToken && secondToken !== SyntaxKind.EOF) {
hasError = true;
}
break;
case SyntaxKind.Unknown:
hasError = true;
break;
}

if (lineBreak && (secondToken === SyntaxKind.LineCommentTrivia || secondToken === SyntaxKind.BlockCommentTrivia)) {
replaceContent = newLineAndIndent();
replaceContent = newLinesAndIndent();
}
}
if (secondToken === SyntaxKind.EOF) {
replaceContent = options.insertFinalNewline ? eol : '';
if (options.keepLines) {
if (lineBreak) {
replaceContent = newLinesAndIndent();
} else {
replaceContent = options.insertFinalNewline ? eol : '';
}
} else {
replaceContent = options.insertFinalNewline ? eol : '';
}
}
let secondTokenStart = scanner.getTokenOffset() + formatTextStart;
addEdit(replaceContent, firstTokenEnd, secondTokenStart);
Expand Down
4 changes: 4 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,10 @@ export interface FormattingOptions {
* If set, will add a new line at the end of the document.
*/
insertFinalNewline?: boolean;
/**
* If true, will keep line positions as is in the formatting
*/
keepLines?: boolean;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/test/edit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ suite('JSON - edits', () => {
let formattingOptions: FormattingOptions = {
insertSpaces: true,
tabSize: 2,
eol: '\n'
eol: '\n',
keepLines: false
};

let options: ModificationOptions = {
Expand Down
Loading

0 comments on commit 26a70df

Please sign in to comment.