-
Notifications
You must be signed in to change notification settings - Fork 886
Added space-before-function-paren rule #1897
Conversation
Thanks for your interest in palantir/tslint, @cameron-mcateer! Before we can accept your pull request, you need to sign our contributor license agreement - just visit https://cla.palantir.com/ and follow the instructions. Once you sign, I'll automatically update this pull request. |
e98e041
to
444ff58
Compare
can you turn on circleCI? |
|
import * as Lint from "../index"; | ||
|
||
const ALWAYS_OR_NEVER = { | ||
enum: ["always", "never"], |
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 use 4-space indentation in TS files like the rest of the project
super.visitMethodSignature(node); | ||
} | ||
|
||
private _visitFunction(node: ts.Node): void { |
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.
we don't use the underscore naming convention -- the private
modifier is enough to denote encapsulation.
failure = this.createFailure(openParen.getStart(), 1, Rule.MISSING_WHITESPACE_ERROR, fix); | ||
} | ||
|
||
if (failure) { |
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 avoid implicit type coercion to boolean -- do an explicit undefined
check instead
private _visitFunction(node: ts.Node): void { | ||
const options = this.getOptions(); | ||
|
||
if (options === null || options.length === 0 || Object.keys(options).length === 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.
this check looks overly defensive; I don't think any of your code will break if you remove this. it's better to be consistent with other rules in code style.
private getOption(option: string): string { | ||
const allOptions = this.getOptions(); | ||
if (allOptions == null || allOptions.length === 0) { | ||
return null; |
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 avoid using null
explicitly; return undefined
instead
} | ||
}); | ||
|
||
if (!openParen || (isArrow && !isAsyncArrow)) { |
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.
no implicit boolean coercion
type: "style", | ||
typescriptOnly: false, | ||
}; | ||
public static INVALID_WHITESPACE_ERROR = "Should be no space before paren"; |
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.
suggestion: "Spaces before function parens are disallowed"
typescriptOnly: false, | ||
}; | ||
public static INVALID_WHITESPACE_ERROR = "Should be no space before paren"; | ||
public static MISSING_WHITESPACE_ERROR = "Should be a space before paren"; |
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.
suggestion: "Missing whitespace before function parens"
444ff58
to
936078a
Compare
@adidahiya Thanks for the feedback! Changes made. |
936078a
to
dec8fed
Compare
Updated. Renamed file from |
|
||
* \`"anonymous"\` checks before the opening paren in anonymous functions | ||
* \`"named"\` checks before the opening paren in named functions | ||
* \`"asyncArrow"\` checks before the opening paren in async arrow functions, |
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.
don't need comma at the end here
super.visitMethodSignature(node); | ||
} | ||
|
||
private visitFunction(node: ts.Node): void { |
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.
can you break this up into smaller functions?
export class Rule extends Lint.Rules.AbstractRule { | ||
public static metadata: Lint.IRuleMetadata = { | ||
description: "Require or disallow a space before function parenthesis", | ||
optionExamples: [`[true, {"anonymous": "always", "named": "never", "asyncArrow": "always"}]`], |
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.
seems tedious to need to specify a value for each type of function. How about allowing something like [true, "always"]
or even [true]
, which defaults to the same thing.
deferring to @nchen63 for final review
6395bc7
to
665ab24
Compare
@nchen63 Split |
* \`"named"\` checks before the opening paren in named functions | ||
* \`"asyncArrow"\` checks before the opening paren in async arrow functions | ||
* \`"method"\` checks before the opening paren in class methods | ||
*v\`"constructor"\` checks before the opening paren in class constructors |
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.
stray v
?
} | ||
|
||
private getOption(optionName: string): string { | ||
const allOptions = this.getOptions(); |
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.
can you parse the options once in the constructor so that doing this check will be a quick lookup?
665ab24
to
4ce2f1d
Compare
@nchen63 Woops sorry that snuck in. Also caching the options now. |
4ce2f1d
to
5d6cf1c
Compare
Rebased on latest to keep tests passing. |
|
||
class FunctionWalker extends Lint.RuleWalker { | ||
private scanner: ts.Scanner; | ||
private cachedOptions: any; |
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.
here's how you can avoid using any
for cachedOptions
:
interface CachedOptions {
anonymous?: boolean;
asyncArrow?: boolean;
}
type optionType = "anonymous" | "asyncArrow";
let cachedOptions: CachedOptions = {};
// cache the options
let optionArray: optionType[] = ["anonymous", "asyncArrow"]
for (const option of optionArray) {
cachedOptions[option] = true;
}
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.
Oh thank you. I kept using the string values in so that it allows the user to ignore certain rules (as opposed to forcing a failure if they are not consistent).
5d6cf1c
to
b562822
Compare
@cameron-mcateer thanks! For future reference, it would be helpful if you didn't squash and force push your changes so I can see the diff between updates. |
@nchen63 Thanks! Will do. I'm used to amending all my PR commits. I'll keep that in mind from now on. |
PR checklist
What changes did you make?
I added a rule which lets you enforce whether a space should exist or not before the opening parenthesis of a named function, anonymous function, async arrow function, method, or constructor. This is meant to be similar to the same-named rule for eslint.
Is there anything you'd like reviewers to focus on?
ts.Scanner
for checking spaces before parenthesis).