Skip to content

Commit

Permalink
no-unnecessary-initializer: Convert to function (palantir#2707)
Browse files Browse the repository at this point in the history
  • Loading branch information
andy-hanson authored and nchen63 committed May 8, 2017
1 parent dcc73b5 commit 0645b9f
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 44 deletions.
80 changes: 36 additions & 44 deletions src/rules/noUnnecessaryInitializerRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

import * as utils from "tsutils";
import { isBindingPattern } from "tsutils";
import * as ts from "typescript";

import * as Lint from "../index";
Expand All @@ -40,62 +40,54 @@ export class Rule extends Lint.Rules.AbstractRule {
"Also, the type declaration does not need to include '| undefined'.";

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new Walker(sourceFile, this.getOptions()));
return this.applyWithFunction(sourceFile, walk);
}
}

class Walker extends Lint.RuleWalker {
public visitVariableDeclaration(node: ts.VariableDeclaration) {
if (utils.isBindingPattern(node.name)) {
for (const elem of node.name.elements) {
if (elem.kind === ts.SyntaxKind.BindingElement) {
this.checkInitializer(elem);
}
}
} else if (!Lint.isNodeFlagSet(node.parent!, ts.NodeFlags.Const)) {
this.checkInitializer(node);
}

super.visitVariableDeclaration(node);
}

public visitMethodDeclaration(node: ts.MethodDeclaration) {
this.checkSignature(node);
super.visitMethodDeclaration(node);
}
public visitFunctionDeclaration(node: ts.FunctionDeclaration) {
this.checkSignature(node);
super.visitFunctionDeclaration(node);
}
public visitConstructorDeclaration(node: ts.ConstructorDeclaration) {
this.checkSignature(node);
super.visitConstructorDeclaration(node);
}
function walk(ctx: Lint.WalkContext<void>): void {
ts.forEachChild(ctx.sourceFile, function cb(node: ts.Node): void {
switch (node.kind) {
case ts.SyntaxKind.BindingElement:
checkInitializer(node as ts.BindingElement);
break;

private checkSignature({ parameters }: ts.MethodDeclaration | ts.FunctionDeclaration | ts.ConstructorDeclaration) {
parameters.forEach((parameter, i) => {
if (isUndefined(parameter.initializer)) {
if (parametersAllOptionalAfter(parameters, i)) {
// No fix since they may want to remove '| undefined' from the type.
this.addFailureAtNode(parameter, Rule.FAILURE_STRING_PARAMETER);
} else {
this.failWithFix(parameter);
case ts.SyntaxKind.VariableDeclaration:
if (!isBindingPattern((node as ts.VariableDeclaration).name) && !Lint.isNodeFlagSet(node.parent!, ts.NodeFlags.Const)) {
checkInitializer(node as ts.VariableDeclaration);
}
break;

case ts.SyntaxKind.MethodDeclaration:
case ts.SyntaxKind.FunctionDeclaration:
case ts.SyntaxKind.Constructor: {
const { parameters } = node as ts.FunctionLikeDeclaration;
parameters.forEach((parameter, i) => {
if (isUndefined(parameter.initializer)) {
if (parametersAllOptionalAfter(parameters, i)) {
// No fix since they may want to remove '| undefined' from the type.
ctx.addFailureAtNode(parameter, Rule.FAILURE_STRING_PARAMETER);
} else {
failWithFix(parameter);
}
}
});
break;
}
});
}
}
ts.forEachChild(node, cb);
});

private checkInitializer(node: ts.VariableDeclaration | ts.BindingElement) {
function checkInitializer(node: ts.VariableDeclaration | ts.BindingElement) {
if (isUndefined(node.initializer)) {
this.failWithFix(node);
failWithFix(node);
}
}

private failWithFix(node: ts.VariableDeclaration | ts.BindingElement | ts.ParameterDeclaration) {
const fix = this.deleteFromTo(
function failWithFix(node: ts.VariableDeclaration | ts.BindingElement | ts.ParameterDeclaration) {
const fix = Lint.Replacement.deleteFromTo(
Lint.childOfKind(node, ts.SyntaxKind.EqualsToken)!.pos,
node.end);
this.addFailureAtNode(node, Rule.FAILURE_STRING, fix);
ctx.addFailureAtNode(node, Rule.FAILURE_STRING, fix);
}
}

Expand Down
2 changes: 2 additions & 0 deletions test/rules/no-unnecessary-initializer/test.ts.fix
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ declare function get<T>(): T
const { g } = get<{ g?: number }>();
const [h] = get<number[]>();

function f({ x }: { x?: number }) {}

3 changes: 3 additions & 0 deletions test/rules/no-unnecessary-initializer/test.ts.lint
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,8 @@ const { g = undefined } = get<{ g?: number }>();
const [h = undefined] = get<number[]>();
~~~~~~~~~~~~~ [0]

function f({ x = undefined }: { x?: number }) {}
~~~~~~~~~~~~~ [0]

[0]: Unnecessary initialization to 'undefined'.
[1]: Use an optional parameter instead of initializing to 'undefined'. Also, the type declaration does not need to include '| undefined'.

0 comments on commit 0645b9f

Please sign in to comment.