2015-10-27 23:51:03 -04:00
|
|
|
import {RuleFailure} from 'tslint/lib/lint';
|
|
|
|
import {AbstractRule} from 'tslint/lib/rules';
|
|
|
|
import {RuleWalker} from 'tslint/lib/language/walker';
|
|
|
|
import * as ts from 'tslint/node_modules/typescript';
|
2015-07-07 23:03:00 -04:00
|
|
|
|
2015-10-27 23:51:03 -04:00
|
|
|
export class Rule extends AbstractRule {
|
2015-07-07 23:03:00 -04:00
|
|
|
public static FAILURE_STRING = "missing type declaration";
|
|
|
|
|
2015-10-27 23:51:03 -04:00
|
|
|
public apply(sourceFile: ts.SourceFile): RuleFailure[] {
|
2015-07-07 23:03:00 -04:00
|
|
|
const typedefWalker = new TypedefWalker(sourceFile, this.getOptions());
|
|
|
|
return this.applyWithWalker(typedefWalker);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-27 23:51:03 -04:00
|
|
|
class TypedefWalker extends RuleWalker {
|
2015-07-07 23:03:00 -04:00
|
|
|
public visitMethodDeclaration(node: ts.MethodDeclaration) {
|
|
|
|
if (node.name.getText().charAt(0) !== '_') {
|
|
|
|
node.parameters.forEach((p: ts.ParameterDeclaration) => {
|
|
|
|
// a parameter's "type" could be a specific string value, for example `fn(option:
|
|
|
|
// "someOption", anotherOption: number)`
|
|
|
|
if (p.type == null || p.type.kind !== ts.SyntaxKind.StringLiteral) {
|
|
|
|
this.checkTypeAnnotation(p.getEnd(), <ts.TypeNode>p.type, p.name);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
super.visitMethodDeclaration(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
private checkTypeAnnotation(location: number, typeAnnotation: ts.TypeNode, name?: ts.Node) {
|
|
|
|
if (typeAnnotation == null) {
|
|
|
|
let ns = "<name missing>";
|
|
|
|
if (name != null && name.kind === ts.SyntaxKind.Identifier) {
|
|
|
|
ns = (<ts.Identifier>name).text;
|
|
|
|
}
|
|
|
|
if (ns.charAt(0) === '_') return;
|
|
|
|
let failure = this.createFailure(location, 1, "expected parameter " + ns + " to have a type");
|
|
|
|
this.addFailure(failure);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|