-
Notifications
You must be signed in to change notification settings - Fork 885
[enhancement] object-literal-shorthand / config to disallow shorthand #3268
Conversation
} | ||
} | ||
|
||
function walk(ctx: Lint.WalkContext<void>) { | ||
function walk(ctx: Lint.WalkContext<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.
The branches for both options don't share any code. Consider splitting into two separate functions. That will make it easier to understand and avoids unnecessary CPU cycles.
if (isPropertyAssignment(node)) { | ||
if (node.name.kind === ts.SyntaxKind.Identifier && | ||
if (isShorthandAssignment(node) && !allowShorthandAssignments) { | ||
ctx.addFailureAtNode(node, Rule.SHORTHAND_ASSIGNMENT); |
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.
fixing the shorthand to longhand syntax shouldn't be too hard I guess
name: ts.PropertyName, | ||
initializer: ts.FunctionExpression, | ||
sourceFile: ts.SourceFile, | ||
): [string, Lint.Fix] { |
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 all these purely stylistic changes. They don't add any value to the PR and make the diff harder to reason about.
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 think I have a TS formatter formatting on save. I'll take care of it.
function fixShorthandToLonghand(node: ts.ShorthandPropertyAssignment | ts.MethodDeclaration): Lint.Fix { | ||
let replacementText = isMethodDeclaration(node) | ||
? ": function" | ||
: `: ${node.name.getText()}`; |
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 can use node.name.text
here
function walk(ctx: Lint.WalkContext<void>) { | ||
function walk(ctx: Lint.WalkContext<Options>) { | ||
const { options: { allowShorthandAssignments } } = ctx; | ||
allowShorthandAssignments ? enforceShorthand(ctx) : disallowShorthand(ctx); |
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 can also do that in Rule#apply
:
this.applyWithFunction(sourceFile, this.ruleArguments.indexOf(OPTION_NEVER) === -1 ? enforceShorthand : disallowShorthand);
@@ -63,6 +103,19 @@ function walk(ctx: Lint.WalkContext<void>) { | |||
}); | |||
} | |||
|
|||
function fixShorthandToLonghand(node: ts.ShorthandPropertyAssignment | ts.MethodDeclaration): Lint.Fix { | |||
let replacementText = isMethodDeclaration(node) ? ": function" : `: ${node.name.getText()}`; |
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 can substitute node.name.getText()
with node.name.text
|
||
const asyncFn = { | ||
foo: async function() {}, | ||
bar: async function*() {} |
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.
needs a test for async shorthand
if (isGeneratorFunction(node)) { | ||
const asteriskPosition = (node as ts.MethodDeclaration).asteriskToken!.getStart(); | ||
fixes.push(Lint.Replacement.replaceFromTo(asteriskPosition, asteriskPosition + 1, "")); | ||
} |
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.
needs special handling for async
methods as well.
before you do that, just a suggestion to simplify the fix: replace the name with the function
keyword and insert the name plus the colon at the start of the declaration.
That way you don't have to handle the async keyword or the asterisk at all
src/configs/all.ts
Outdated
@@ -204,7 +204,7 @@ export const rules = { | |||
"no-unnecessary-type-assertion": true, | |||
"number-literal-format": true, | |||
"object-literal-key-quotes": [true, "consistent-as-needed"], | |||
"object-literal-shorthand": true, | |||
"object-literal-shorthand": [true, "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.
With the current implementation "always"
is not a valid option.
I'm struggling to simplify the fixer function b/c of this case:
|
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.
almost done
let | ||
replacementStart = (isAsync && node.modifiers !== undefined) ? getModifier(node, ts.SyntaxKind.AsyncKeyword)!.getStart() : -1; | ||
replacementStart = (isGenerator && !isAsync) ? (node as ts.MethodDeclaration).asteriskToken!.getStart() : -1; | ||
replacementStart = replacementStart === -1 ? node.name.getStart() : replacementStart; |
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 async
keyword is the only modifier allowed here, so replacementStart
can always be node.getStart()
`${node.name.getText()}:${isAsync ? " async" : ""} function${isGenerator ? "*" : ""}`, | ||
) | ||
/* tslint:disable:trailing-comma */ | ||
: Lint.Replacement.appendText(node.name.getStart(), `${node.name.text}: `) |
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.
consider moving the fix for ShorthandPropertyAssignment out of the function. It will make many conditions and type assertions unnecessary
function isShorthandAssignment(node: ts.Node): boolean { | ||
return ( | ||
isShorthandPropertyAssignment(node) || | ||
(isMethodDeclaration(node) && node.parent !== undefined ? node.parent.kind === ts.SyntaxKind.ObjectLiteralExpression : false) |
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.
node.parent
cannot be undefined
also no need for the conditional expression, just use &&
x: x | ||
} | ||
}; | ||
[OBJECT_LITERAL_DISALLOWED]: Shorthand property assignments have been disallowed. |
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 add a test case with class methods. these should be ignored by the rule
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 mean class members which instantiate object literals with shorthand props?
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 mean regular method declarations inside a class. They are ignored by the rule. I just want a test to ensure this won't regress.
class C {
doStuff() {} // shouldn't be an error
}
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.
Ahh of course. Thanks
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.
LGTM with a suggestion
return ts.forEachChild(ctx.sourceFile, function cb(node): void { | ||
if (isShorthandAssignment(node)) { | ||
ctx.addFailureAtNode( | ||
node, |
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.
looking at the tests, I think it's better to just show the error at node.name
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.
Went ahead and updated the error messages for shorthand-only too
I was just about to comment on that. I think showing the error only at the name is a bit too narrow for those errors. |
Haha maybe a bit presumptuous on my part. Anyway, we made it! Thanks as always for your help/patience. |
Thanks @aervin |
PR checklist
Overview of change:
Can pass argument "never" to object-literal-shorthand rule to disallow shorthand syntax. Currently, default is "always".