From d053541e568579310562498cc9e0772033ffb7b6 Mon Sep 17 00:00:00 2001 From: fumer-fubotv <89787347+fumer-fubotv@users.noreply.github.com> Date: Tue, 2 Apr 2024 14:57:44 -0700 Subject: [PATCH 01/10] handle double-indent followed by double-outdent --- src/Formatter.spec.ts | 18 ++++++++++++++++++ src/formatters/IndentFormatter.ts | 23 +++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/Formatter.spec.ts b/src/Formatter.spec.ts index 6d6ed60..f147e0d 100644 --- a/src/Formatter.spec.ts +++ b/src/Formatter.spec.ts @@ -251,6 +251,24 @@ describe('Formatter', () => { end sub `); }); + + it('formats outdents', () => { + expect(formatter.format(undent` + temp = { + key_9: { env: ["any"], themes: ["any"], runtimeCheck: function() as boolean + return true + end function } + } + `, { + formatMultiLineObjectsAndArrays: false + })).to.equal(undent` + temp = { + key_9: { env: ["any"], themes: ["any"], runtimeCheck: function() as boolean + return true + end function } + } + `); + }); }); describe('formatMultiLineObjectsAndArrays', () => { diff --git a/src/formatters/IndentFormatter.ts b/src/formatters/IndentFormatter.ts index cc54164..8346e6d 100644 --- a/src/formatters/IndentFormatter.ts +++ b/src/formatters/IndentFormatter.ts @@ -59,6 +59,7 @@ export class IndentFormatter { let currentLineOffset = 0; let nextLineOffset = 0; let foundIndentorThisLine = false; + let foundUnIndentOnThisLine = false; for (let i = 0; i < lineTokens.length; i++) { let token = lineTokens[i]; @@ -90,6 +91,17 @@ export class IndentFormatter { continue; } + //skip indent for 'function'|'sub' used as type if another indent already exist in this line + if ( + CallableKeywordTokenKinds.includes(token.kind) && + //validate if its a function/sub call + nextNonWhitespaceToken.kind === TokenKind.LeftParen && + foundIndentorThisLine + ) { + parentIndentTokenKinds.push(token.kind); + continue; + } + //skip indent for single-line if statements let ifStatement = ifStatements.get(token); const endIfToken = this.getEndIfToken(ifStatement); @@ -151,6 +163,17 @@ export class IndentFormatter { } nextLineOffset--; + + if ( + [TokenKind.RightCurlyBrace].includes(token.kind) && + //if the line has already been unindented + (foundUnIndentOnThisLine) + ) { + continue; + } + + foundUnIndentOnThisLine = true; + if (foundIndentorThisLine === false) { currentLineOffset--; } From ffdbad7dd75f6ca52cb91a361945ca4ee7f19a63 Mon Sep 17 00:00:00 2001 From: fumer-fubotv <89787347+fumer-fubotv@users.noreply.github.com> Date: Wed, 3 Apr 2024 07:54:20 -0700 Subject: [PATCH 02/10] Solution extended to support more indent and outdent tokens --- src/formatters/IndentFormatter.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/formatters/IndentFormatter.ts b/src/formatters/IndentFormatter.ts index 8346e6d..ca6f852 100644 --- a/src/formatters/IndentFormatter.ts +++ b/src/formatters/IndentFormatter.ts @@ -93,7 +93,7 @@ export class IndentFormatter { //skip indent for 'function'|'sub' used as type if another indent already exist in this line if ( - CallableKeywordTokenKinds.includes(token.kind) && + IndentSpacerTokenKinds.includes(token.kind) && //validate if its a function/sub call nextNonWhitespaceToken.kind === TokenKind.LeftParen && foundIndentorThisLine @@ -164,10 +164,17 @@ export class IndentFormatter { nextLineOffset--; + let doubleIndentSkip = (token.kind === TokenKind.RightCurlyBrace || token.kind === TokenKind.RightSquareBracket) && + //next is closing square + nextNonWhitespaceToken && nextNonWhitespaceToken.kind === TokenKind.RightSquareBracket && + //both tokens are on the same line + token.range.start.line === nextNonWhitespaceToken.range.start.line; + if ( - [TokenKind.RightCurlyBrace].includes(token.kind) && - //if the line has already been unindented - (foundUnIndentOnThisLine) + OutdentSpacerTokenKinds.includes(token.kind) && + //if the line has already been outdented + (foundUnIndentOnThisLine) && + !doubleIndentSkip ) { continue; } @@ -180,14 +187,7 @@ export class IndentFormatter { parentIndentTokenKinds.pop(); //don't double un-indent if this is `[[...\n...]]` or `[{...\n...}]` - if ( - //is closing curly or square - (token.kind === TokenKind.RightCurlyBrace || token.kind === TokenKind.RightSquareBracket) && - //next is closing square - nextNonWhitespaceToken && nextNonWhitespaceToken.kind === TokenKind.RightSquareBracket && - //both tokens are on the same line - token.range.start.line === nextNonWhitespaceToken.range.start.line - ) { + if (doubleIndentSkip) { let opener = this.getOpeningToken( tokens, tokens.indexOf(nextNonWhitespaceToken), From bc8660ddd1ebc3d9b4ac264381dfff8f15242ed3 Mon Sep 17 00:00:00 2001 From: fumer-fubotv <89787347+fumer-fubotv@users.noreply.github.com> Date: Wed, 3 Apr 2024 08:20:24 -0700 Subject: [PATCH 03/10] CI issue addressed --- src/formatters/IndentFormatter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formatters/IndentFormatter.ts b/src/formatters/IndentFormatter.ts index ca6f852..3aab5a3 100644 --- a/src/formatters/IndentFormatter.ts +++ b/src/formatters/IndentFormatter.ts @@ -190,7 +190,7 @@ export class IndentFormatter { if (doubleIndentSkip) { let opener = this.getOpeningToken( tokens, - tokens.indexOf(nextNonWhitespaceToken), + tokens.indexOf(nextNonWhitespaceToken!), TokenKind.LeftSquareBracket, TokenKind.RightSquareBracket ); From 7f4c09b1afbfd0ec5c88050a16a782adead544a9 Mon Sep 17 00:00:00 2001 From: fumer-fubotv <89787347+fumer-fubotv@users.noreply.github.com> Date: Thu, 4 Apr 2024 09:09:56 -0700 Subject: [PATCH 04/10] Added support to check multiple indents followed by multiple outdents --- src/Formatter.spec.ts | 47 +++++++++++++++++++++++++++ src/formatters/IndentFormatter.ts | 53 ++++++++++++++++++++++++------- 2 files changed, 89 insertions(+), 11 deletions(-) diff --git a/src/Formatter.spec.ts b/src/Formatter.spec.ts index f147e0d..73afcdf 100644 --- a/src/Formatter.spec.ts +++ b/src/Formatter.spec.ts @@ -268,6 +268,53 @@ describe('Formatter', () => { end function } } `); + + expect(formatter.format(undent` + function test() + temp = { + key_9: { env: ["any"], themes: ["any"], runtimeCheck: function() as boolean + return true + end function + } + } + end function + `, { + formatMultiLineObjectsAndArrays: false + })).to.equal(undent` + function test() + temp = { + key_9: { env: ["any"], themes: ["any"], runtimeCheck: function() as boolean + return true + end function + } + } + end function + `); + + expect(formatter.format(undent` + function test() + temp = { + key_9: { + env: ["any"], themes: ["any"], runtimeCheck: function() as boolean + return true + end function + } + } + end function + `, { + formatMultiLineObjectsAndArrays: false + })).to.equal(undent` + function test() + temp = { + key_9: { + env: ["any"], themes: ["any"], runtimeCheck: function() as boolean + return true + end function + } + } + end function + `); + }); }); diff --git a/src/formatters/IndentFormatter.ts b/src/formatters/IndentFormatter.ts index 3aab5a3..c6cc667 100644 --- a/src/formatters/IndentFormatter.ts +++ b/src/formatters/IndentFormatter.ts @@ -91,17 +91,6 @@ export class IndentFormatter { continue; } - //skip indent for 'function'|'sub' used as type if another indent already exist in this line - if ( - IndentSpacerTokenKinds.includes(token.kind) && - //validate if its a function/sub call - nextNonWhitespaceToken.kind === TokenKind.LeftParen && - foundIndentorThisLine - ) { - parentIndentTokenKinds.push(token.kind); - continue; - } - //skip indent for single-line if statements let ifStatement = ifStatements.get(token); const endIfToken = this.getEndIfToken(ifStatement); @@ -212,12 +201,54 @@ export class IndentFormatter { // tabCount--; // } } + + //check if next multiple indents are followed by multiple outdents and update indentation accordingly + if (nextLineOffset > 1) { + nextLineOffset = this.lookaheadSameLineMultiOutdents(tokens, lineTokens[lineTokens.length - 1], nextLineOffset, currentLineOffset); + } + return { currentLineOffset: currentLineOffset, nextLineOffset: nextLineOffset }; } + /** + * Lookahead if next line with oudents are same as indents on current line + * @param tokens the array of tokens in a file + * @param curLineToken token of curent line + * @param nextLineOffset the number of tabs to indent the next line + * @param currentLineOffset the number of tabs to indent the current line + */ + private lookaheadSameLineMultiOutdents(tokens: Token[], curLineToken: Token, nextLineOffset: number, currentLineOffset: number): number { + let outdentCount = 0; + let tokenLineNum = 0; + let currentLineTokenIndex = tokens.indexOf(curLineToken); + + for (let i = currentLineTokenIndex + 1; i < tokens.length; i++) { + let token = tokens[i]; + //next line with outdents + if (OutdentSpacerTokenKinds.includes(token.kind)) { + if (tokenLineNum === 0) { + tokenLineNum = token.range.start.line; + } + + if (token.range.start.line === tokenLineNum) { + outdentCount++; + } else { + //exit when the line ends + break; + } + } + } + + //if outdents on next line with outdents = indents on current line then indent next line by one tab only + if (outdentCount > 0 && outdentCount === nextLineOffset) { + nextLineOffset = currentLineOffset + 1; + } + return nextLineOffset; + } + /** * Ensure the list of tokens contains the correct number of tabs * @param tokens the array of tokens to be modified in-place From 548ba2291c89257d31658bf31cb1f2a51994ecfb Mon Sep 17 00:00:00 2001 From: fumer-fubotv <89787347+fumer-fubotv@users.noreply.github.com> Date: Fri, 5 Apr 2024 10:26:05 -0700 Subject: [PATCH 05/10] updated tests and outdent fixes --- src/Formatter.spec.ts | 75 +++++++++++++++++++++++++++++++ src/formatters/IndentFormatter.ts | 58 ++++++++++++------------ 2 files changed, 105 insertions(+), 28 deletions(-) diff --git a/src/Formatter.spec.ts b/src/Formatter.spec.ts index 73afcdf..8c32222 100644 --- a/src/Formatter.spec.ts +++ b/src/Formatter.spec.ts @@ -315,6 +315,81 @@ describe('Formatter', () => { end function `); + expect(formatter.format(undent` + namespace tests + class TestStuff + function _() + m.assertEqual(sanitize({ + key_0: { env: [], themes: ["any"] } + key_1: { env: ["any"], themes: ["test"] } + key_2: { env: ["prod"], themes: ["test"] } + key_3: { env: ["prod"], themes: ["test"] } + key_4: { env: ["prod", "qa"], themes: ["test", "test"] } + key_5: { env: ["dev", "qa"], themes: ["test"] } + key_6: { env: ["dev", "qa"], themes: ["test", "test"] } + key_7: { env: ["dev", "qa"], themes: ["test"] } + key_8: { env: [], themes: [] } + key_9: { env: ["any"], themes: ["any"], runtimeCheck: function() as boolean + return true + end function } + key_10: { env: ["any"], themes: ["any"], runtimeCheck: function() as boolean + return false + end function } + key_11: { env: ["dev"], themes: ["any"], runtimeCheck: function() as boolean + return true + end function } + key_12: { env: ["any"], themes: ["test"], runtimeCheck: function() as boolean + return true + end function } + key_13: { { env: ["any"], themes: ["test"], runtimeCheck: function() as boolean + return true + end function } } + }, "prod", "test"), { + enabled: ["key_1", "key_2", "key_4", "key_9"] + available: ["key_0", "key_1", "key_10", "key_11", "key_12", "key_2", "key_3", "key_4", "key_5", "key_6", "key_7", "key_8", "key_9"] + }) + end function + end class + end namespace + `, { + formatMultiLineObjectsAndArrays: false + })).to.equal(undent` + namespace tests + class TestStuff + function _() + m.assertEqual(sanitize({ + key_0: { env: [], themes: ["any"] } + key_1: { env: ["any"], themes: ["test"] } + key_2: { env: ["prod"], themes: ["test"] } + key_3: { env: ["prod"], themes: ["test"] } + key_4: { env: ["prod", "qa"], themes: ["test", "test"] } + key_5: { env: ["dev", "qa"], themes: ["test"] } + key_6: { env: ["dev", "qa"], themes: ["test", "test"] } + key_7: { env: ["dev", "qa"], themes: ["test"] } + key_8: { env: [], themes: [] } + key_9: { env: ["any"], themes: ["any"], runtimeCheck: function() as boolean + return true + end function } + key_10: { env: ["any"], themes: ["any"], runtimeCheck: function() as boolean + return false + end function } + key_11: { env: ["dev"], themes: ["any"], runtimeCheck: function() as boolean + return true + end function } + key_12: { env: ["any"], themes: ["test"], runtimeCheck: function() as boolean + return true + end function } + key_13: { { env: ["any"], themes: ["test"], runtimeCheck: function() as boolean + return true + end function } } + }, "prod", "test"), { + enabled: ["key_1", "key_2", "key_4", "key_9"] + available: ["key_0", "key_1", "key_10", "key_11", "key_12", "key_2", "key_3", "key_4", "key_5", "key_6", "key_7", "key_8", "key_9"] + }) + end function + end class + end namespace + `); }); }); diff --git a/src/formatters/IndentFormatter.ts b/src/formatters/IndentFormatter.ts index c6cc667..6d6d655 100644 --- a/src/formatters/IndentFormatter.ts +++ b/src/formatters/IndentFormatter.ts @@ -59,7 +59,7 @@ export class IndentFormatter { let currentLineOffset = 0; let nextLineOffset = 0; let foundIndentorThisLine = false; - let foundUnIndentOnThisLine = false; + let outdentCount = 0; for (let i = 0; i < lineTokens.length; i++) { let token = lineTokens[i]; @@ -152,34 +152,24 @@ export class IndentFormatter { } nextLineOffset--; - - let doubleIndentSkip = (token.kind === TokenKind.RightCurlyBrace || token.kind === TokenKind.RightSquareBracket) && - //next is closing square - nextNonWhitespaceToken && nextNonWhitespaceToken.kind === TokenKind.RightSquareBracket && - //both tokens are on the same line - token.range.start.line === nextNonWhitespaceToken.range.start.line; - - if ( - OutdentSpacerTokenKinds.includes(token.kind) && - //if the line has already been outdented - (foundUnIndentOnThisLine) && - !doubleIndentSkip - ) { - continue; + if (OutdentSpacerTokenKinds.includes(token.kind)) { + outdentCount++; } - foundUnIndentOnThisLine = true; - if (foundIndentorThisLine === false) { currentLineOffset--; } parentIndentTokenKinds.pop(); //don't double un-indent if this is `[[...\n...]]` or `[{...\n...}]` - if (doubleIndentSkip) { + if ((token.kind === TokenKind.RightCurlyBrace || token.kind === TokenKind.RightSquareBracket) && + //next is closing square + nextNonWhitespaceToken && nextNonWhitespaceToken.kind === TokenKind.RightSquareBracket && + //both tokens are on the same line + token.range.start.line === nextNonWhitespaceToken.range.start.line) { let opener = this.getOpeningToken( tokens, - tokens.indexOf(nextNonWhitespaceToken!), + tokens.indexOf(nextNonWhitespaceToken), TokenKind.LeftSquareBracket, TokenKind.RightSquareBracket ); @@ -205,6 +195,16 @@ export class IndentFormatter { //check if next multiple indents are followed by multiple outdents and update indentation accordingly if (nextLineOffset > 1) { nextLineOffset = this.lookaheadSameLineMultiOutdents(tokens, lineTokens[lineTokens.length - 1], nextLineOffset, currentLineOffset); + } else if (outdentCount > 0) { + //if multiple outdents on same line then outdent only once + if (currentLineOffset < 0) { + currentLineOffset = -1; + } + + //if multiple outdents on same line then outdent nextline only once + if (nextLineOffset < 0) { + nextLineOffset = -1; + } } return { @@ -227,16 +227,18 @@ export class IndentFormatter { for (let i = currentLineTokenIndex + 1; i < tokens.length; i++) { let token = tokens[i]; - //next line with outdents - if (OutdentSpacerTokenKinds.includes(token.kind)) { - if (tokenLineNum === 0) { - tokenLineNum = token.range.start.line; - } + if (token.kind !== TokenKind.Whitespace) { + //next line with outdents + if (OutdentSpacerTokenKinds.includes(token.kind)) { + if (tokenLineNum === 0) { + tokenLineNum = token.range.start.line; + } - if (token.range.start.line === tokenLineNum) { - outdentCount++; - } else { - //exit when the line ends + if (token.range.start.line === tokenLineNum) { + outdentCount++; + } + } + if (tokenLineNum > 0 && token.range.start.line !== tokenLineNum) { break; } } From c9d7fe5aef2178c3be64962c7a11030e2d6608c9 Mon Sep 17 00:00:00 2001 From: fumer-fubotv <89787347+fumer-fubotv@users.noreply.github.com> Date: Fri, 5 Apr 2024 10:29:00 -0700 Subject: [PATCH 06/10] formatting updated --- src/formatters/IndentFormatter.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/formatters/IndentFormatter.ts b/src/formatters/IndentFormatter.ts index 6d6d655..0ece121 100644 --- a/src/formatters/IndentFormatter.ts +++ b/src/formatters/IndentFormatter.ts @@ -162,11 +162,14 @@ export class IndentFormatter { parentIndentTokenKinds.pop(); //don't double un-indent if this is `[[...\n...]]` or `[{...\n...}]` - if ((token.kind === TokenKind.RightCurlyBrace || token.kind === TokenKind.RightSquareBracket) && - //next is closing square - nextNonWhitespaceToken && nextNonWhitespaceToken.kind === TokenKind.RightSquareBracket && - //both tokens are on the same line - token.range.start.line === nextNonWhitespaceToken.range.start.line) { + if ( + //is closing curly or square + (token.kind === TokenKind.RightCurlyBrace || token.kind === TokenKind.RightSquareBracket) && + //next is closing square + nextNonWhitespaceToken && nextNonWhitespaceToken.kind === TokenKind.RightSquareBracket && + //both tokens are on the same line + token.range.start.line === nextNonWhitespaceToken.range.start.line + ) { let opener = this.getOpeningToken( tokens, tokens.indexOf(nextNonWhitespaceToken), From a6691aa0d334a5e62b2394918ddf06ee39455b21 Mon Sep 17 00:00:00 2001 From: fumer-fubotv <89787347+fumer-fubotv@users.noreply.github.com> Date: Mon, 15 Apr 2024 08:58:35 -0700 Subject: [PATCH 07/10] More test cases added and solution updated --- src/Formatter.spec.ts | 45 ++++++++++++ src/formatters/IndentFormatter.ts | 113 +++++++++++++++++++++++++++--- 2 files changed, 147 insertions(+), 11 deletions(-) diff --git a/src/Formatter.spec.ts b/src/Formatter.spec.ts index 8c32222..3c17a69 100644 --- a/src/Formatter.spec.ts +++ b/src/Formatter.spec.ts @@ -390,6 +390,51 @@ describe('Formatter', () => { end class end namespace `); + + formatEqual(undent` + sub createSections(navigationAction as object) + m.sections = [FormatJson({ + type: "test" + components: [{ + type: "test" + group_id: "1" + }] + slug: "test" + })] + end sub + `, undefined, { + formatMultiLineObjectsAndArrays: false + }); + + formatEqual(undent` + sub createSections(navigationAction as object) + m.sections = [parser.parseList({ + components: [{ + buttons: [{ + actions: { + on_click: [get.value(navigationAction, "_retryAction")] + } + }] + }] + })] + end sub + `, undefined, { + formatMultiLineObjectsAndArrays: false + }); + + formatEqual(undent` + namespace alpha + namespace beta + sub createSections() + m.sections = [ + FormatJson({ + })] + end sub + end namespace + end namespace + `, undefined, { + formatMultiLineObjectsAndArrays: false + }); }); }); diff --git a/src/formatters/IndentFormatter.ts b/src/formatters/IndentFormatter.ts index 0ece121..b7441a1 100644 --- a/src/formatters/IndentFormatter.ts +++ b/src/formatters/IndentFormatter.ts @@ -204,9 +204,9 @@ export class IndentFormatter { currentLineOffset = -1; } - //if multiple outdents on same line then outdent nextline only once if (nextLineOffset < 0) { - nextLineOffset = -1; + //look back to get offset of last closing token pair + nextLineOffset = this.getNextLineOffset(tokens, lineTokens); } } @@ -216,6 +216,71 @@ export class IndentFormatter { }; } + /** + * Lookback to find the matching opening token and then calculates outdents + * @param tokens the array of tokens in a file + * @param lineTokens token of curent line + */ + private getNextLineOffset(tokens: Token[], lineTokens: Token[]): number { + let nextLineOffset = -1; + + let lineLastToken = util.getPreviousNonWhitespaceToken(lineTokens, lineTokens.length - 1); + let curLineLastToken = lineLastToken !== undefined ? lineLastToken : lineTokens[lineTokens.length - 1]; + + let closeKind = curLineLastToken.kind; + let openKind = this.getOpeningTokenKind(closeKind); + + if ((curLineLastToken.kind === TokenKind.RightCurlyBrace) || (curLineLastToken.kind === TokenKind.RightSquareBracket)) { + let openCount = 0; + let isWhiteSpaceToken = (lineTokens[0].kind === TokenKind.Whitespace) || (lineTokens[0].kind === TokenKind.Newline); + let lineFirstToken = isWhiteSpaceToken ? util.getNextNonWhitespaceToken(lineTokens, 0) : lineTokens[0]; + let curLineStart = lineFirstToken?.range.start.character ? lineFirstToken?.range.start.character : 0; + + let openerFound = false; + let currentIndex = lineTokens.indexOf(curLineLastToken); + + let lines = this.splitTokensByLine(tokens); + + for (let lineIndex = curLineLastToken.range.start.line; lineIndex >= 0; lineIndex--) { + let lineToken = lines[lineIndex]; + isWhiteSpaceToken = (lineToken[0].kind === TokenKind.Whitespace) || (lineToken[0].kind === TokenKind.Newline); + let firstToken = isWhiteSpaceToken ? util.getNextNonWhitespaceToken(lineToken, 0) : lineToken[0]; + let lineStartPosition = firstToken ? firstToken.range.start.character : 0; + + let lineTokenIndex = currentIndex > -1 ? currentIndex : lineToken.length - 1; + currentIndex = -1; + + for (let i = lineTokenIndex; i >= 0; i--) { + let token = lineToken[i]; + if (token.kind === TokenKind.Whitespace) { + continue; + } + + if (token.kind === openKind) { + openCount++; + } else if (token.kind === closeKind) { + openCount--; + } + + if (openCount === 0) { + openerFound = true; + break; + } + } + + if (lineStartPosition < curLineStart) { + nextLineOffset--; + curLineStart = lineStartPosition; + } + + if (openerFound) { + break; + } + } + } + return nextLineOffset; + } + /** * Lookahead if next line with oudents are same as indents on current line * @param tokens the array of tokens in a file @@ -231,14 +296,18 @@ export class IndentFormatter { for (let i = currentLineTokenIndex + 1; i < tokens.length; i++) { let token = tokens[i]; if (token.kind !== TokenKind.Whitespace) { + let openingTokenKind = this.getOpeningTokenKind(token.kind); //next line with outdents - if (OutdentSpacerTokenKinds.includes(token.kind)) { - if (tokenLineNum === 0) { - tokenLineNum = token.range.start.line; - } - - if (token.range.start.line === tokenLineNum) { - outdentCount++; + if (OutdentSpacerTokenKinds.includes(token.kind) && openingTokenKind) { + let opener = this.getOpeningToken(tokens, i, openingTokenKind, token.kind); + if (opener && opener.range.start.line === curLineToken.range.start.line) { + if (tokenLineNum === 0) { + tokenLineNum = token.range.start.line; + } + + if (token.range.start.line === tokenLineNum) { + outdentCount++; + } } } if (tokenLineNum > 0 && token.range.start.line !== tokenLineNum) { @@ -248,8 +317,10 @@ export class IndentFormatter { } //if outdents on next line with outdents = indents on current line then indent next line by one tab only - if (outdentCount > 0 && outdentCount === nextLineOffset) { - nextLineOffset = currentLineOffset + 1; + if (outdentCount > 0) { + if (outdentCount === nextLineOffset) { + nextLineOffset = currentLineOffset + 1; + } } return nextLineOffset; } @@ -373,6 +444,26 @@ export class IndentFormatter { } } + /** + * Returns opening token kind of the tokenkind passed + */ + public getOpeningTokenKind(tokenKind: TokenKind) { + if (tokenKind === TokenKind.RightCurlyBrace) { + return TokenKind.LeftCurlyBrace; + } else if (tokenKind === TokenKind.RightParen) { + return TokenKind.LeftParen; + } else if (tokenKind === TokenKind.RightSquareBracket) { + return TokenKind.LeftSquareBracket; + } else if (tokenKind === TokenKind.EndIf) { + return TokenKind.If; + } else if (tokenKind === TokenKind.EndFunction) { + return TokenKind.Function; + } else if (tokenKind === TokenKind.EndSub) { + return TokenKind.Sub; + } + return undefined; + } + /** * Determines if this is an outdent token */ From 0ed0e98b4b5dbed8326e19c402d46baf3c340257 Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Tue, 7 May 2024 09:22:09 -0400 Subject: [PATCH 08/10] Add failing test --- src/Formatter.spec.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Formatter.spec.ts b/src/Formatter.spec.ts index 3c17a69..1f3c01c 100644 --- a/src/Formatter.spec.ts +++ b/src/Formatter.spec.ts @@ -252,6 +252,19 @@ describe('Formatter', () => { `); }); + it.only('empty newlines in AA do not break indentation', ()=>{ + formatEqual(undent` + sub test() + array = [{ + + }] + if true then + print true + end if + end sub + `); + }); + it('formats outdents', () => { expect(formatter.format(undent` temp = { @@ -285,7 +298,7 @@ describe('Formatter', () => { temp = { key_9: { env: ["any"], themes: ["any"], runtimeCheck: function() as boolean return true - end function + end function } } end function From 9be551d460b3779f251af723216ef85d86cf9760 Mon Sep 17 00:00:00 2001 From: fumer-fubotv <89787347+fumer-fubotv@users.noreply.github.com> Date: Thu, 9 May 2024 13:09:13 -0700 Subject: [PATCH 09/10] Support for empty lines in AA --- src/Formatter.spec.ts | 2 +- src/formatters/IndentFormatter.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Formatter.spec.ts b/src/Formatter.spec.ts index 1f3c01c..11168c8 100644 --- a/src/Formatter.spec.ts +++ b/src/Formatter.spec.ts @@ -252,7 +252,7 @@ describe('Formatter', () => { `); }); - it.only('empty newlines in AA do not break indentation', ()=>{ + it('empty newlines in AA do not break indentation', ()=>{ formatEqual(undent` sub test() array = [{ diff --git a/src/formatters/IndentFormatter.ts b/src/formatters/IndentFormatter.ts index b7441a1..d4fc18e 100644 --- a/src/formatters/IndentFormatter.ts +++ b/src/formatters/IndentFormatter.ts @@ -243,6 +243,10 @@ export class IndentFormatter { for (let lineIndex = curLineLastToken.range.start.line; lineIndex >= 0; lineIndex--) { let lineToken = lines[lineIndex]; + + if (lineToken.length === 1 && lineToken[0].kind === TokenKind.Newline) { + continue; + } isWhiteSpaceToken = (lineToken[0].kind === TokenKind.Whitespace) || (lineToken[0].kind === TokenKind.Newline); let firstToken = isWhiteSpaceToken ? util.getNextNonWhitespaceToken(lineToken, 0) : lineToken[0]; let lineStartPosition = firstToken ? firstToken.range.start.character : 0; From f01dd39cfa8dc807af25022fc863faef093f7d05 Mon Sep 17 00:00:00 2001 From: fumer-fubotv <89787347+fumer-fubotv@users.noreply.github.com> Date: Thu, 9 May 2024 13:12:25 -0700 Subject: [PATCH 10/10] spaces --- src/Formatter.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Formatter.spec.ts b/src/Formatter.spec.ts index 11168c8..825d8c6 100644 --- a/src/Formatter.spec.ts +++ b/src/Formatter.spec.ts @@ -252,7 +252,7 @@ describe('Formatter', () => { `); }); - it('empty newlines in AA do not break indentation', ()=>{ + it('empty newlines in AA do not break indentation', () => { formatEqual(undent` sub test() array = [{