Skip to content

Commit bce0026

Browse files
rafaelss95wKoza
authored andcommitted
fix: some rules not considering options correctly (#617)
1 parent 7fc3b09 commit bce0026

7 files changed

+359
-345
lines changed

src/maxInlineDeclarationsRule.ts

Lines changed: 103 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,82 @@
1-
import * as Lint from 'tslint';
2-
import * as ts from 'typescript';
3-
import { ComponentMetadata } from './angular/metadata';
1+
import { sprintf } from 'sprintf-js';
2+
import { IOptions, IRuleMetadata, RuleFailure, Rules, Utils } from 'tslint/lib';
3+
import { SourceFile } from 'typescript/lib/typescript';
4+
import { CodeWithSourceMap, ComponentMetadata } from './angular/metadata';
45
import { NgWalker } from './angular/ngWalker';
56

6-
export class Rule extends Lint.Rules.AbstractRule {
7-
public static metadata: Lint.IRuleMetadata = {
8-
ruleName: 'max-inline-declarations',
9-
type: 'maintainability',
10-
description: 'Disallows having too many lines in inline template or styles. Forces separate template or styles file creation.',
11-
descriptionDetails: 'See more at https://angular.io/guide/styleguide#style-05-04',
7+
const DEFAULT_STYLES_LIMIT: number = 3;
8+
const DEFAULT_TEMPLATE_LIMIT: number = 3;
9+
const OPTION_STYLES = 'styles';
10+
const OPTION_TEMPLATE = 'template';
11+
12+
export class Rule extends Rules.AbstractRule {
13+
static readonly metadata: IRuleMetadata = {
14+
description: 'Disallows having too many lines in inline template and styles. Forces separate template or styles file creation.',
15+
descriptionDetails: 'See more at https://angular.io/guide/styleguide#style-05-04.',
16+
optionExamples: [true, [true, { [OPTION_STYLES]: 8, [OPTION_TEMPLATE]: 5 }]],
1217
options: {
13-
type: 'array',
1418
items: {
19+
properties: {
20+
[OPTION_STYLES]: {
21+
type: 'number'
22+
},
23+
[OPTION_TEMPLATE]: {
24+
type: 'number'
25+
}
26+
},
1527
type: 'object'
16-
}
28+
},
29+
maxLength: 1,
30+
minLength: 0,
31+
type: 'array'
1732
},
18-
optionsDescription: 'Define inline template and styles lines limit.',
19-
optionExamples: ['[{template: 5, styles: 8}]'],
33+
optionsDescription: Utils.dedent`
34+
It can take an optional object with the properties '${OPTION_STYLES}' and '${OPTION_TEMPLATE}':
35+
* \`${OPTION_STYLES}\` - number > 0 defining the maximum allowed inline lines for styles. Defaults to ${DEFAULT_STYLES_LIMIT}.
36+
* \`${OPTION_TEMPLATE}\` - number > 0 defining the maximum allowed inline lines for template. Defaults to ${DEFAULT_TEMPLATE_LIMIT}.
37+
`,
38+
rationale:
39+
"Large, inline templates and styles obscure the component's purpose and implementation, reducing readability and maintainability.",
40+
ruleName: 'max-inline-declarations',
41+
type: 'maintainability',
2042
typescriptOnly: true
2143
};
2244

23-
private readonly templateLinesLimit: number = 3;
24-
private readonly stylesLinesLimit: number = 3;
45+
static readonly FAILURE_STRING = 'Exceeds the maximum allowed inline lines for %s. Defined limit: %s / total lines: %s';
2546

26-
constructor(options: Lint.IOptions) {
27-
super(options);
28-
if (options.ruleArguments.length > 1) {
29-
const args = options.ruleArguments[1];
30-
if (args.template > -1) {
31-
this.templateLinesLimit = args.template;
32-
}
33-
if (args.styles > -1) {
34-
this.stylesLinesLimit = args.styles;
35-
}
36-
}
37-
}
38-
39-
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
40-
return this.applyWithWalker(
41-
new MaxInlineDeclarationsValidator(sourceFile, this.getOptions(), this.templateLinesLimit, this.stylesLinesLimit)
42-
);
47+
apply(sourceFile: SourceFile): RuleFailure[] {
48+
return this.applyWithWalker(new MaxInlineDeclarationsValidator(sourceFile, this.getOptions()));
4349
}
4450
}
4551

52+
type PropertyType = 'styles' | 'template';
53+
54+
export type PropertyPair = { [key in PropertyType]?: number };
55+
56+
const generateFailure = (type: PropertyType, limit: number, value: number): string => {
57+
return sprintf(Rule.FAILURE_STRING, type, limit, value);
58+
};
59+
60+
export const getStylesFailure = (value: number, limit = DEFAULT_STYLES_LIMIT): string => {
61+
return generateFailure(OPTION_STYLES, limit, value);
62+
};
63+
64+
export const getTemplateFailure = (value: number, limit = DEFAULT_TEMPLATE_LIMIT): string => {
65+
return generateFailure(OPTION_TEMPLATE, limit, value);
66+
};
67+
4668
export class MaxInlineDeclarationsValidator extends NgWalker {
47-
private newLineRegExp = /\r\n|\r|\n/;
69+
private readonly stylesLinesLimit = DEFAULT_STYLES_LIMIT;
70+
private readonly templateLinesLimit = DEFAULT_TEMPLATE_LIMIT;
71+
private readonly newLineRegExp = /\r\n|\r|\n/;
4872

49-
constructor(sourceFile: ts.SourceFile, options: Lint.IOptions, private templateLinesLimit: number, private stylesLinesLimit: number) {
73+
constructor(sourceFile: SourceFile, options: IOptions) {
5074
super(sourceFile, options);
75+
76+
const { styles, template } = (options.ruleArguments[0] || []) as PropertyPair;
77+
78+
this.stylesLinesLimit = styles > -1 ? styles : this.stylesLinesLimit;
79+
this.templateLinesLimit = template > -1 ? template : this.templateLinesLimit;
5180
}
5281

5382
protected visitNgComponent(metadata: ComponentMetadata): void {
@@ -56,30 +85,44 @@ export class MaxInlineDeclarationsValidator extends NgWalker {
5685
super.visitNgComponent(metadata);
5786
}
5887

59-
private validateInlineTemplate(metadata: ComponentMetadata): void {
60-
if (this.hasInlineTemplate(metadata) && this.getTemplateLinesCount(metadata) > this.templateLinesLimit) {
61-
const templateLinesCount = this.getTemplateLinesCount(metadata);
62-
const msg = `Inline template lines limit exceeded. Defined limit: ${this.templateLinesLimit} / template lines: ${templateLinesCount}`;
63-
this.addFailureAtNode(metadata.template.node, msg);
64-
}
88+
private getTotalLines(source: CodeWithSourceMap['source']): number {
89+
return source.trim().split(this.newLineRegExp).length;
90+
}
91+
92+
private getTemplateLinesCount(metadata: ComponentMetadata): number {
93+
return this.hasInlineTemplate(metadata) ? this.getTotalLines(metadata.template.template.source) : 0;
6594
}
6695

6796
private hasInlineTemplate(metadata: ComponentMetadata): boolean {
68-
return !!metadata.template && !metadata.template.url && !!metadata.template.template && !!metadata.template.template.source;
97+
return !!(metadata.template && !metadata.template.url && metadata.template.template && metadata.template.template.source);
6998
}
7099

71-
private getTemplateLinesCount(metadata: ComponentMetadata): number {
72-
return metadata.template.template.source.split(this.newLineRegExp).length;
100+
private validateInlineTemplate(metadata: ComponentMetadata): void {
101+
const templateLinesCount = this.getTemplateLinesCount(metadata);
102+
103+
if (templateLinesCount <= this.templateLinesLimit) {
104+
return;
105+
}
106+
107+
const failureMessage = getTemplateFailure(templateLinesCount, this.templateLinesLimit);
108+
109+
this.addFailureAtNode(metadata.template.node, failureMessage);
73110
}
74111

75-
private validateInlineStyles(metadata: ComponentMetadata): void {
76-
if (this.hasInlineStyles(metadata) && this.getInlineStylesLinesCount(metadata) > this.stylesLinesLimit) {
77-
const stylesLinesCount = this.getInlineStylesLinesCount(metadata);
78-
const msg = `Inline styles lines limit exceeded. Defined limit: ${this.stylesLinesLimit} / styles lines: ${stylesLinesCount}`;
79-
for (let i = 0; i < metadata.styles.length; i++) {
80-
this.addFailureAtNode(metadata.styles[i].node, msg);
112+
private getInlineStylesLinesCount(metadata: ComponentMetadata): number {
113+
let result = 0;
114+
115+
if (!this.hasInlineStyles(metadata)) {
116+
return result;
117+
}
118+
119+
for (let i = 0; i < metadata.styles.length; i++) {
120+
if (!metadata.styles[i].url) {
121+
result += this.getTotalLines(metadata.styles[i].style.source);
81122
}
82123
}
124+
125+
return result;
83126
}
84127

85128
private hasInlineStyles(metadata: ComponentMetadata): boolean {
@@ -89,6 +132,7 @@ export class MaxInlineDeclarationsValidator extends NgWalker {
89132

90133
for (let i = 0; i < metadata.styles.length; i++) {
91134
const style = metadata.styles[i];
135+
92136
if (!style.url && style.style && style.style.source) {
93137
return true;
94138
}
@@ -97,14 +141,17 @@ export class MaxInlineDeclarationsValidator extends NgWalker {
97141
return false;
98142
}
99143

100-
private getInlineStylesLinesCount(metadata: ComponentMetadata) {
101-
let result = 0;
102-
for (let i = 0; i < metadata.styles.length; i++) {
103-
if (!metadata.styles[i].url) {
104-
result += metadata.styles[i].style.source.split(this.newLineRegExp).length;
105-
}
144+
private validateInlineStyles(metadata: ComponentMetadata): void {
145+
const stylesLinesCount = this.getInlineStylesLinesCount(metadata);
146+
147+
if (stylesLinesCount <= this.stylesLinesLimit) {
148+
return;
106149
}
107150

108-
return result;
151+
const failureMessage = getStylesFailure(stylesLinesCount, this.stylesLinesLimit);
152+
153+
for (let i = 0; i < metadata.styles.length; i++) {
154+
this.addFailureAtNode(metadata.styles[i].node, failureMessage);
155+
}
109156
}
110157
}

src/noInputPrefixRule.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class NoInputPrefixWalker extends NgWalker {
5050

5151
constructor(source: SourceFile, options: IOptions) {
5252
super(source, options);
53-
this.blacklistedPrefixes = options.ruleArguments.slice(1);
53+
this.blacklistedPrefixes = options.ruleArguments;
5454
}
5555

5656
protected visitNgInput(property: PropertyDeclaration, input: Decorator, args: string[]) {

src/preferInlineDecoratorRule.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ type DecoratorKeys =
4141
| 'ViewChild'
4242
| 'ViewChildren';
4343

44-
export const decoratorKeys = new Set<DecoratorKeys>([
44+
export const decoratorKeys: ReadonlySet<DecoratorKeys> = new Set<DecoratorKeys>([
4545
'ContentChild',
4646
'ContentChildren',
4747
'HostBinding',
@@ -52,12 +52,16 @@ export const decoratorKeys = new Set<DecoratorKeys>([
5252
'ViewChildren'
5353
]);
5454

55+
export const getFailureMessage = (): string => {
56+
return Rule.FAILURE_STRING;
57+
};
58+
5559
export class PreferInlineDecoratorWalker extends NgWalker {
5660
private readonly blacklistedDecorators: typeof decoratorKeys;
5761

5862
constructor(source: SourceFile, options: IOptions) {
5963
super(source, options);
60-
this.blacklistedDecorators = new Set<DecoratorKeys>(options.ruleArguments.slice(1));
64+
this.blacklistedDecorators = new Set<DecoratorKeys>(options.ruleArguments);
6165
}
6266

6367
protected visitMethodDecorator(decorator: Decorator) {
@@ -86,6 +90,6 @@ export class PreferInlineDecoratorWalker extends NgWalker {
8690
}
8791

8892
const fix = Replacement.deleteFromTo(decorator.getEnd(), propertyStartPos - 1);
89-
this.addFailureAt(decoratorStartPos, property.getWidth(), Rule.FAILURE_STRING, fix);
93+
this.addFailureAt(decoratorStartPos, property.getWidth(), getFailureMessage(), fix);
9094
}
9195
}

0 commit comments

Comments
 (0)