-
Notifications
You must be signed in to change notification settings - Fork 235
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
Fix embedded templates handling in block-indentation
rule
#2838
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -102,8 +102,12 @@ function get(node, path) { | |
return value; | ||
} | ||
|
||
function removeWhitespaceEnd(str) { | ||
return str.replace(/ +$/, ''); | ||
function addWhitespaceEnd(str, count) { | ||
return `${str}${' '.repeat(count)}`; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See line 326. The direct child indentation used to only remove whitespaces, but in embedded templates adding whitespaces is now also necessary sometimes. |
||
} | ||
|
||
function removeWhitespaceEnd(str, count) { | ||
return str.replace(new RegExp(` {${count}}$`), ''); | ||
} | ||
|
||
export default class BlockIndentation extends Rule { | ||
|
@@ -306,13 +310,20 @@ export default class BlockIndentation extends Rule { | |
const hasLeadingContent = | ||
!isDirectChildOfTemplate || this.hasLeadingContent(node, this.template.body); | ||
const startColumn = node.loc.start.column; | ||
const expectedStartColumn = | ||
this.columnOffset === 0 || node.loc.start.line === 1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The 'root' node starting at line 1 is meant for cases like: test('it renders', async (assert) => {
await render(hbs`<div class="parent">
<div class="child"></div>
</div>`);
); |
||
? 0 | ||
: this.columnOffset + this.config.indentation; | ||
|
||
// If it's not a direct child of the template the block start is already fixed by the validateBlockChildren function | ||
if (isDirectChildOfTemplate && startColumn !== 0 && !hasLeadingContent) { | ||
if (isDirectChildOfTemplate && startColumn !== expectedStartColumn && !hasLeadingContent) { | ||
if (this.mode === 'fix') { | ||
const previousNode = this.template.body[indexOfNodeInTemplate - 1]; | ||
if (previousNode.type === 'TextNode') { | ||
previousNode.chars = removeWhitespaceEnd(previousNode.chars); | ||
previousNode.chars = | ||
startColumn > expectedStartColumn | ||
? removeWhitespaceEnd(previousNode.chars, startColumn - expectedStartColumn) | ||
: addWhitespaceEnd(previousNode.chars, expectedStartColumn - startColumn); | ||
} | ||
} else { | ||
let isElementNode = node && node.type === 'ElementNode'; | ||
|
@@ -322,7 +333,7 @@ export default class BlockIndentation extends Rule { | |
|
||
let warning = | ||
`Incorrect indentation for \`${display}\` beginning at ${startLocation}. ` + | ||
`Expected \`${display}\` to be at an indentation of 0, but was found at ${startColumn}.`; | ||
`Expected \`${display}\` to be at an indentation of ${expectedStartColumn}, but was found at ${startColumn}.`; | ||
|
||
this.log({ | ||
message: warning, | ||
|
@@ -347,8 +358,12 @@ export default class BlockIndentation extends Rule { | |
|
||
let controlCharCount = this.endingControlCharCount(node); | ||
let correctedEndColumn = endColumn - displayName.length - controlCharCount; | ||
let expectedEndColumn = | ||
this.columnOffset === 0 || node.loc.end.line !== this.template.loc.end.line | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to the start of a block: test('it renders', async (assert) => {
await render(hbs`<div class="parent">
<div class="child"></div>
</div>`);
); When the node it at the end of the template is and the template is embedded, then the start column should be the |
||
? startColumn | ||
: this.columnOffset; | ||
|
||
if (correctedEndColumn !== startColumn) { | ||
if (correctedEndColumn !== expectedEndColumn) { | ||
if (this.mode === 'fix') { | ||
// If we are in a child (path set) we want to edit directly the source and not the source of the node | ||
const elementSource = path | ||
|
@@ -362,7 +377,7 @@ export default class BlockIndentation extends Rule { | |
lines, | ||
node.loc.end.line - (path ? 1 : node.loc.start.line), | ||
correctedEndColumn, | ||
startColumn, | ||
expectedEndColumn, | ||
path | ||
); | ||
return fixedNode; | ||
|
@@ -372,7 +387,7 @@ export default class BlockIndentation extends Rule { | |
|
||
let warning = | ||
`Incorrect indentation for \`${displayName}\` beginning at ${startLocation}` + | ||
`. Expected \`${display}\` ending at ${endLocation} to be at an indentation of ${startColumn} but ` + | ||
`. Expected \`${display}\` ending at ${endLocation} to be at an indentation of ${expectedEndColumn} but ` + | ||
`was found at ${correctedEndColumn}.`; | ||
|
||
this.log({ | ||
|
@@ -405,7 +420,9 @@ export default class BlockIndentation extends Rule { | |
} | ||
|
||
let startColumn = node.loc.start.column; | ||
let expectedStartColumn = startColumn + this.config.indentation; | ||
let correctedStartColumn = | ||
this.columnOffset > 0 && node.loc.start.line === 1 ? this.columnOffset : startColumn; | ||
let expectedStartColumn = correctedStartColumn + this.config.indentation; | ||
let fixedNode = node; | ||
|
||
let i = 0; | ||
|
@@ -477,7 +494,7 @@ export default class BlockIndentation extends Rule { | |
|
||
fixedNode = this.fixLine( | ||
lines, | ||
childStartLine - 1, | ||
childStartLine - (path ? 1 : fixedNode.loc.start.line), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This actually seemed to be an existing bug. When I ran the autofixer with |
||
childStartColumn, | ||
expectedStartColumn, | ||
path | ||
|
@@ -520,9 +537,11 @@ export default class BlockIndentation extends Rule { | |
|
||
let inverse = node.inverse; | ||
let startColumn = node.loc.start.column; | ||
let expectedStartColumn = | ||
this.columnOffset > 0 && node.loc.start.line === 1 ? this.columnOffset : startColumn; | ||
let elseStartColumn = node.program.loc.end.column; | ||
|
||
if (elseStartColumn !== startColumn) { | ||
if (elseStartColumn !== expectedStartColumn) { | ||
if (this.mode === 'fix') { | ||
// If we are in a child (path set) we want to edit directly the source and not the source of the node | ||
const sourceToFix = path | ||
|
@@ -533,7 +552,13 @@ export default class BlockIndentation extends Rule { | |
}); | ||
const lines = sourceToFix.split('\n'); | ||
const elseLine = node.program.loc.end.line; | ||
const fixedNode = this.fixLine(lines, elseLine - 1, elseStartColumn, startColumn, path); | ||
const fixedNode = this.fixLine( | ||
lines, | ||
elseLine - 1, | ||
elseStartColumn, | ||
expectedStartColumn, | ||
path | ||
); | ||
return fixedNode; | ||
} else { | ||
let displayName = node.path.original; | ||
|
@@ -542,7 +567,7 @@ export default class BlockIndentation extends Rule { | |
|
||
let warning = | ||
`Incorrect indentation for inverse block of \`{{#${displayName}}}\` beginning at ${startLocation}` + | ||
`. Expected \`{{else}}\` starting at ${elseLocation} to be at an indentation of ${startColumn} but ` + | ||
`. Expected \`{{else}}\` starting at ${elseLocation} to be at an indentation of ${expectedStartColumn} but ` + | ||
`was found at ${elseStartColumn}.`; | ||
|
||
this.log({ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way I approached it, is that the location of the embedded template is offset by the indentation of the line the template starts at. So, something like
has an offset of 2, because
await
has an indentation of 2 spaces. Based on this info, each rule (block-indentation
in this case, butattribute-indentation
can probably work the same) can adjust the expected indentation if needed.