Skip to content

Commit

Permalink
Merge pull request #96 from philanderson888/issue-77-formatter-with-k…
Browse files Browse the repository at this point in the history
…eywords-in-function-name

Fix indentation bug when brighterscript keywords are used as identifiers
  • Loading branch information
TwitchBronBron authored Jan 29, 2025
2 parents 5ad754a + 7bc49ff commit 07e31fa
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 4 deletions.
67 changes: 67 additions & 0 deletions src/Formatter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`);
});
Expand Down Expand Up @@ -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`,
Expand Down
4 changes: 3 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ export let IndentSpacerTokenKinds = [
export let IgnoreIndentSpacerByParentTokenKind = new Map<TokenKind, TokenKind[]>([
[TokenKind.Interface, [
TokenKind.Sub,
TokenKind.Function
TokenKind.Function,
TokenKind.Enum,
TokenKind.Class
]]
]);

Expand Down
23 changes: 20 additions & 3 deletions src/formatters/IndentFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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;
Expand Down

0 comments on commit 07e31fa

Please sign in to comment.