Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

object-literal-shorthand: various optimizations #3273

Merged
merged 1 commit into from
Oct 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
67 changes: 21 additions & 46 deletions src/rules/objectLiteralShorthandRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import {
getChildOfKind,
getModifier,
hasModifier,
isFunctionExpression,
isIdentifier,
Expand Down Expand Up @@ -64,15 +63,18 @@ export class Rule extends Lint.Rules.AbstractRule {

function disallowShorthandWalker(ctx: Lint.WalkContext<void>) {
return ts.forEachChild(ctx.sourceFile, function cb(node): void {
if (isShorthandAssignment(node)) {
if (isShorthandPropertyAssignment(node)) {
ctx.addFailureAtNode(
(node as ts.ShorthandPropertyAssignment).name,
node.name,
Rule.SHORTHAND_ASSIGNMENT,
isMethodDeclaration(node)
? fixShorthandMethodDeclaration(node)
: fixShorthandPropertyAssignment(node as ts.ShorthandPropertyAssignment),
Lint.Replacement.appendText(node.getStart(ctx.sourceFile), `${node.name.text}: `),
);
} else if (isMethodDeclaration(node) && node.parent!.kind === ts.SyntaxKind.ObjectLiteralExpression) {
ctx.addFailureAtNode(
node.name,
Rule.SHORTHAND_ASSIGNMENT,
fixShorthandMethodDeclaration(node, ctx.sourceFile),
);
return;
}
return ts.forEachChild(node, cb);
});
Expand All @@ -93,47 +95,27 @@ function enforceShorthandWalker(ctx: Lint.WalkContext<void>) {
// allow named function expressions
node.initializer.name === undefined) {
const [name, fix] = handleLonghandMethod(node.name, node.initializer, ctx.sourceFile);
ctx.addFailureAtNode(node, `${Rule.LONGHAND_METHOD}('{${name}() {...}}').`, fix);
ctx.addFailure(
node.getStart(ctx.sourceFile),
getChildOfKind(node.initializer, ts.SyntaxKind.OpenParenToken, ctx.sourceFile)!.pos,
`${Rule.LONGHAND_METHOD}('{${name}() {...}}').`,
fix,
);
}
}
return ts.forEachChild(node, cb);
});
}

function fixShorthandMethodDeclaration(node: ts.MethodDeclaration): Lint.Fix {
function fixShorthandMethodDeclaration(node: ts.MethodDeclaration, sourceFile: ts.SourceFile) {
const isGenerator = node.asteriskToken !== undefined;
const isAsync = hasModifier(node.modifiers, ts.SyntaxKind.AsyncKeyword);
let
replacementStart =
(isAsync && node.modifiers !== undefined)
? getModifier(node, ts.SyntaxKind.AsyncKeyword)!.getStart()
: node.name.getStart();
replacementStart =
(isGenerator && !isAsync)
? node.asteriskToken!.getStart()
: node.name.getStart();

const fixes: Lint.Fix = [
Lint.Replacement.replaceFromTo(
replacementStart,
node.name.end,
`${node.name.getText()}:${isAsync ? " async" : ""} function${isGenerator ? "*" : ""}`,
),
];

if (isAsync) {
fixes.unshift(
Lint.Replacement.deleteFromTo(
getModifier(node, ts.SyntaxKind.AsyncKeyword)!.getStart(),
node.name.getStart(),
),
);
}
return fixes;
}

function fixShorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment): Lint.Fix {
return Lint.Replacement.appendText(node.name.getStart(), `${node.name.text}: `);
return Lint.Replacement.replaceFromTo(
node.getStart(sourceFile),
node.name.end,
`${node.name.getText(sourceFile)}:${isAsync ? " async" : ""} function${isGenerator ? "*" : ""}`,
);
}

function handleLonghandMethod(name: ts.PropertyName, initializer: ts.FunctionExpression, sourceFile: ts.SourceFile): [string, Lint.Fix] {
Expand All @@ -151,10 +133,3 @@ function handleLonghandMethod(name: ts.PropertyName, initializer: ts.FunctionExp
}
return [prefix + sourceFile.text.substring(nameStart, name.end), fix];
}

function isShorthandAssignment(node: ts.Node): boolean {
return (
isShorthandPropertyAssignment(node) ||
(isMethodDeclaration(node) && node.parent!.kind === ts.SyntaxKind.ObjectLiteralExpression)
);
}
2 changes: 2 additions & 0 deletions test/rules/object-literal-shorthand/always/test.ts.fix
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,5 @@ const asyncFn = {
async foo() {},
async *bar() {}
}

({foo} = {foo});
16 changes: 10 additions & 6 deletions test/rules/object-literal-shorthand/always/test.ts.lint
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const bad = {
w: function() {},
~~~~~~~~~~~~~~~~ [Expected method shorthand in object literal ('{w() {...}}').]
~~~~~~~~~~~ [Expected method shorthand in object literal ('{w() {...}}').]
x: function *() {},
~~~~~~~~~~~~~~~~~~ [Expected method shorthand in object literal ('{*x() {...}}').]
~~~~~~~~~~~~~ [Expected method shorthand in object literal ('{*x() {...}}').]
[y]: function() {},
~~~~~~~~~~~~~~~~~~ [Expected method shorthand in object literal ('{[y]() {...}}').]
~~~~~~~~~~~~~ [Expected method shorthand in object literal ('{[y]() {...}}').]
z: z
~~~~ [Expected property shorthand in object literal ('{z}').]
};
Expand All @@ -26,7 +26,7 @@ const namedFunctions = {

const quotes = {
"foo-bar": function() {},
~~~~~~~~~~~~~~~~~~~~~~~~ [Expected method shorthand in object literal ('{"foo-bar"() {...}}').]
~~~~~~~~~~~~~~~~~~~ [Expected method shorthand in object literal ('{"foo-bar"() {...}}').]
"foo-bar"() {}
};

Expand All @@ -43,7 +43,11 @@ const extraCases = {

const asyncFn = {
foo: async function() {},
~~~~~~~~~~~~~~~~~~~~~~~~ [Expected method shorthand in object literal ('{async foo() {...}}').]
~~~~~~~~~~~~~~~~~~~ [Expected method shorthand in object literal ('{async foo() {...}}').]
bar: async function*() {}
~~~~~~~~~~~~~~~~~~~~~~~~~ [Expected method shorthand in object literal ('{async *bar() {...}}').]
~~~~~~~~~~~~~~~~~~~~ [Expected method shorthand in object literal ('{async *bar() {...}}').]
}

({foo: foo} = {foo: foo});
~~~~~~~~ [Expected property shorthand in object literal ('{foo}').]
~~~~~~~~ [Expected property shorthand in object literal ('{foo}').]
9 changes: 8 additions & 1 deletion test/rules/object-literal-shorthand/never/test.ts.fix
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ const asyncFn = {
};

const bad = {
w: function() {},
w: function() {
const alsoBad = {
bad: bad,
};
},
x: function*() {},
[y]: function() {},
z: z,
Expand Down Expand Up @@ -50,3 +54,6 @@ const extraCases = {
export class ClassA extends ClassZ {
testMethod() {}
}

({foo: foo} = {foo: foo});

12 changes: 11 additions & 1 deletion test/rules/object-literal-shorthand/never/test.ts.lint
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ const asyncFn = {
};

const bad = {
w() {},
w() {
~ [OBJECT_LITERAL_DISALLOWED]
const alsoBad = {
bad,
~~~ [OBJECT_LITERAL_DISALLOWED]
};
},
*x() {},
~ [OBJECT_LITERAL_DISALLOWED]
[y]() {},
Expand Down Expand Up @@ -59,4 +64,9 @@ const extraCases = {
export class ClassA extends ClassZ {
testMethod() {}
}

({foo} = {foo});
~~~ [OBJECT_LITERAL_DISALLOWED]
~~~ [OBJECT_LITERAL_DISALLOWED]

[OBJECT_LITERAL_DISALLOWED]: Shorthand property assignments have been disallowed.