From 761bfb0d95de116f5279d8f63a711f09edf2ebd6 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Thu, 30 Nov 2017 09:56:19 +0100 Subject: [PATCH] completed-docs: exclude object literal methods [bugfix] `completed-docs`: don't require documentation on methods in object literals Also simplifies some other checks. --- src/rules/completedDocsRule.ts | 62 +++++++------------- test/rules/completed-docs/types/test.ts.lint | 35 +++++------ 2 files changed, 39 insertions(+), 58 deletions(-) diff --git a/src/rules/completedDocsRule.ts b/src/rules/completedDocsRule.ts index 2a9ce3626ee..96310acb07e 100644 --- a/src/rules/completedDocsRule.ts +++ b/src/rules/completedDocsRule.ts @@ -15,7 +15,6 @@ * limitations under the License. */ -import { isVariableDeclarationList, isVariableStatement } from "tsutils"; import * as ts from "typescript"; import * as Lint from "../index"; @@ -319,12 +318,11 @@ function walk(context: Lint.WalkContext, typeChecker: ts.TypeChec case ts.SyntaxKind.EnumDeclaration: checkNode(node as ts.EnumDeclaration, ARGUMENT_ENUMS); - break; - - case ts.SyntaxKind.EnumMember: - // Enum members don't have modifiers, so use the parent - // enum declaration when checking the requirements. - checkNode(node as ts.EnumMember, ARGUMENT_ENUM_MEMBERS, node.parent); + for (const member of (node as ts.EnumDeclaration).members) { + // Enum members don't have modifiers, so use the parent + // enum declaration when checking the requirements. + checkNode(member, ARGUMENT_ENUM_MEMBERS, node); + } break; case ts.SyntaxKind.FunctionDeclaration: @@ -336,7 +334,9 @@ function walk(context: Lint.WalkContext, typeChecker: ts.TypeChec break; case ts.SyntaxKind.MethodDeclaration: - checkNode(node as ts.MethodDeclaration, ARGUMENT_METHODS); + if (node.parent!.kind !== ts.SyntaxKind.ObjectLiteralExpression) { + checkNode(node as ts.MethodDeclaration, ARGUMENT_METHODS); + } break; case ts.SyntaxKind.ModuleDeclaration: @@ -351,13 +351,23 @@ function walk(context: Lint.WalkContext, typeChecker: ts.TypeChec checkNode(node as ts.TypeAliasDeclaration, ARGUMENT_TYPES); break; - case ts.SyntaxKind.VariableDeclaration: - checkVariable(node as ts.VariableDeclaration); + case ts.SyntaxKind.VariableStatement: + // Only check variables at the namespace/module-level or file-level + // and not variables declared inside functions and other things. + switch (node.parent!.kind) { + case ts.SyntaxKind.SourceFile: + case ts.SyntaxKind.ModuleBlock: + for (const declaration of (node as ts.VariableStatement).declarationList.declarations) { + checkNode(declaration, ARGUMENT_VARIABLES, node); + } + } break; case ts.SyntaxKind.GetAccessor: case ts.SyntaxKind.SetAccessor: - checkAccessor(node as ts.NamedDeclaration); + if (node.parent!.kind !== ts.SyntaxKind.ObjectLiteralExpression) { + checkNode(node as ts.AccessorDeclaration, ARGUMENT_PROPERTIES); + } } return ts.forEachChild(node, cb); @@ -389,36 +399,6 @@ function walk(context: Lint.WalkContext, typeChecker: ts.TypeChec checkComments(node, describeNode(nodeType), comments, requirementNode); } - function checkVariable(node: ts.VariableDeclaration) { - // Only check variables in variable declaration lists - // and not variables in catch clauses and for loops. - const list = node.parent!; - if (!isVariableDeclarationList(list)) { - return; - } - - const statement = list.parent!; - if (!isVariableStatement(statement)) { - return; - } - - // Only check variables at the namespace/module-level or file-level - // and not variables declared inside functions and other things. - switch (statement.parent!.kind) { - case ts.SyntaxKind.SourceFile: - case ts.SyntaxKind.ModuleBlock: - checkNode(node, ARGUMENT_VARIABLES, statement); - } - } - - function checkAccessor(node: ts.NamedDeclaration): void { - // Properties in object literal expressions do not - // require documentation, so neither do accessors. - if (node.parent!.kind !== ts.SyntaxKind.ObjectLiteralExpression) { - checkNode(node, ARGUMENT_PROPERTIES); - } - } - function checkComments(node: ts.Node, nodeDescriptor: string, comments: ts.SymbolDisplayPart[], requirementNode: ts.Node) { if (comments.map((comment: ts.SymbolDisplayPart) => comment.text).join("").trim() === "") { addDocumentationFailure(node, nodeDescriptor, requirementNode); diff --git a/test/rules/completed-docs/types/test.ts.lint b/test/rules/completed-docs/types/test.ts.lint index a91d520b47b..3a112afb1f0 100644 --- a/test/rules/completed-docs/types/test.ts.lint +++ b/test/rules/completed-docs/types/test.ts.lint @@ -50,54 +50,54 @@ class BadClass { } /** - * + * */ class EmptyClass { ~~~~~~~~~~~~~~~~~~ [Documentation must exist for classes.] /** - * + * */ emptyDefaultProperty; ~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for properties.] /** - * + * */ public emptyPublicProperty; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for public properties.] /** - * + * */ protected emptyProtectedProperty; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for protected properties.] /** - * + * */ private emptyPrivateProperty; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for private properties.] /** - * + * */ emptyDefaultMethod() { } ~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for methods.] /** - * + * */ public emptyPublicMethod() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for public methods.] /** - * + * */ protected emptyProtectedMethod() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for protected methods.] /** - * + * */ private emptyPrivateMethod() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for private methods.] @@ -240,7 +240,7 @@ enum BadEnum { } ~~~~~~~~~~~~~~~~ [Documentation must exist for enums.] /** - * + * */ enum EmptyEnum { } ~~~~~~~~~~~~~~~~~~ [Documentation must exist for enums.] @@ -267,7 +267,7 @@ function BadFunction() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for functions.] /** - * + * */ function EmptyFunction() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for functions.] @@ -281,7 +281,7 @@ interface BadInterface { } ~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for interfaces.] /** - * + * */ interface EmptyInterface { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for interfaces.] @@ -295,7 +295,7 @@ namespace BadNamespace { } ~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for namespaces.] /** - * + * */ namespace EmptyNamespace { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for namespaces.] @@ -309,7 +309,7 @@ type BadType = 1; ~~~~~~~~~~~~~~~~~ [Documentation must exist for types.] /** - * + * */ type EmptyType = 1; ~~~~~~~~~~~~~~~~~~~ [Documentation must exist for types.] @@ -323,7 +323,7 @@ type BadType = 1; ~~~~~~~~~~~~~~~~~ [Documentation must exist for types.] /** - * + * */ type EmptyType = 1; ~~~~~~~~~~~~~~~~~~~ [Documentation must exist for types.] @@ -337,7 +337,7 @@ const BadVariable = 1; ~~~~~~~~~~~~~~~ [Documentation must exist for variables.] /** - * + * */ const EmptyVariable = 1; ~~~~~~~~~~~~~~~~~ [Documentation must exist for variables.] @@ -348,10 +348,11 @@ const EmptyVariable = 1; const GoodVariable = 1; /** - * Properties and accessors in object literals should not require documentation. + * Properties, methods and accessors in object literals should not require documentation. */ let literal = { prop: 1, get accessor() { return literal.prop; }, set accessor(value) { literal.prop = value; } + someMethod() {} }