77 lines
3.5 KiB
JavaScript
77 lines
3.5 KiB
JavaScript
"use strict";
|
|
var __extends = (this && this.__extends) || function (d, b) {
|
|
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
|
function __() { this.constructor = d; }
|
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
};
|
|
var Lint = require('tslint/lib/lint');
|
|
var sprintf_js_1 = require('sprintf-js');
|
|
var SyntaxKind = require('./util/syntaxKind');
|
|
var Rule = (function (_super) {
|
|
__extends(Rule, _super);
|
|
function Rule() {
|
|
_super.apply(this, arguments);
|
|
}
|
|
Rule.prototype.apply = function (sourceFile) {
|
|
return this.applyWithWalker(new ClassMetadataWalker(sourceFile, this.getOptions()));
|
|
};
|
|
Rule.FAILURE_SINGLE = 'Implement lifecycle hook interfaces (https://goo.gl/w1Nwk3)';
|
|
Rule.FAILURE_MANY = 'Implement lifecycle hook interfaces (https://goo.gl/w1Nwk3)';
|
|
Rule.HOOKS_PREFIX = 'ng';
|
|
Rule.LIFE_CYCLE_HOOKS_NAMES = [
|
|
"OnChanges",
|
|
"OnInit",
|
|
"DoCheck",
|
|
"AfterContentInit",
|
|
"AfterContentChecked",
|
|
"AfterViewInit",
|
|
"AfterViewChecked",
|
|
"OnDestroy"
|
|
];
|
|
return Rule;
|
|
}(Lint.Rules.AbstractRule));
|
|
exports.Rule = Rule;
|
|
var ClassMetadataWalker = (function (_super) {
|
|
__extends(ClassMetadataWalker, _super);
|
|
function ClassMetadataWalker() {
|
|
_super.apply(this, arguments);
|
|
}
|
|
ClassMetadataWalker.prototype.visitClassDeclaration = function (node) {
|
|
var syntaxKind = SyntaxKind.current();
|
|
var className = node.name.text;
|
|
var interfaces = [];
|
|
if (node.heritageClauses) {
|
|
var interfacesClause = node.heritageClauses.filter(function (h) { return h.token === syntaxKind.ImplementsKeyword; });
|
|
if (interfacesClause.length !== 0) {
|
|
interfaces = interfacesClause[0].types.map(function (t) { return t.expression.text; });
|
|
}
|
|
}
|
|
var missing = this.extractMissing(node.members, syntaxKind, interfaces);
|
|
if (missing.length !== 0) {
|
|
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), sprintf_js_1.sprintf.apply(this, this.formatFailure(className, missing))));
|
|
}
|
|
_super.prototype.visitClassDeclaration.call(this, node);
|
|
};
|
|
ClassMetadataWalker.prototype.extractMissing = function (members, syntaxKind, interfaces) {
|
|
var ngMembers = members.filter(function (m) { return m.kind === syntaxKind.MethodDeclaration; })
|
|
.map(function (m) { return m.name.text; })
|
|
.filter(function (n) { return (n && n.substr(0, 2) === Rule.HOOKS_PREFIX); })
|
|
.map(function (n) { return n.substr(2, n.lenght); })
|
|
.filter(function (n) { return Rule.LIFE_CYCLE_HOOKS_NAMES.indexOf(n) !== -1; });
|
|
return ngMembers.filter(function (m) { return interfaces.indexOf(m) === -1; });
|
|
};
|
|
ClassMetadataWalker.prototype.formatFailure = function (className, missing) {
|
|
var failureConfig;
|
|
if (missing.length === 1) {
|
|
failureConfig = [Rule.FAILURE_SINGLE, className, Rule.HOOKS_PREFIX + missing[0], missing[0]];
|
|
}
|
|
else {
|
|
var joinedNgMissing = missing.map(function (m) { return Rule.HOOKS_PREFIX + m; }).join(', ');
|
|
var joinedMissingInterfaces = missing.join(', ');
|
|
failureConfig = [Rule.FAILURE_MANY, className, joinedNgMissing, joinedMissingInterfaces];
|
|
}
|
|
return failureConfig;
|
|
};
|
|
return ClassMetadataWalker;
|
|
}(Lint.RuleWalker));
|
|
exports.ClassMetadataWalker = ClassMetadataWalker;
|