Skip to content

Commit

Permalink
wip: ban-dom-globals
Browse files Browse the repository at this point in the history
Fixes: #181
  • Loading branch information
ajafff committed Apr 27, 2018
1 parent 4e5183b commit 5b71b47
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/mimir/recommended.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
rules:
await-async-result: error
await-only-promise: error
ban-dom-globals: error
generator-require-yield: error
new-parens: error
no-case-declaration: error
Expand Down
65 changes: 65 additions & 0 deletions packages/mimir/src/rules/ban-dom-globals.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { TypedRule, requireLibraryFile } from '@fimbul/ymir';
import * as ts from 'typescript';
import { getUsageDomain, UsageDomain, isSourceFile } from 'tsutils';
import * as path from 'path';

@requireLibraryFile('lib.dom.d.ts')
export class Rule extends TypedRule {
public apply() {
for (const node of this.context.getFlatAst()) {
if (node.kind !== ts.SyntaxKind.Identifier)
continue;
const text = (<ts.Identifier>node).text;
if (isWhitelisted(text) || (getUsageDomain(<ts.Identifier>node)! & UsageDomain.Value) === 0)
continue;
const symbol = this.checker.getSymbolAtLocation(node);
if (
symbol !== undefined &&
symbol.valueDeclaration !== undefined &&
symbol.flags & (ts.SymbolFlags.Variable | ts.SymbolFlags.Function) &&
isDeclarationInLibDom(symbol.valueDeclaration)
)
this.addFailureAtNode(
node,
`Referencing global '${text}' is not allowed. Did you mean to use a local variable or parameter with a similar name?`,
);
}
}
}

function isDeclarationInLibDom(node: ts.Node): boolean {
if (node.kind === ts.SyntaxKind.FunctionDeclaration) {
node = node.parent!;
} else if (node.kind === ts.SyntaxKind.VariableDeclaration) {
node = node.parent!.parent!;
if (node.kind !== ts.SyntaxKind.VariableStatement)
return false;
node = node.parent!;
} else {
return false;
}
return isSourceFile(node) && path.basename(node.fileName) === 'lib.dom.d.ts';
}

function isWhitelisted(name: string): boolean {
// exclude all identifiers that start with an uppercase letter to allow `new Event()` and stuff
if (name.charAt(0) === name.charAt(0).toUpperCase())
return true;
switch (name) {
case 'document':
case 'window':
case 'navigator':
case 'alert':
case 'confirm':
case 'prompt':
case 'atob':
case 'btoa':
case 'console':
case 'sessionStorage':
case 'localStorage':
case 'indexedDB':
return true;
default:
return /^(?:(?:set|clear)(?:Timeout|Interval|Immediate)|(?:request|cancel)AnimationFrame)$/.test(name);
}
}

0 comments on commit 5b71b47

Please sign in to comment.