ipsos-components
Version:
Material Design components for Angular
57 lines (43 loc) • 2.06 kB
text/typescript
import * as path from 'path';
import * as ts from 'typescript';
import * as Lint from 'tslint';
import * as minimatch from 'minimatch';
/**
* Rule that enforces that the specified external packages have been included in our Rollup config.
* Usage: [true, './path/to/rollup/config.json']
*/
export class Rule extends Lint.Rules.AbstractRule {
apply(sourceFile: ts.SourceFile) {
return this.applyWithWalker(new Walker(sourceFile, this.getOptions()));
}
}
class Walker extends Lint.RuleWalker {
/** Path to the rollup globals configuration file. */
private _configPath: string;
/** Rollup globals configuration object. */
private _config: {[globalName: string]: string};
/** Whether the walker should check the current source file. */
private _enabled: boolean;
constructor(sourceFile: ts.SourceFile, options: Lint.IOptions) {
super(sourceFile, options);
if (!options.ruleArguments.length) {
throw Error('missing-rollup-globals: The Rollup config path has to be specified.');
}
const [configPath, ...fileGlobs] = options.ruleArguments;
// Relative path for the current TypeScript source file.
const relativeFilePath = path.relative(process.cwd(), sourceFile.fileName);
this._configPath = path.resolve(process.cwd(), configPath);
this._config = require(this._configPath).rollupGlobals;
this._enabled = fileGlobs.some(p => minimatch(relativeFilePath, p));
}
visitImportDeclaration(node: ts.ImportDeclaration) {
// Parse out the module name. The first and last characters are the quote marks.
const module = node.moduleSpecifier.getText().slice(1, -1);
const isExternal = !module.startsWith('.') && !module.startsWith('/');
// Check whether the module is external and whether it's in our config.
if (this._enabled && isExternal && !this._config[module]) {
this.addFailureAtNode(node, `Module "${module}" is missing from file ${this._configPath}.`);
}
super.visitImportDeclaration(node);
}
}