forked from mgechev/codelyzer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtemplateBananaInBoxRule.ts
More file actions
59 lines (49 loc) · 2.12 KB
/
templateBananaInBoxRule.ts
File metadata and controls
59 lines (49 loc) · 2.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import { BoundEventAst } from '@angular/compiler';
import { IRuleMetadata, Replacement, RuleFailure } from 'tslint';
import { AbstractRule } from 'tslint/lib/rules';
import { SourceFile } from 'typescript';
import { NgWalker, NgWalkerConfig } from './angular/ngWalker';
import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor';
const INVALID_PATTERN = /\[(.*)\]/;
const VALID_CLOSE_BOX = ')]';
const VALID_OPEN_BOX = '[(';
export class Rule extends AbstractRule {
static readonly metadata: IRuleMetadata = {
description: 'Ensures that the two-way data binding syntax is correct.',
hasFix: true,
options: null,
optionsDescription: 'Not configurable.',
rationale: 'The parentheses "()" should have been inside the brackets "[]".',
ruleName: 'template-banana-in-box',
type: 'functionality',
typescriptOnly: true,
};
static readonly FAILURE_STRING = 'Invalid binding syntax. Use [(expr)] instead';
apply(sourceFile: SourceFile): RuleFailure[] {
const walkerConfig: NgWalkerConfig = { templateVisitorCtrl: TemplateVisitorCtrl };
const walker = new NgWalker(sourceFile, this.getOptions(), walkerConfig);
return this.applyWithWalker(walker);
}
}
class TemplateVisitorCtrl extends BasicTemplateAstVisitor {
visitEvent(ast: BoundEventAst, context: BasicTemplateAstVisitor): any {
this.validateEvent(ast);
super.visitEvent(ast, context);
}
private validateEvent(ast: BoundEventAst): void {
const matches = ast.name.match(INVALID_PATTERN);
if (!matches) return;
const {
sourceSpan: {
end: { offset: endOffset },
start: { offset: startOffset },
},
} = ast;
const text = matches[1];
const absoluteStartPosition = this.getSourcePosition(startOffset);
const absoluteEndPosition = absoluteStartPosition + VALID_OPEN_BOX.length + text.length + VALID_CLOSE_BOX.length;
const newText = `${VALID_OPEN_BOX}${text}${VALID_CLOSE_BOX}`;
const fix = Replacement.replaceFromTo(absoluteStartPosition, absoluteEndPosition, newText);
this.addFailureFromStartToEnd(startOffset, endOffset, Rule.FAILURE_STRING, fix);
}
}