Skip to content

Commit d8a3ab7

Browse files
authored
ci: Ban introduction of more zone-dependent code (#28711)
1 parent 9d18c89 commit d8a3ab7

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import * as Lint from 'tslint';
2+
import ts from 'typescript';
3+
import minimatch from 'minimatch';
4+
5+
/**
6+
* NgZone properties that are ok to access.
7+
*/
8+
const allowedNgZoneProperties = new Set<string>(['run', 'runOutsideAngular']);
9+
10+
/** Rule to prevent adding code that depends on using zones. */
11+
export class Rule extends Lint.Rules.TypedRule {
12+
applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
13+
return this.applyWithWalker(
14+
new Walker(sourceFile, this.getOptions(), program.getTypeChecker()),
15+
);
16+
}
17+
}
18+
19+
class Walker extends Lint.RuleWalker {
20+
/** Whether the walker should check the current source file. */
21+
private _enabled: boolean;
22+
23+
constructor(
24+
sourceFile: ts.SourceFile,
25+
options: Lint.IOptions,
26+
private _typeChecker: ts.TypeChecker,
27+
) {
28+
super(sourceFile, options);
29+
30+
// Globs that are used to determine which files to lint.
31+
const fileGlobs: string[] = options.ruleArguments[0];
32+
33+
// Whether the file should be checked at all.
34+
this._enabled = !fileGlobs.some(p => minimatch(sourceFile.fileName, p));
35+
}
36+
37+
override visitPropertyAccessExpression(node: ts.PropertyAccessExpression) {
38+
if (!this._enabled) {
39+
return;
40+
}
41+
42+
const classType = this._typeChecker.getTypeAtLocation(node.expression);
43+
const className = classType.symbol && classType.symbol.name;
44+
const propertyName = node.name.text;
45+
46+
if (className === 'NgZone' && !allowedNgZoneProperties.has(propertyName)) {
47+
this.addFailureAtNode(node, `Using NgZone.${propertyName} is not allowed.`);
48+
}
49+
50+
return super.visitPropertyAccessExpression(node);
51+
}
52+
}

tslint.json

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,26 @@
157157
],
158158
"no-unescaped-html-tag": true,
159159
// Ensures that all rxjs imports come only from `rxjs` and `rxjs/operators`.
160-
"import-blacklist": [true, ["^rxjs(?!$|/operators$).*", "^@material/"]]
160+
"import-blacklist": [true, ["^rxjs(?!$|/operators$).*", "^@material/"]],
161+
"no-zone-dependencies": [
162+
true,
163+
[
164+
// Tests may need to verify behavior with zones.
165+
"**/*.spec.ts",
166+
// TODO(mmalerba): following files to be cleaned up and removed from this list:
167+
"**/cdk/a11y/focus-trap/focus-trap.ts",
168+
"**/cdk/drag-drop/directives/drag.ts",
169+
"**/cdk/overlay/overlay-ref.ts",
170+
"**/cdk/table/coalesced-style-scheduler.ts",
171+
"**/cdk/table/table.ts",
172+
"**/material/autocomplete/autocomplete-trigger.ts",
173+
"**/material/chips/chip.ts",
174+
"**/material/form-field/form-field.ts",
175+
"**/material/menu/menu.ts",
176+
"**/material/sidenav/drawer.ts",
177+
"**/material/tabs/paginated-tab-header.ts"
178+
]
179+
]
161180
},
162181
"linterOptions": {
163182
"exclude": [

0 commit comments

Comments
 (0)