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

Commit

Permalink
[new-rule-option] Introduce new typedef rule option (variable-declara…
Browse files Browse the repository at this point in the history
…tion-ignore-function) (#4769)

* Introduce new typedef rule option (variable-declaration-ignore-function)

Ignores typedef requirement for vars for arrow and non arrow functions.

Fixes: #2654

* Fix linting issues

* Include ignore typedef for member var declaration

* Fix linter issue

* Process PR comments, remove comments from test + add test cases
  • Loading branch information
michaelw85 authored and Josh Goldberg committed Jul 4, 2019
1 parent 8056e63 commit 1d5d624
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 13 deletions.
59 changes: 46 additions & 13 deletions src/rules/typedefRule.ts
Expand Up @@ -29,6 +29,7 @@ interface Options {
"arrow-parameter"?: boolean;
"property-declaration"?: boolean;
"variable-declaration"?: boolean;
"variable-declaration-ignore-function"?: boolean;
"member-variable-declaration"?: boolean;
"object-destructuring"?: boolean;
"array-destructuring"?: boolean;
Expand All @@ -41,6 +42,7 @@ const OPTION_PARAMETER: Option = "parameter";
const OPTION_ARROW_PARAMETER: Option = "arrow-parameter";
const OPTION_PROPERTY_DECLARATION: Option = "property-declaration";
const OPTION_VARIABLE_DECLARATION: Option = "variable-declaration";
const OPTION_VARIABLE_DECLARATION_IGNORE_FUNCTION: Option = "variable-declaration-ignore-function";
const OPTION_MEMBER_VARIABLE_DECLARATION: Option = "member-variable-declaration";
const OPTION_OBJECT_DESTRUCTURING: Option = "object-destructuring";
const OPTION_ARRAY_DESTRUCTURING: Option = "array-destructuring";
Expand All @@ -67,6 +69,7 @@ export class Rule extends Lint.Rules.AbstractRule {
* \`"${OPTION_ARROW_PARAMETER}"\` checks type specifier of function parameters for arrow functions.
* \`"${OPTION_PROPERTY_DECLARATION}"\` checks return types of interface properties.
* \`"${OPTION_VARIABLE_DECLARATION}"\` checks non-binding variable declarations.
* \`"${OPTION_VARIABLE_DECLARATION_IGNORE_FUNCTION}"\` ignore variable declarations for non-arrow and arrow functions.
* \`"${OPTION_MEMBER_VARIABLE_DECLARATION}"\` checks member variable declarations.
* \`"${OPTION_OBJECT_DESTRUCTURING}"\` checks object destructuring declarations.
* \`"${OPTION_ARRAY_DESTRUCTURING}"\` checks array destructuring declarations.`,
Expand All @@ -81,13 +84,14 @@ export class Rule extends Lint.Rules.AbstractRule {
OPTION_ARROW_PARAMETER,
OPTION_PROPERTY_DECLARATION,
OPTION_VARIABLE_DECLARATION,
OPTION_VARIABLE_DECLARATION_IGNORE_FUNCTION,
OPTION_MEMBER_VARIABLE_DECLARATION,
OPTION_OBJECT_DESTRUCTURING,
OPTION_ARRAY_DESTRUCTURING,
],
},
minLength: 0,
maxLength: 7,
maxLength: 10,
},
optionExamples: [
[true, OPTION_CALL_SIGNATURE, OPTION_PARAMETER, OPTION_MEMBER_VARIABLE_DECLARATION],
Expand Down Expand Up @@ -153,7 +157,8 @@ class TypedefWalker extends Lint.AbstractWalker<Options> {
}
}

private checkParameter({ parent, name, type }: ts.ParameterDeclaration): void {
private checkParameter(node: ts.Node): void {
const { parent, name, type } = node as ts.ParameterDeclaration;
const isArrowFunction = parent.kind === ts.SyntaxKind.ArrowFunction;

const option = (() => {
Expand All @@ -177,11 +182,20 @@ class TypedefWalker extends Lint.AbstractWalker<Options> {
// If this is an arrow function, it doesn't need to have a typedef on the property declaration
// as the typedefs can be on the function's parameters instead
if (initializer === undefined || initializer.kind !== ts.SyntaxKind.ArrowFunction) {
if (
this.options[OPTION_VARIABLE_DECLARATION_IGNORE_FUNCTION] === true &&
initializer !== undefined &&
initializer.kind === ts.SyntaxKind.FunctionExpression
) {
return;
}
this.checkTypeAnnotation("member-variable-declaration", name, type, name);
}
}

private checkVariableDeclaration({ parent, name, type }: ts.VariableDeclaration): void {
private checkVariableDeclaration(node: ts.Node): void {
const { parent, name, type } = node as ts.VariableDeclaration;

// variable declarations should always have a grandparent, but check that to be on the safe side.
// catch statements will be the parent of the variable declaration
// for-in/for-of loops will be the gradparent of the variable declaration
Expand All @@ -193,20 +207,39 @@ class TypedefWalker extends Lint.AbstractWalker<Options> {
return;
}

const option = (() => {
switch (name.kind) {
case ts.SyntaxKind.ObjectBindingPattern:
return "object-destructuring";
case ts.SyntaxKind.ArrayBindingPattern:
return "array-destructuring";
default:
return "variable-declaration";
}
})();
let option: Option;

switch (name.kind) {
case ts.SyntaxKind.ObjectBindingPattern:
option = OPTION_OBJECT_DESTRUCTURING;
break;

case ts.SyntaxKind.ArrayBindingPattern:
option = OPTION_ARRAY_DESTRUCTURING;
break;

default:
option = OPTION_VARIABLE_DECLARATION;
}

if (this.shouldIgnoreVariableDeclaration(node)) {
return;
}

this.checkTypeAnnotation(option, name, type, name);
}

private shouldIgnoreVariableDeclaration(node: ts.Node): boolean {
const ignoreFunctions: boolean =
this.options[OPTION_VARIABLE_DECLARATION_IGNORE_FUNCTION] === true;

return (
ignoreFunctions &&
(utils.getChildOfKind(node, ts.SyntaxKind.ArrowFunction) !== undefined ||
utils.getChildOfKind(node, ts.SyntaxKind.FunctionExpression) !== undefined)
);
}

private checkTypeAnnotation(
option: Option,
location: ts.Node | ts.NodeArray<ts.Node>,
Expand Down
@@ -0,0 +1,23 @@
var foo = function(): void {};
let foo = function(): void {};
const foo = function(): void {};

var foo = (): void => {};
let foo = (): void => {};
const foo = (): void => {};

class Foo {
foo = (): void => {};
foo = function(): void {};
}

const foo: () => void = (): void => {};
const foo: () => void = function(): void {};

var noTypeDef = 'Should still fail';
~~~~~~~~~ [expected variable-declaration: 'noTypeDef' to have a typedef]

class NoTypeDef {
public noTypeDef = 'Should still fail';
~~~~~~~~~ [expected member-variable-declaration: 'noTypeDef' to have a typedef]
}
@@ -0,0 +1,10 @@
{
"rules": {
"typedef": [
true,
"variable-declaration",
"member-variable-declaration",
"variable-declaration-ignore-function"
]
}
}

0 comments on commit 1d5d624

Please sign in to comment.