Skip to content

Commit 473b1df

Browse files
josephperrottmmalerba
authored andcommitted
chore: create tslint rule to allow @HostListener and @HostBinding in abstract classes (#8036)
1 parent 24984f5 commit 473b1df

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import * as ts from 'typescript';
2+
import * as Lint from 'tslint';
3+
4+
export class Rule extends Lint.Rules.AbstractRule {
5+
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
6+
return this.applyWithWalker(new Walker(sourceFile, this.getOptions()));
7+
}
8+
}
9+
10+
class Walker extends Lint.RuleWalker {
11+
visitClassDeclaration(node: ts.ClassDeclaration) {
12+
if (!node.modifiers || !this.getOptions().length) { return; }
13+
14+
// Do not check the class if its abstract.
15+
if (!!node.modifiers.find(modifier => modifier.kind === ts.SyntaxKind.AbstractKeyword)) {
16+
return;
17+
}
18+
19+
node.members
20+
.filter(el => el.decorators)
21+
.map(el => el.decorators!)
22+
.forEach(decorators => {
23+
decorators.forEach(decorator => {
24+
const decoratorText: string = decorator.getChildAt(1).getText();
25+
const matchedDecorator: string = this.getOptions().find(
26+
(item: string) => decoratorText.startsWith(item));
27+
if (!!matchedDecorator) {
28+
this.addFailureFromStartToEnd(decorator.getChildAt(1).pos - 1, decorator.end,
29+
`The @${matchedDecorator} decorator may only be used in abstract classes. In ` +
30+
`concrete classes use \`host\` in the component definition instead.`);
31+
}
32+
});
33+
});
34+
35+
super.visitClassDeclaration(node);
36+
}
37+
}

tslint.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,7 @@
7575
["fit"],
7676
["fdescribe"],
7777
["xit"],
78-
["xdescribe"],
79-
{ "name": "HostBinding", "message": "Use `host` in the component definition instead." },
80-
{ "name": "HostListener", "message": "Use `host` in the component definition instead." }
78+
["xdescribe"]
8179
],
8280
// Disallows importing the whole RxJS library. Submodules can be still imported.
8381
"import-blacklist": [true, "rxjs"],
@@ -87,6 +85,11 @@
8785
// Custom Rules
8886
"ts-loader": true,
8987
"no-exposed-todo": true,
88+
"no-host-decorator-in-concrete": [
89+
true,
90+
"HostBinding",
91+
"HostListener"
92+
],
9093
"validate-decorators": [true, {
9194
"Component": {
9295
"encapsulation": "\\.None$",

0 commit comments

Comments
 (0)