From 5c165a65fca4746b3e5122ed8c3add56f2d1a3ab Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 2 Mar 2019 16:53:05 -0500 Subject: [PATCH 1/3] Added an overloads-separate-docs option in completed-docs Opt-in (false by default) boolean flag that can be applied to functions and methods. --- src/rules/completed-docs/exclusionFactory.ts | 79 ++++---- src/rules/completedDocsRule.ts | 169 +++++++++++++----- .../accessors-public/tsconfig.json | 5 - .../completed-docs/accessors/tsconfig.json | 5 - .../completed-docs/defaults/tsconfig.json | 5 - .../default/test.ts.lint | 8 + .../default/tslint.json | 9 + .../false/test.ts.lint | 8 + .../overloads-separate-docs/false/tslint.json | 10 ++ .../overloads-separate-docs/true/test.ts.lint | 23 +++ .../overloads-separate-docs/true/tslint.json | 10 ++ .../interface-members/tsconfig.json | 5 - .../completed-docs/locations/tsconfig.json | 5 - .../default/test.ts.lint | 10 ++ .../default/tslint.json | 9 + .../false/test.ts.lint | 10 ++ .../overloads-separate-docs/false/tslint.json | 10 ++ .../overloads-separate-docs/true/test.ts.lint | 12 ++ .../overloads-separate-docs/true/tslint.json | 10 ++ .../privacies-private/tsconfig.json | 5 - .../privacies-protected/tsconfig.json | 5 - .../privacies-public/tsconfig.json | 5 - .../completed-docs/privacies/tsconfig.json | 5 - .../completed-docs/tags/content/tsconfig.json | 5 - .../tags/existence/tsconfig.json | 5 - test/rules/completed-docs/types/tsconfig.json | 5 - .../completed-docs/variables/tsconfig.json | 5 - .../completed-docs/visibilities/tsconfig.json | 5 - 28 files changed, 299 insertions(+), 148 deletions(-) delete mode 100644 test/rules/completed-docs/accessors-public/tsconfig.json delete mode 100644 test/rules/completed-docs/accessors/tsconfig.json delete mode 100644 test/rules/completed-docs/defaults/tsconfig.json create mode 100644 test/rules/completed-docs/functions/overloads-separate-docs/default/test.ts.lint create mode 100644 test/rules/completed-docs/functions/overloads-separate-docs/default/tslint.json create mode 100644 test/rules/completed-docs/functions/overloads-separate-docs/false/test.ts.lint create mode 100644 test/rules/completed-docs/functions/overloads-separate-docs/false/tslint.json create mode 100644 test/rules/completed-docs/functions/overloads-separate-docs/true/test.ts.lint create mode 100644 test/rules/completed-docs/functions/overloads-separate-docs/true/tslint.json delete mode 100644 test/rules/completed-docs/interface-members/tsconfig.json delete mode 100644 test/rules/completed-docs/locations/tsconfig.json create mode 100644 test/rules/completed-docs/methods/overloads-separate-docs/default/test.ts.lint create mode 100644 test/rules/completed-docs/methods/overloads-separate-docs/default/tslint.json create mode 100644 test/rules/completed-docs/methods/overloads-separate-docs/false/test.ts.lint create mode 100644 test/rules/completed-docs/methods/overloads-separate-docs/false/tslint.json create mode 100644 test/rules/completed-docs/methods/overloads-separate-docs/true/test.ts.lint create mode 100644 test/rules/completed-docs/methods/overloads-separate-docs/true/tslint.json delete mode 100644 test/rules/completed-docs/privacies-private/tsconfig.json delete mode 100644 test/rules/completed-docs/privacies-protected/tsconfig.json delete mode 100644 test/rules/completed-docs/privacies-public/tsconfig.json delete mode 100644 test/rules/completed-docs/privacies/tsconfig.json delete mode 100644 test/rules/completed-docs/tags/content/tsconfig.json delete mode 100644 test/rules/completed-docs/tags/existence/tsconfig.json delete mode 100644 test/rules/completed-docs/types/tsconfig.json delete mode 100644 test/rules/completed-docs/variables/tsconfig.json delete mode 100644 test/rules/completed-docs/visibilities/tsconfig.json diff --git a/src/rules/completed-docs/exclusionFactory.ts b/src/rules/completed-docs/exclusionFactory.ts index 7f9acc47986..3d66edb9d60 100644 --- a/src/rules/completed-docs/exclusionFactory.ts +++ b/src/rules/completed-docs/exclusionFactory.ts @@ -16,7 +16,7 @@ */ import { hasOwnProperty } from "../../utils"; -import { DocType } from "../completedDocsRule"; +import { DESCRIPTOR_OVERLOADS_SEPARATE_DOCS, DocType } from "../completedDocsRule"; import { BlockExclusion, IBlockExclusionDescriptor } from "./blockExclusion"; import { ClassExclusion, IClassExclusionDescriptor } from "./classExclusion"; @@ -24,48 +24,61 @@ import { Exclusion } from "./exclusion"; import { IInputExclusionDescriptors, InputExclusionDescriptor } from "./exclusionDescriptors"; import { ITagExclusionDescriptor, TagExclusion } from "./tagExclusion"; -export type ExclusionsMap = Map>>; +export type ExclusionsMap = Map; -export class ExclusionFactory { - public constructExclusionsMap(ruleArguments: IInputExclusionDescriptors[]): ExclusionsMap { - const exclusionsMap: ExclusionsMap = new Map(); +export interface DocTypeExclusions { + overloadsSeparateDocs?: boolean; + requirements: Array>; +} - for (const ruleArgument of ruleArguments) { - this.addRequirements(exclusionsMap, ruleArgument); - } +export const constructExclusionsMap = ( + ruleArguments: IInputExclusionDescriptors[], +): ExclusionsMap => { + const exclusions: ExclusionsMap = new Map(); - return exclusionsMap; + for (const ruleArgument of ruleArguments) { + addRequirements(exclusions, ruleArgument); } - private addRequirements(exclusionsMap: ExclusionsMap, descriptors: IInputExclusionDescriptors) { - if (typeof descriptors === "string") { - exclusionsMap.set(descriptors, this.createRequirementsForDocType(descriptors, {})); - return; - } + return exclusions; +}; - for (const docType in descriptors) { - if (hasOwnProperty(descriptors, docType)) { - exclusionsMap.set( - docType as DocType, - this.createRequirementsForDocType(docType as DocType, descriptors[docType]), - ); - } +const addRequirements = (exclusionsMap: ExclusionsMap, descriptors: IInputExclusionDescriptors) => { + if (typeof descriptors === "string") { + exclusionsMap.set(descriptors, createRequirementsForDocType(descriptors, {})); + return; + } + + for (const docType in descriptors) { + if (hasOwnProperty(descriptors, docType)) { + exclusionsMap.set( + docType as DocType, + createRequirementsForDocType(docType as DocType, descriptors[docType]), + ); } } +}; - private createRequirementsForDocType(docType: DocType, descriptor: InputExclusionDescriptor) { - const requirements = []; +const createRequirementsForDocType = (docType: DocType, descriptor: InputExclusionDescriptor) => { + const requirements = []; + let overloadsSeparateDocs = false; - if (docType === "methods" || docType === "properties") { - requirements.push(new ClassExclusion(descriptor as IClassExclusionDescriptor)); - } else { - requirements.push(new BlockExclusion(descriptor as IBlockExclusionDescriptor)); - } + if (typeof descriptor === "object" && DESCRIPTOR_OVERLOADS_SEPARATE_DOCS in descriptor) { + overloadsSeparateDocs = !!(descriptor as any)[DESCRIPTOR_OVERLOADS_SEPARATE_DOCS]; + } - if ((descriptor as ITagExclusionDescriptor).tags !== undefined) { - requirements.push(new TagExclusion(descriptor as ITagExclusionDescriptor)); - } + if (docType === "methods" || docType === "properties") { + requirements.push(new ClassExclusion(descriptor as IClassExclusionDescriptor)); + } else { + requirements.push(new BlockExclusion(descriptor as IBlockExclusionDescriptor)); + } - return requirements; + if ((descriptor as ITagExclusionDescriptor).tags !== undefined) { + requirements.push(new TagExclusion(descriptor as ITagExclusionDescriptor)); } -} + + return { + overloadsSeparateDocs, + requirements, + }; +}; diff --git a/src/rules/completedDocsRule.ts b/src/rules/completedDocsRule.ts index efffcd3330a..328110719ed 100644 --- a/src/rules/completedDocsRule.ts +++ b/src/rules/completedDocsRule.ts @@ -21,7 +21,7 @@ import * as ts from "typescript"; import * as Lint from "../index"; import { IInputExclusionDescriptors } from "./completed-docs/exclusionDescriptors"; -import { ExclusionFactory, ExclusionsMap } from "./completed-docs/exclusionFactory"; +import { constructExclusionsMap, ExclusionsMap } from "./completed-docs/exclusionFactory"; export const ALL = "all"; @@ -38,6 +38,7 @@ export const ARGUMENT_VARIABLES = "variables"; export const DESCRIPTOR_TAGS = "tags"; export const DESCRIPTOR_LOCATIONS = "locations"; +export const DESCRIPTOR_OVERLOADS_SEPARATE_DOCS = "overloads-separate-docs"; export const DESCRIPTOR_PRIVACIES = "privacies"; export const DESCRIPTOR_VISIBILITIES = "visibilities"; @@ -159,6 +160,26 @@ export class Rule extends Lint.Rules.AbstractRule { type: "object", }; + public static ARGUMENT_DESCRIPTOR_FUNCTION = { + properties: { + ...Rule.ARGUMENT_DESCRIPTOR_BLOCK.properties, + [DESCRIPTOR_OVERLOADS_SEPARATE_DOCS]: { + type: "boolean", + }, + }, + type: "object", + }; + + public static ARGUMENT_DESCRIPTOR_METHOD = { + properties: { + ...Rule.ARGUMENT_DESCRIPTOR_CLASS.properties, + [DESCRIPTOR_OVERLOADS_SEPARATE_DOCS]: { + type: "boolean", + }, + }, + type: "object", + }; + /* tslint:disable:object-literal-sort-keys */ public static metadata: Lint.IRuleMetadata = { ruleName: "completed-docs", @@ -183,6 +204,8 @@ export class Rule extends Lint.Rules.AbstractRule { * \`"${ALL}"\` * \`"${VISIBILITY_EXPORTED}"\` * \`"${VISIBILITY_INTERNAL}"\` + * \`"${ARGUMENT_FUNCTIONS}"\` \`"${ARGUMENT_METHODS}"\` may also specify \`"${DESCRIPTOR_OVERLOADS_SEPARATE_DOCS}"\` + to indicate that each overload should have its own documentation, which is \`false\` by default. * All types may also provide \`"${DESCRIPTOR_TAGS}"\` with members specifying tags that allow the docs to not have a body. * \`"${TAGS_FOR_CONTENT}"\`: Object mapping tags to \`RegExp\` bodies content allowed to count as complete docs. @@ -224,9 +247,9 @@ export class Rule extends Lint.Rules.AbstractRule { [ARGUMENT_CLASSES]: Rule.ARGUMENT_DESCRIPTOR_BLOCK, [ARGUMENT_ENUMS]: Rule.ARGUMENT_DESCRIPTOR_BLOCK, [ARGUMENT_ENUM_MEMBERS]: Rule.ARGUMENT_DESCRIPTOR_BLOCK, - [ARGUMENT_FUNCTIONS]: Rule.ARGUMENT_DESCRIPTOR_BLOCK, + [ARGUMENT_FUNCTIONS]: Rule.ARGUMENT_DESCRIPTOR_FUNCTION, [ARGUMENT_INTERFACES]: Rule.ARGUMENT_DESCRIPTOR_BLOCK, - [ARGUMENT_METHODS]: Rule.ARGUMENT_DESCRIPTOR_CLASS, + [ARGUMENT_METHODS]: Rule.ARGUMENT_DESCRIPTOR_METHOD, [ARGUMENT_NAMESPACES]: Rule.ARGUMENT_DESCRIPTOR_BLOCK, [ARGUMENT_PROPERTIES]: Rule.ARGUMENT_DESCRIPTOR_CLASS, [ARGUMENT_TYPES]: Rule.ARGUMENT_DESCRIPTOR_BLOCK, @@ -264,7 +287,7 @@ export class Rule extends Lint.Rules.AbstractRule { rationale: Lint.Utils.dedent` Helps ensure important components are documented. - Note: use this rule sparingly. It's better to have self-documenting names on components with single, consice responsibilities. + Note: use this rule sparingly. It's better to have self-documenting names on components with single, concise responsibilities. Comments that only restate the names of variables add nothing to code, and can easily become outdated. `, type: "style", @@ -272,8 +295,6 @@ export class Rule extends Lint.Rules.AbstractRule { }; /* tslint:enable:object-literal-sort-keys */ - private readonly exclusionFactory = new ExclusionFactory(); - public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { const options = this.getOptions(); const exclusionsMap = this.getExclusionsMap(options.ruleArguments); @@ -288,7 +309,7 @@ export class Rule extends Lint.Rules.AbstractRule { ruleArguments = [Rule.defaultArguments]; } - return this.exclusionFactory.constructExclusionsMap(ruleArguments); + return constructExclusionsMap(ruleArguments); } } @@ -364,7 +385,7 @@ function walk(context: Lint.WalkContext) { case ts.SyntaxKind.GetAccessor: case ts.SyntaxKind.SetAccessor: if (node.parent.kind !== ts.SyntaxKind.ObjectLiteralExpression) { - checkAccessorNode(node as ts.AccessorDeclaration); + checkAccessorNode(node as ts.AccessorDeclaration, ARGUMENT_PROPERTIES); } } @@ -373,29 +394,29 @@ function walk(context: Lint.WalkContext) { function checkNode( node: ts.NamedDeclaration, - nodeType: DocType, + docType: DocType, requirementNode: ts.Node = node, ): void { - if (!nodeIsExcluded(node, nodeType, requirementNode) && !nodeHasDocs(node)) { - addDocumentationFailure(node, describeNode(nodeType), requirementNode); + if (!nodeIsExcluded(node, docType, requirementNode) && !nodeHasDocs(node, docType)) { + addDocumentationFailure(node, describeDocType(docType), requirementNode); } } - function checkAccessorNode(node: ts.AccessorDeclaration): void { - if (nodeIsExcluded(node, ARGUMENT_PROPERTIES, node) || nodeHasDocs(node)) { + function checkAccessorNode(node: ts.AccessorDeclaration, docType: DocType): void { + if (nodeIsExcluded(node, ARGUMENT_PROPERTIES, node) || nodeHasDocs(node, docType)) { return; } const correspondingAccessor = getCorrespondingAccessor(node); - if (correspondingAccessor === undefined || !nodeHasDocs(correspondingAccessor)) { + if (correspondingAccessor === undefined || !nodeHasDocs(correspondingAccessor, docType)) { addDocumentationFailure(node, ARGUMENT_PROPERTIES, node); } } function nodeIsExcluded( node: ts.NamedDeclaration, - nodeType: DocType, + docType: DocType, requirementNode: ts.Node, ): boolean { const { name } = node; @@ -403,13 +424,13 @@ function walk(context: Lint.WalkContext) { return true; } - const exclusions = context.options.get(nodeType); + const exclusions = context.options.get(docType); if (exclusions === undefined) { return true; } - for (const exclusion of exclusions) { - if (exclusion.excludes(requirementNode)) { + for (const requirement of exclusions.requirements) { + if (requirement.excludes(requirementNode)) { return true; } } @@ -417,8 +438,8 @@ function walk(context: Lint.WalkContext) { return false; } - function nodeHasDocs(node: ts.Node): boolean { - const docs = getApparentJsDoc(node); + function nodeHasDocs(node: ts.Node, docType: DocType): boolean { + const docs = getApparentJsDoc(node, docType, context.sourceFile); if (docs === undefined) { return false; } @@ -430,14 +451,80 @@ function walk(context: Lint.WalkContext) { return comments.length !== 0; } + /** + * @see https://github.com/ajafff/tsutils/issues/16 + */ + function getApparentJsDoc( + node: ts.Node, + docType: DocType, + sourceFile: ts.SourceFile, + ): ts.JSDoc[] | undefined { + if (ts.isVariableDeclaration(node)) { + if (variableIsAfterFirstInDeclarationList(node)) { + return undefined; + } + + node = node.parent; + } + + if (ts.isVariableDeclarationList(node)) { + node = node.parent; + } + + const equivalentNodesForDocs: ts.Node[] = getEquivalentNodesForDocs(node, docType); + + return equivalentNodesForDocs + .map(docsNode => tsutils.getJsDoc(docsNode, sourceFile)) + .filter(nodeDocs => nodeDocs !== undefined) + .reduce((docs, moreDocs) => [...docs, ...moreDocs], []); + } + + /** + * @see https://github.com/palantir/tslint/issues/4416 + */ + function getEquivalentNodesForDocs(node: ts.Node, docType: DocType): ts.Node[] { + const exclusions = context.options.get(docType); + if (exclusions === undefined || exclusions.overloadsSeparateDocs) { + return [node]; + } + + if (tsutils.isFunctionDeclaration(node) && node.name !== undefined) { + const functionName = node.name.text; + + return getSiblings(node).filter( + child => + tsutils.isFunctionDeclaration(child) && + child.name !== undefined && + child.name.text === functionName, + ); + } + + if ( + tsutils.isMethodDeclaration(node) && + tsutils.isIdentifier(node.name) && + tsutils.isClassDeclaration(node.parent) + ) { + const methodName = node.name.text; + + return node.parent.members.filter( + member => + tsutils.isMethodDeclaration(member) && + tsutils.isIdentifier(member.name) && + member.name.text === methodName, + ); + } + + return [node]; + } + function addDocumentationFailure( node: ts.Node, - nodeType: string, + docType: string, requirementNode: ts.Node, ): void { const start = node.getStart(); const width = node.getText().split(/\r|\n/g)[0].length; - const description = describeDocumentationFailure(requirementNode, nodeType); + const description = describeDocumentationFailure(requirementNode, docType); context.addFailureAt(start, width, description); } @@ -466,25 +553,6 @@ function getCorrespondingAccessor(node: ts.AccessorDeclaration) { return undefined; } -/** - * @remarks See https://github.com/ajafff/tsutils/issues/16 - */ -function getApparentJsDoc(node: ts.Node): ts.JSDoc[] | undefined { - if (ts.isVariableDeclaration(node)) { - if (variableIsAfterFirstInDeclarationList(node)) { - return undefined; - } - - node = node.parent; - } - - if (ts.isVariableDeclarationList(node)) { - node = node.parent; - } - - return tsutils.getJsDoc(node); -} - function variableIsAfterFirstInDeclarationList(node: ts.VariableDeclaration): boolean { const parent = node.parent; if (parent === undefined) { @@ -494,7 +562,7 @@ function variableIsAfterFirstInDeclarationList(node: ts.VariableDeclaration): bo return ts.isVariableDeclarationList(parent) && node !== parent.declarations[0]; } -function describeDocumentationFailure(node: ts.Node, nodeType: string): string { +function describeDocumentationFailure(node: ts.Node, docType: string): string { let description = Rule.FAILURE_STRING_EXIST; if (node.modifiers !== undefined) { @@ -503,7 +571,7 @@ function describeDocumentationFailure(node: ts.Node, nodeType: string): string { .join(" ")} `; } - return `${description}${nodeType}.`; + return `${description}${docType}.`; } function describeModifier(kind: ts.SyntaxKind) { @@ -512,8 +580,19 @@ function describeModifier(kind: ts.SyntaxKind) { return alias !== undefined ? alias : description; } -function describeNode(nodeType: DocType): string { - return nodeType.replace("-", " "); +function describeDocType(docType: DocType): string { + return docType.replace("-", " "); +} + +function getSiblings(node: ts.Node) { + const { parent } = node; + + // Source files nest their statements within a node for getChildren() + if (ts.isSourceFile(parent)) { + return [...parent.statements]; + } + + return parent.getChildren()!; } function isGetAccessor(node: ts.Node): node is ts.GetAccessorDeclaration { diff --git a/test/rules/completed-docs/accessors-public/tsconfig.json b/test/rules/completed-docs/accessors-public/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/accessors-public/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/rules/completed-docs/accessors/tsconfig.json b/test/rules/completed-docs/accessors/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/accessors/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/rules/completed-docs/defaults/tsconfig.json b/test/rules/completed-docs/defaults/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/defaults/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/rules/completed-docs/functions/overloads-separate-docs/default/test.ts.lint b/test/rules/completed-docs/functions/overloads-separate-docs/default/test.ts.lint new file mode 100644 index 00000000000..0a47ae0c5d3 --- /dev/null +++ b/test/rules/completed-docs/functions/overloads-separate-docs/default/test.ts.lint @@ -0,0 +1,8 @@ +function emit(event: string, data: number): void; + +function emit(event: string, data: string): void; + +/** + * Exists in one place + */ +function emit(event: string, data:any) { } diff --git a/test/rules/completed-docs/functions/overloads-separate-docs/default/tslint.json b/test/rules/completed-docs/functions/overloads-separate-docs/default/tslint.json new file mode 100644 index 00000000000..3863a3cb511 --- /dev/null +++ b/test/rules/completed-docs/functions/overloads-separate-docs/default/tslint.json @@ -0,0 +1,9 @@ +{ + "rules": { + "completed-docs": [true, { + "functions": { + "privacies": ["all"] + } + }] + } +} diff --git a/test/rules/completed-docs/functions/overloads-separate-docs/false/test.ts.lint b/test/rules/completed-docs/functions/overloads-separate-docs/false/test.ts.lint new file mode 100644 index 00000000000..0a47ae0c5d3 --- /dev/null +++ b/test/rules/completed-docs/functions/overloads-separate-docs/false/test.ts.lint @@ -0,0 +1,8 @@ +function emit(event: string, data: number): void; + +function emit(event: string, data: string): void; + +/** + * Exists in one place + */ +function emit(event: string, data:any) { } diff --git a/test/rules/completed-docs/functions/overloads-separate-docs/false/tslint.json b/test/rules/completed-docs/functions/overloads-separate-docs/false/tslint.json new file mode 100644 index 00000000000..09d202a5894 --- /dev/null +++ b/test/rules/completed-docs/functions/overloads-separate-docs/false/tslint.json @@ -0,0 +1,10 @@ +{ + "rules": { + "completed-docs": [true, { + "functions": { + "overloads-separate-docs": false, + "privacies": ["all"] + } + }] + } +} diff --git a/test/rules/completed-docs/functions/overloads-separate-docs/true/test.ts.lint b/test/rules/completed-docs/functions/overloads-separate-docs/true/test.ts.lint new file mode 100644 index 00000000000..a016578605e --- /dev/null +++ b/test/rules/completed-docs/functions/overloads-separate-docs/true/test.ts.lint @@ -0,0 +1,23 @@ +function emit(event: string, data: number): void; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for functions.] + +function emit(event: string, data: string): void; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for functions.] + +/** + * Exists in one place + */ +function emit(event: string, data:any) { } + +{ + function a(event: string, data: number): void; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for functions.] + + function b(event: string, data: string): void; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for functions.] + + /** + * Exists in one place + */ + function b(event: string, data:any) { } +} diff --git a/test/rules/completed-docs/functions/overloads-separate-docs/true/tslint.json b/test/rules/completed-docs/functions/overloads-separate-docs/true/tslint.json new file mode 100644 index 00000000000..4609318d3db --- /dev/null +++ b/test/rules/completed-docs/functions/overloads-separate-docs/true/tslint.json @@ -0,0 +1,10 @@ +{ + "rules": { + "completed-docs": [true, { + "functions": { + "overloads-separate-docs": true, + "privacies": ["all"] + } + }] + } +} diff --git a/test/rules/completed-docs/interface-members/tsconfig.json b/test/rules/completed-docs/interface-members/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/interface-members/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/rules/completed-docs/locations/tsconfig.json b/test/rules/completed-docs/locations/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/locations/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/rules/completed-docs/methods/overloads-separate-docs/default/test.ts.lint b/test/rules/completed-docs/methods/overloads-separate-docs/default/test.ts.lint new file mode 100644 index 00000000000..bcf75d31dee --- /dev/null +++ b/test/rules/completed-docs/methods/overloads-separate-docs/default/test.ts.lint @@ -0,0 +1,10 @@ +class Foo { + emit(event: string, data: number): void; + + emit(event: string, data: string): void; + + /** + * Exists in one place + */ + emit(event: string, data:any) { } +} diff --git a/test/rules/completed-docs/methods/overloads-separate-docs/default/tslint.json b/test/rules/completed-docs/methods/overloads-separate-docs/default/tslint.json new file mode 100644 index 00000000000..3ed521af93c --- /dev/null +++ b/test/rules/completed-docs/methods/overloads-separate-docs/default/tslint.json @@ -0,0 +1,9 @@ +{ + "rules": { + "completed-docs": [true, { + "methods": { + "privacies": ["all"] + } + }] + } +} diff --git a/test/rules/completed-docs/methods/overloads-separate-docs/false/test.ts.lint b/test/rules/completed-docs/methods/overloads-separate-docs/false/test.ts.lint new file mode 100644 index 00000000000..bcf75d31dee --- /dev/null +++ b/test/rules/completed-docs/methods/overloads-separate-docs/false/test.ts.lint @@ -0,0 +1,10 @@ +class Foo { + emit(event: string, data: number): void; + + emit(event: string, data: string): void; + + /** + * Exists in one place + */ + emit(event: string, data:any) { } +} diff --git a/test/rules/completed-docs/methods/overloads-separate-docs/false/tslint.json b/test/rules/completed-docs/methods/overloads-separate-docs/false/tslint.json new file mode 100644 index 00000000000..39954196387 --- /dev/null +++ b/test/rules/completed-docs/methods/overloads-separate-docs/false/tslint.json @@ -0,0 +1,10 @@ +{ + "rules": { + "completed-docs": [true, { + "methods": { + "overloads-separate-docs": false, + "privacies": ["all"] + } + }] + } +} diff --git a/test/rules/completed-docs/methods/overloads-separate-docs/true/test.ts.lint b/test/rules/completed-docs/methods/overloads-separate-docs/true/test.ts.lint new file mode 100644 index 00000000000..918db1762b7 --- /dev/null +++ b/test/rules/completed-docs/methods/overloads-separate-docs/true/test.ts.lint @@ -0,0 +1,12 @@ +class Foo { + emit(event: string, data: number): void; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for methods.] + + emit(event: string, data: string): void; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Documentation must exist for methods.] + + /** + * Exists in one place + */ + emit(event: string, data:any) { } +} diff --git a/test/rules/completed-docs/methods/overloads-separate-docs/true/tslint.json b/test/rules/completed-docs/methods/overloads-separate-docs/true/tslint.json new file mode 100644 index 00000000000..4f47bedde12 --- /dev/null +++ b/test/rules/completed-docs/methods/overloads-separate-docs/true/tslint.json @@ -0,0 +1,10 @@ +{ + "rules": { + "completed-docs": [true, { + "methods": { + "overloads-separate-docs": true, + "privacies": ["all"] + } + }] + } +} diff --git a/test/rules/completed-docs/privacies-private/tsconfig.json b/test/rules/completed-docs/privacies-private/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/privacies-private/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/rules/completed-docs/privacies-protected/tsconfig.json b/test/rules/completed-docs/privacies-protected/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/privacies-protected/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/rules/completed-docs/privacies-public/tsconfig.json b/test/rules/completed-docs/privacies-public/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/privacies-public/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/rules/completed-docs/privacies/tsconfig.json b/test/rules/completed-docs/privacies/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/privacies/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/rules/completed-docs/tags/content/tsconfig.json b/test/rules/completed-docs/tags/content/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/tags/content/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/rules/completed-docs/tags/existence/tsconfig.json b/test/rules/completed-docs/tags/existence/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/tags/existence/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/rules/completed-docs/types/tsconfig.json b/test/rules/completed-docs/types/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/types/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/rules/completed-docs/variables/tsconfig.json b/test/rules/completed-docs/variables/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/variables/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/rules/completed-docs/visibilities/tsconfig.json b/test/rules/completed-docs/visibilities/tsconfig.json deleted file mode 100644 index 744a66c893a..00000000000 --- a/test/rules/completed-docs/visibilities/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} From 3ab2821d05ed3dc725486f11b09418202dabf1ac Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 6 Mar 2019 21:09:14 -0500 Subject: [PATCH 2/3] Adidahiya feedback: rename file to exclusions; option to overloads --- .../{exclusionFactory.ts => exclusions.ts} | 6 +++--- src/rules/completedDocsRule.ts | 10 +++++----- .../overloads-separate-docs/false/tslint.json | 2 +- .../functions/overloads-separate-docs/true/tslint.json | 2 +- .../methods/overloads-separate-docs/false/tslint.json | 2 +- .../methods/overloads-separate-docs/true/tslint.json | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) rename src/rules/completed-docs/{exclusionFactory.ts => exclusions.ts} (93%) diff --git a/src/rules/completed-docs/exclusionFactory.ts b/src/rules/completed-docs/exclusions.ts similarity index 93% rename from src/rules/completed-docs/exclusionFactory.ts rename to src/rules/completed-docs/exclusions.ts index 3d66edb9d60..f575fa2df9c 100644 --- a/src/rules/completed-docs/exclusionFactory.ts +++ b/src/rules/completed-docs/exclusions.ts @@ -16,7 +16,7 @@ */ import { hasOwnProperty } from "../../utils"; -import { DESCRIPTOR_OVERLOADS_SEPARATE_DOCS, DocType } from "../completedDocsRule"; +import { DESCRIPTOR_OVERLOADS, DocType } from "../completedDocsRule"; import { BlockExclusion, IBlockExclusionDescriptor } from "./blockExclusion"; import { ClassExclusion, IClassExclusionDescriptor } from "./classExclusion"; @@ -63,8 +63,8 @@ const createRequirementsForDocType = (docType: DocType, descriptor: InputExclusi const requirements = []; let overloadsSeparateDocs = false; - if (typeof descriptor === "object" && DESCRIPTOR_OVERLOADS_SEPARATE_DOCS in descriptor) { - overloadsSeparateDocs = !!(descriptor as any)[DESCRIPTOR_OVERLOADS_SEPARATE_DOCS]; + if (typeof descriptor === "object" && DESCRIPTOR_OVERLOADS in descriptor) { + overloadsSeparateDocs = !!(descriptor as any)[DESCRIPTOR_OVERLOADS]; } if (docType === "methods" || docType === "properties") { diff --git a/src/rules/completedDocsRule.ts b/src/rules/completedDocsRule.ts index 328110719ed..7a303f87557 100644 --- a/src/rules/completedDocsRule.ts +++ b/src/rules/completedDocsRule.ts @@ -21,7 +21,7 @@ import * as ts from "typescript"; import * as Lint from "../index"; import { IInputExclusionDescriptors } from "./completed-docs/exclusionDescriptors"; -import { constructExclusionsMap, ExclusionsMap } from "./completed-docs/exclusionFactory"; +import { constructExclusionsMap, ExclusionsMap } from "./completed-docs/exclusions"; export const ALL = "all"; @@ -38,7 +38,7 @@ export const ARGUMENT_VARIABLES = "variables"; export const DESCRIPTOR_TAGS = "tags"; export const DESCRIPTOR_LOCATIONS = "locations"; -export const DESCRIPTOR_OVERLOADS_SEPARATE_DOCS = "overloads-separate-docs"; +export const DESCRIPTOR_OVERLOADS = "overloads"; export const DESCRIPTOR_PRIVACIES = "privacies"; export const DESCRIPTOR_VISIBILITIES = "visibilities"; @@ -163,7 +163,7 @@ export class Rule extends Lint.Rules.AbstractRule { public static ARGUMENT_DESCRIPTOR_FUNCTION = { properties: { ...Rule.ARGUMENT_DESCRIPTOR_BLOCK.properties, - [DESCRIPTOR_OVERLOADS_SEPARATE_DOCS]: { + [DESCRIPTOR_OVERLOADS]: { type: "boolean", }, }, @@ -173,7 +173,7 @@ export class Rule extends Lint.Rules.AbstractRule { public static ARGUMENT_DESCRIPTOR_METHOD = { properties: { ...Rule.ARGUMENT_DESCRIPTOR_CLASS.properties, - [DESCRIPTOR_OVERLOADS_SEPARATE_DOCS]: { + [DESCRIPTOR_OVERLOADS]: { type: "boolean", }, }, @@ -204,7 +204,7 @@ export class Rule extends Lint.Rules.AbstractRule { * \`"${ALL}"\` * \`"${VISIBILITY_EXPORTED}"\` * \`"${VISIBILITY_INTERNAL}"\` - * \`"${ARGUMENT_FUNCTIONS}"\` \`"${ARGUMENT_METHODS}"\` may also specify \`"${DESCRIPTOR_OVERLOADS_SEPARATE_DOCS}"\` + * \`"${ARGUMENT_FUNCTIONS}"\` \`"${ARGUMENT_METHODS}"\` may also specify \`"${DESCRIPTOR_OVERLOADS}"\` to indicate that each overload should have its own documentation, which is \`false\` by default. * All types may also provide \`"${DESCRIPTOR_TAGS}"\` with members specifying tags that allow the docs to not have a body. diff --git a/test/rules/completed-docs/functions/overloads-separate-docs/false/tslint.json b/test/rules/completed-docs/functions/overloads-separate-docs/false/tslint.json index 09d202a5894..e7dd2c3f4d0 100644 --- a/test/rules/completed-docs/functions/overloads-separate-docs/false/tslint.json +++ b/test/rules/completed-docs/functions/overloads-separate-docs/false/tslint.json @@ -2,7 +2,7 @@ "rules": { "completed-docs": [true, { "functions": { - "overloads-separate-docs": false, + "overloads": false, "privacies": ["all"] } }] diff --git a/test/rules/completed-docs/functions/overloads-separate-docs/true/tslint.json b/test/rules/completed-docs/functions/overloads-separate-docs/true/tslint.json index 4609318d3db..8462098ec42 100644 --- a/test/rules/completed-docs/functions/overloads-separate-docs/true/tslint.json +++ b/test/rules/completed-docs/functions/overloads-separate-docs/true/tslint.json @@ -2,7 +2,7 @@ "rules": { "completed-docs": [true, { "functions": { - "overloads-separate-docs": true, + "overloads": true, "privacies": ["all"] } }] diff --git a/test/rules/completed-docs/methods/overloads-separate-docs/false/tslint.json b/test/rules/completed-docs/methods/overloads-separate-docs/false/tslint.json index 39954196387..a00c757c495 100644 --- a/test/rules/completed-docs/methods/overloads-separate-docs/false/tslint.json +++ b/test/rules/completed-docs/methods/overloads-separate-docs/false/tslint.json @@ -2,7 +2,7 @@ "rules": { "completed-docs": [true, { "methods": { - "overloads-separate-docs": false, + "overloads": false, "privacies": ["all"] } }] diff --git a/test/rules/completed-docs/methods/overloads-separate-docs/true/tslint.json b/test/rules/completed-docs/methods/overloads-separate-docs/true/tslint.json index 4f47bedde12..678606ada86 100644 --- a/test/rules/completed-docs/methods/overloads-separate-docs/true/tslint.json +++ b/test/rules/completed-docs/methods/overloads-separate-docs/true/tslint.json @@ -2,7 +2,7 @@ "rules": { "completed-docs": [true, { "methods": { - "overloads-separate-docs": true, + "overloads": true, "privacies": ["all"] } }] From 175a02098cd5d7c59a92f6b8bfe55112b096b29e Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 6 Mar 2019 21:09:44 -0500 Subject: [PATCH 3/3] oh, the lint error was about the assertion. DUh. --- src/rules/completedDocsRule.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rules/completedDocsRule.ts b/src/rules/completedDocsRule.ts index 7a303f87557..bdec70419df 100644 --- a/src/rules/completedDocsRule.ts +++ b/src/rules/completedDocsRule.ts @@ -592,7 +592,7 @@ function getSiblings(node: ts.Node) { return [...parent.statements]; } - return parent.getChildren()!; + return parent.getChildren(); } function isGetAccessor(node: ts.Node): node is ts.GetAccessorDeclaration {