diff --git a/src/Formatter.spec.ts b/src/Formatter.spec.ts index 6d6ed60..9f33cd6 100644 --- a/src/Formatter.spec.ts +++ b/src/Formatter.spec.ts @@ -935,6 +935,72 @@ end sub`; ); }); + it('correctly indents function class modifiers', () => { + expect(formatter.format( + 'function class()\nend function' + )).to.equal( + 'function class()\nend function' + ); + }); + + it('correctly indents function class modifiers with print statement', () => { + expect(formatter.format( + 'function class()\nprint "hello"\nend function' + )).to.equal( + 'function class()\n print "hello"\nend function' + ); + }); + + it('correctly indents function enum modifiers', () => { + expect(formatter.format( + 'function enum()\nend function' + )).to.equal( + 'function enum()\nend function' + ); + }); + + it('correctly indents function enum modifiers with print statement', () => { + expect(formatter.format( + 'function enum()\nprint "hello"\nend function' + )).to.equal( + 'function enum()\n print "hello"\nend function' + ); + }); + it('property indents try catch statements', () => { + formatEqualTrim(` + function try() + try + print "hello" + catch e + print "caught" + end try + print "hello" + end function + `); + }); + + it('correctly indents function with try having contents', () => { + expect(formatter.format(undent` + function try + try + print "hello" + catch e + print "world" + end try + print "done" + end function + `)).to.equal(undent` + function try + try + print "hello" + catch e + print "world" + end try + print "done" + end function + `); + }); + it('trims empty lines', () => { expect(formatter.format(`sub a()\n \nend sub`)).to.equal(`sub a()\n\nend sub`); }); @@ -1551,6 +1617,7 @@ end sub`; expect(format(['exitwhile', TokenKind.ExitWhile])).to.equal('exit while'); expect(format(['exitfor', TokenKind.ExitFor])).to.equal('exit for'); expect(format(['endfor', TokenKind.EndFor])).to.equal('end for'); + expect(format(['endtry', TokenKind.EndTry])).to.equal('end try'); expect(formatter.format( `sub add()\n if true then\n a=1\n elseif true then\n a=1\n endif\nendsub`, diff --git a/src/constants.ts b/src/constants.ts index ad7f36a..d11575b 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -103,7 +103,9 @@ export let IndentSpacerTokenKinds = [ export let IgnoreIndentSpacerByParentTokenKind = new Map([ [TokenKind.Interface, [ TokenKind.Sub, - TokenKind.Function + TokenKind.Function, + TokenKind.Enum, + TokenKind.Class ]] ]); diff --git a/src/formatters/IndentFormatter.ts b/src/formatters/IndentFormatter.ts index cc54164..5980cdb 100644 --- a/src/formatters/IndentFormatter.ts +++ b/src/formatters/IndentFormatter.ts @@ -53,7 +53,8 @@ export class IndentFormatter { parentIndentTokenKinds: TokenKind[] ): { currentLineOffset: number; nextLineOffset: number } { const getParentIndentTokenKind = () => { - return parentIndentTokenKinds.length > 0 ? parentIndentTokenKinds[parentIndentTokenKinds.length - 1] : undefined; + const parentIndentTokenKind = parentIndentTokenKinds.length > 0 ? parentIndentTokenKinds[parentIndentTokenKinds.length - 1] : undefined; + return parentIndentTokenKind; }; let currentLineOffset = 0; @@ -112,6 +113,23 @@ export class IndentFormatter { // check for specifically mentioned tokens to NOT indent const parentIndentTokenKind = getParentIndentTokenKind(); + const parentIndentTokenKindsContainsSubOrFunction = parentIndentTokenKinds.includes(TokenKind.Sub) || parentIndentTokenKinds.includes(TokenKind.Function); + + const tokenKindIsClass = token.kind === TokenKind.Class; + const tokenKindIsEnum = token.kind === TokenKind.Enum; + const tokenKindIsInterface = token.kind === TokenKind.Interface; + const tokenKindIsNamespace = token.kind === TokenKind.Namespace; + const tokenKindIsTry = token.kind === TokenKind.Try; + + // dont indent if parent is sub or function and this is a class, enum, interface, namespace, or try + const preventIndent = parentIndentTokenKindsContainsSubOrFunction && (tokenKindIsClass || tokenKindIsEnum || tokenKindIsInterface || tokenKindIsNamespace || tokenKindIsTry); + if (preventIndent) { + if (tokenKindIsTry && (lineTokens.length === 2 || lineTokens.length === 3)) { + nextLineOffset++; + } + continue; + } + if (parentIndentTokenKind && IgnoreIndentSpacerByParentTokenKind.get(parentIndentTokenKind)?.includes(token.kind)) { // This particular token should not be indented because it is listed in the ignore group for its parent continue; @@ -121,7 +139,6 @@ export class IndentFormatter { foundIndentorThisLine = true; parentIndentTokenKinds.push(token.kind); - //don't double indent if this is `[[...\n...]]` or `[{...\n...}]` if ( //is open square @@ -144,7 +161,7 @@ export class IndentFormatter { } else if (this.isOutdentToken(token, nextNonWhitespaceToken)) { //do not un-indent if this is a `next` or `endclass` token preceeded by a period if ( - [TokenKind.Next, TokenKind.EndClass, TokenKind.Namespace, TokenKind.EndNamespace].includes(token.kind) && + [TokenKind.Next, TokenKind.EndClass, TokenKind.Namespace, TokenKind.EndNamespace, TokenKind.Catch, TokenKind.EndTry].includes(token.kind) && previousNonWhitespaceToken && previousNonWhitespaceToken.kind === TokenKind.Dot ) { continue;