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' ;
4
5
import { NgWalker } from './angular/ngWalker' ;
5
6
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 } ] ] ,
12
17
options : {
13
- type : 'array' ,
14
18
items : {
19
+ properties : {
20
+ [ OPTION_STYLES ] : {
21
+ type : 'number'
22
+ } ,
23
+ [ OPTION_TEMPLATE ] : {
24
+ type : 'number'
25
+ }
26
+ } ,
15
27
type : 'object'
16
- }
28
+ } ,
29
+ maxLength : 1 ,
30
+ minLength : 0 ,
31
+ type : 'array'
17
32
} ,
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' ,
20
42
typescriptOnly : true
21
43
} ;
22
44
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' ;
25
46
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 ( ) ) ) ;
43
49
}
44
50
}
45
51
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
+
46
68
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 / ;
48
72
49
- constructor ( sourceFile : ts . SourceFile , options : Lint . IOptions , private templateLinesLimit : number , private stylesLinesLimit : number ) {
73
+ constructor ( sourceFile : SourceFile , options : IOptions ) {
50
74
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 ;
51
80
}
52
81
53
82
protected visitNgComponent ( metadata : ComponentMetadata ) : void {
@@ -56,30 +85,44 @@ export class MaxInlineDeclarationsValidator extends NgWalker {
56
85
super . visitNgComponent ( metadata ) ;
57
86
}
58
87
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 ;
65
94
}
66
95
67
96
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 ) ;
69
98
}
70
99
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 ) ;
73
110
}
74
111
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 ) ;
81
122
}
82
123
}
124
+
125
+ return result ;
83
126
}
84
127
85
128
private hasInlineStyles ( metadata : ComponentMetadata ) : boolean {
@@ -89,6 +132,7 @@ export class MaxInlineDeclarationsValidator extends NgWalker {
89
132
90
133
for ( let i = 0 ; i < metadata . styles . length ; i ++ ) {
91
134
const style = metadata . styles [ i ] ;
135
+
92
136
if ( ! style . url && style . style && style . style . source ) {
93
137
return true ;
94
138
}
@@ -97,14 +141,17 @@ export class MaxInlineDeclarationsValidator extends NgWalker {
97
141
return false ;
98
142
}
99
143
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 ;
106
149
}
107
150
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
+ }
109
156
}
110
157
}
0 commit comments