Skip to content

Commit 721ad03

Browse files
committed
build: add linting for classList usage
Once in a while we hit an issue because we use some of the `classList` methods in a way that isn't supported in all browsers (e.g. passing multiple parameters to `add` in #17378). These changes add a simple lint rule to catch these cases earlier.
1 parent 14c4dba commit 721ad03

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import * as ts from 'typescript';
2+
import * as Lint from 'tslint';
3+
4+
/**
5+
* Rule that catches cases where `classList` is used in a way
6+
* that won't work in all browsers that we support.
7+
*/
8+
export class Rule extends Lint.Rules.TypedRule {
9+
applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
10+
return this.applyWithWalker(new Walker(sourceFile, this.getOptions(), program));
11+
}
12+
}
13+
14+
class Walker extends Lint.ProgramAwareRuleWalker {
15+
visitPropertyAccessExpression(propertyAccess: ts.PropertyAccessExpression) {
16+
const parent = propertyAccess.parent;
17+
18+
// We only care about property accesses inside of calls.
19+
if (!ts.isCallExpression(parent)) {
20+
return;
21+
}
22+
23+
// We only care about these method names.
24+
const name = propertyAccess.name.text;
25+
if (name !== 'add' && name !== 'remove' && name !== 'toggle' && name !== 'replace') {
26+
return;
27+
}
28+
29+
const symbol = this.getTypeChecker().getTypeAtLocation(propertyAccess.expression).symbol;
30+
31+
if (symbol && symbol.name === 'DOMTokenList') {
32+
const args = parent.arguments;
33+
34+
if (name === 'replace') {
35+
this.addFailureAtNode(propertyAccess,
36+
'This method is not supported in iOS Safari. Use `add` and `remove` instead,');
37+
} else if (args.length > 1 || (args.length === 1 && ts.isSpreadElement(args[0]))) {
38+
this.addFailureAtNode(propertyAccess,
39+
'Passing in multiple arguments into this method is not supported in some browsers. ' +
40+
'Use the single argument signature instead.');
41+
}
42+
}
43+
44+
super.visitPropertyAccessExpression(propertyAccess);
45+
}
46+
}

tslint.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
"rxjs-imports": true,
108108
"require-breaking-change-version": true,
109109
"static-query": true,
110+
"class-list-signatures": true,
110111
"no-host-decorator-in-concrete": [
111112
true,
112113
"HostBinding",

0 commit comments

Comments
 (0)