From 4d0ff0dce4bdef031f19a2ec8891ae58f98616ee Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Tue, 30 Jan 2018 14:02:13 -0800 Subject: Add protected keyword to underscore lint rule --- .../rules/underscorePrivateAndProtectedRule.ts | 61 ++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 packages/tslint-config/rules/underscorePrivateAndProtectedRule.ts (limited to 'packages/tslint-config/rules/underscorePrivateAndProtectedRule.ts') diff --git a/packages/tslint-config/rules/underscorePrivateAndProtectedRule.ts b/packages/tslint-config/rules/underscorePrivateAndProtectedRule.ts new file mode 100644 index 000000000..2f05b0c18 --- /dev/null +++ b/packages/tslint-config/rules/underscorePrivateAndProtectedRule.ts @@ -0,0 +1,61 @@ +import * as Lint from 'tslint'; +import * as ts from 'typescript'; + +const UNDERSCORE = '_'; + +type RelevantClassMember = + | ts.MethodDeclaration + | ts.PropertyDeclaration + | ts.GetAccessorDeclaration + | ts.SetAccessorDeclaration; + +// Copied from: https://github.com/DanielRosenwasser/underscore-privates-tslint-rule +// The version on github is not published on npm +export class Rule extends Lint.Rules.AbstractRule { + public static FAILURE_STRING = 'private and protected members must be prefixed with an underscore'; + + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + return this.applyWithFunction(sourceFile, walk); + } +} +function walk(ctx: Lint.WalkContext): void { + traverse(ctx.sourceFile); + + function traverse(node: ts.Node): void { + checkNodeForViolations(ctx, node); + return ts.forEachChild(node, traverse); + } +} +function checkNodeForViolations(ctx: Lint.WalkContext, node: ts.Node): void { + if (!isRelevantClassMember(node)) { + return; + } + // The declaration might have a computed property name or a numeric name. + const name = node.name; + if (!nameIsIdentifier(name)) { + return; + } + if (!nameStartsWithUnderscore(name.text) && memberIsPrivate(node)) { + ctx.addFailureAtNode(name, Rule.FAILURE_STRING); + } +} +function isRelevantClassMember(node: ts.Node): node is RelevantClassMember { + switch (node.kind) { + case ts.SyntaxKind.MethodDeclaration: + case ts.SyntaxKind.PropertyDeclaration: + case ts.SyntaxKind.GetAccessor: + case ts.SyntaxKind.SetAccessor: + return true; + default: + return false; + } +} +function nameStartsWithUnderscore(text: string) { + return text.charCodeAt(0) === UNDERSCORE.charCodeAt(0); +} +function memberIsPrivate(node: ts.Declaration) { + return Lint.hasModifier(node.modifiers, ts.SyntaxKind.PrivateKeyword, ts.SyntaxKind.ProtectedKeyword); +} +function nameIsIdentifier(node: ts.Node): node is ts.Identifier { + return node.kind === ts.SyntaxKind.Identifier; +} -- cgit v1.2.3