build: add rule to enforce static queries (#15963)

Adds a simplified tslint rule to enforce that we've explicitly set the `static` flag on relevant queries. We don't need the more advanced functionality from the one in angular/angular, because we don't have to figure out which value is correct, only that it is set.
This commit is contained in:
Kristiyan Kostadinov
2019-05-10 16:45:01 -04:00
committed by Jeremy Elbourn
parent 8ab0f6336c
commit de45fc0831
5 changed files with 42 additions and 3 deletions
@@ -54,7 +54,7 @@ interface PeriodicElement {
}
abstract class BaseTestComponent {
@ViewChild('table') table: ElementRef;
@ViewChild('table', {static: false}) table: ElementRef;
preservedValues = new Map<number, PeriodicElement>();
@@ -1050,7 +1050,7 @@ class CheckboxWithTabIndex {
<mat-checkbox></mat-checkbox>`,
})
class CheckboxUsingViewChild {
@ViewChild(MatCheckbox) checkbox: MatCheckbox;
@ViewChild(MatCheckbox, {static: false}) checkbox: MatCheckbox;
set isDisabled(value: boolean) {
this.checkbox.disabled = value;
@@ -58,7 +58,7 @@ interface PeriodicElement {
}
abstract class BaseTestComponent {
@ViewChild('table') table: ElementRef;
@ViewChild('table', {static: false}) table: ElementRef;
preservedValues = new Map<number, PeriodicElement>();
+38
View File
@@ -0,0 +1,38 @@
import * as ts from 'typescript';
import * as Lint from 'tslint';
/**
* Rule which enforces that all queries are explicitly marked as static or non-static.
*/
export class Rule extends Lint.Rules.AbstractRule {
apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new Walker(sourceFile, this.getOptions()));
}
}
class Walker extends Lint.RuleWalker {
visitPropertyDeclaration(node: ts.PropertyDeclaration) {
const childQueryDecorator = node.decorators && node.decorators.find(decorator => {
const expression = (decorator.expression as ts.CallExpression);
const name = expression && expression.expression.getText();
return name === 'ViewChild' || name === 'ContentChild';
});
if (childQueryDecorator) {
const options = (childQueryDecorator.expression as ts.CallExpression).arguments[1];
if (!options || !ts.isObjectLiteralExpression(options) ||
!this._getObjectProperty(options, 'static')) {
this.addFailureAtNode(childQueryDecorator,
'Queries have to explicitly set the `static` option.');
}
}
super.visitPropertyDeclaration(node);
}
/** Gets the node of an object property by name. */
private _getObjectProperty(node: ts.ObjectLiteralExpression, name: string) {
return node.properties.find(property => (property.name as ts.Identifier).getText() === name);
}
}
+1
View File
@@ -102,6 +102,7 @@
"ng-on-changes-property-access": true,
"rxjs-imports": true,
"require-breaking-change-version": true,
"static-query": true,
"no-host-decorator-in-concrete": [
true,
"HostBinding",