Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle double-indent followed by double-outdent #89

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
65 changes: 65 additions & 0 deletions src/Formatter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,71 @@ 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 }
}
`);

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
`);

});
});

describe('formatMultiLineObjectsAndArrays', () => {
Expand Down
72 changes: 63 additions & 9 deletions src/formatters/IndentFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -151,23 +152,34 @@ 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;
}

foundUnIndentOnThisLine = true;

if (foundIndentorThisLine === false) {
currentLineOffset--;
}
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),
tokens.indexOf(nextNonWhitespaceToken!),
TokenKind.LeftSquareBracket,
TokenKind.RightSquareBracket
);
Expand All @@ -189,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
Expand Down