-
Notifications
You must be signed in to change notification settings - Fork 889
refactor newlineBeforeReturn to support more variants #3139
Conversation
I agree that it makes sense to rename and enhance the rule instead of adding yet another whitespace related rule. Nevertheless we need to keep |
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.
Finished my first pass of the review. I only looked at the code. Will need to think a bit more about the configuration.
src/rules/newlineRule.ts
Outdated
} | ||
|
||
const ALWAYS_IGNORE_OR_NEVER = { | ||
enum: OptionState, |
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.
this is only used in the metadata? I don't think this works with string enums. It actually expects a string array here.
src/rules/newlineRule.ts
Outdated
options[optionName] = typeof json === "object" ? json[optionName] : json === undefined ? "always" : json; | ||
} | ||
return options; | ||
} |
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.
I'd suggest the following (note that this defaults to ignore, which might be more intuitive)
type Options = Record<OptionName, Option>;
function parseOptions(json: Partial<Options> | undefined) {
const default: Options = {return: "ignore", class: "ignore", functionBlock: "ignore", block: "ignore"};
return {...default, json};
}
src/rules/newlineRule.ts
Outdated
optionsDescription: Lint.Utils.dedent` | ||
Following arguments may be optionally provided: | ||
|
||
* \`"return"\` checks for empty line before return when not the only line in the block. |
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.
s/line/statement/
src/rules/newlineRule.ts
Outdated
Following arguments may be optionally provided: | ||
|
||
* \`"return"\` checks for empty line before return when not the only line in the block. | ||
* \`"class"\` checks for empty line after class declaration. |
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.
checks for empty line at the start of a class body
src/rules/newlineRule.ts
Outdated
|
||
* \`"return"\` checks for empty line before return when not the only line in the block. | ||
* \`"class"\` checks for empty line after class declaration. | ||
* \`"functionBlock"\` checks for empty line after function block declaration. |
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.
at the start of a function block
src/rules/newlineRule.ts
Outdated
|
||
if (isClassDeclaration(node) && this.options.class != OptionState.ignore) { | ||
this.checkForEmptyLine( | ||
getChildOfKind(node, ts.SyntaxKind.OpenBraceToken, this.sourceFile)!, node.members[0], |
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.
instead of getChildOfKind(...)
you could simply pass node.members.pos
as first parameter. see my other comment in checkForEmptyLine
below
src/rules/newlineRule.ts
Outdated
(isFunctionWithBody(node.parent!) && this.options.functionBlock != OptionState.ignore | ||
|| this.options.block != OptionState.ignore)) { | ||
this.checkForEmptyLine( | ||
node.getChildAt(0), node.statements[0], this.options.functionBlock == OptionState.always, 'first statement', |
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.
instead of node.getChildAt(...)
you could simply pass node.statements.pos
as first parameter. see my other comment in checkForEmptyLine
below
src/rules/newlineRule.ts
Outdated
(isFunctionWithBody(node.parent!) && this.options.functionBlock != OptionState.ignore | ||
|| this.options.block != OptionState.ignore)) { | ||
this.checkForEmptyLine( | ||
node.getChildAt(0), node.statements[0], this.options.functionBlock == OptionState.always, 'first statement', |
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.
you need to check if the block contains any statement
src/rules/newlineRule.ts
Outdated
private checkForEmptyLine(node: ts.Node, firstNode: ts.Node, lineRequired: boolean, nodeType: string) { | ||
let start = node.end; | ||
let line = ts.getLineAndCharacterOfPosition(this.sourceFile, start).line; | ||
let firstNodeStart = firstNode.getStart(); |
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.
please provide the sourceFile
parameter to getStart()
for performance reasons
|
||
[0]: Missing blank line before return | ||
|
||
|
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.
do these trailing whitespaces serve a purpose?
optionsDescription: Lint.Utils.dedent` | ||
Following arguments may be optionally provided: | ||
|
||
* \`"return"\` checks for empty listane before return when not the only statement in the block. |
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.
s/listane/line/
* \`"return"\` checks for empty listane before return when not the only statement in the block. | ||
* \`"class"\` checks for empty line at the start of a class body. | ||
* \`"functionBlock"\` checks for empty line at the start of a function block. | ||
* \`"block"\` checks for empty line after block declaration.`, |
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.
s/after/in the first line of a/
|
||
export enum ViolationType { | ||
needed = "needed", | ||
needless = "needless", |
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.
prefer "unnecessary"
optionsDescription: Lint.Utils.dedent` | ||
Following arguments may be optionally provided: | ||
|
||
* \`"return"\` checks for empty listane before return when not the only statement in the block. |
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.
as discussed offline: I don't like the option names.
I'd prefer "before-return" here.
I'm also in favor of "start-of-class" to allow adding "before-class" and "after-class" later on.
And to keep naming consistent, you should prefer "function-block" over "functionBlock"
/* tslint:enable:object-literal-sort-keys */ | ||
|
||
public static FAILURE_STRING_FACTORY(kind: ViolationType, nodeType: string) { | ||
const kindMsg = kind === ViolationType.needed ? 'Missing' : 'Unneeded'; |
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.
Why don't you use the string value of the enum?
PR checklist
Overview of change:
Rename newlineBeforeReturn to newline and add some more options for adding newlines.