@@ -21,22 +21,18 @@ import {
21
21
DEFAULT_CONFIG ,
22
22
findConfiguration ,
23
23
findConfigurationPath ,
24
- getRelativePath ,
25
24
getRulesDirectories ,
26
25
loadConfigurationFromPath ,
27
26
} from "./configuration" ;
28
- import { EnableDisableRulesWalker } from "./enableDisableRules" ;
29
- import { findFormatter } from "./formatterLoader" ;
30
- import { IFormatter } from "./language/formatter/formatter" ;
31
- import { RuleFailure } from "./language/rule/rule" ;
32
- import { TypedRule } from "./language/rule/typedRule" ;
33
- import { getSourceFile } from "./language/utils" ;
34
27
import { ILinterOptions , ILinterOptionsRaw , LintResult } from "./lint" ;
35
- import { loadRules } from "./ruleLoader " ;
28
+ import * as MultiLinter from "./tslintMulti " ;
36
29
import { arrayify } from "./utils" ;
37
30
31
+ /**
32
+ * Linter that can lint exactly one file.
33
+ */
38
34
class Linter {
39
- public static VERSION = "3.15.1" ;
35
+ public static VERSION = MultiLinter . VERSION ;
40
36
41
37
public static findConfiguration = findConfiguration ;
42
38
public static findConfigurationPath = findConfigurationPath ;
@@ -49,99 +45,25 @@ class Linter {
49
45
* Creates a TypeScript program object from a tsconfig.json file path and optional project directory.
50
46
*/
51
47
public static createProgram ( configFile : string , projectDirectory ?: string ) : ts . Program {
52
- if ( projectDirectory === undefined ) {
53
- const lastSeparator = configFile . lastIndexOf ( "/" ) ;
54
- if ( lastSeparator < 0 ) {
55
- projectDirectory = "." ;
56
- } else {
57
- projectDirectory = configFile . substring ( 0 , lastSeparator + 1 ) ;
58
- }
59
- }
60
-
61
- const { config} = ts . readConfigFile ( configFile , ts . sys . readFile ) ;
62
- const parsed = ts . parseJsonConfigFileContent ( config , { readDirectory : ts . sys . readDirectory } , projectDirectory ) ;
63
- const host = ts . createCompilerHost ( parsed . options , true ) ;
64
- const program = ts . createProgram ( parsed . fileNames , parsed . options , host ) ;
65
-
66
- return program ;
48
+ return MultiLinter . createProgram ( configFile , projectDirectory ) ;
67
49
}
68
50
69
51
/**
70
52
* Returns a list of source file names from a TypeScript program. This includes all referenced
71
53
* files and excludes declaration (".d.ts") files.
72
54
*/
73
55
public static getFileNames ( program : ts . Program ) : string [ ] {
74
- return program . getSourceFiles ( ) . map ( s => s . fileName ) . filter ( l => l . substr ( - 5 ) !== ".d.ts" ) ;
56
+ return MultiLinter . getFileNames ( program ) ;
75
57
}
76
58
77
59
constructor ( private fileName : string , private source : string , options : ILinterOptionsRaw , private program ?: ts . Program ) {
78
- this . options = this . computeFullOptions ( options ) ;
60
+ this . options = this . computeFullOptions ( options ) ;
79
61
}
80
62
81
63
public lint ( ) : LintResult {
82
- const failures : RuleFailure [ ] = [ ] ;
83
- let sourceFile : ts . SourceFile ;
84
- if ( this . program ) {
85
- sourceFile = this . program . getSourceFile ( this . fileName ) ;
86
- // check if the program has been type checked
87
- if ( ! ( "resolvedModules" in sourceFile ) ) {
88
- throw new Error ( "Program must be type checked before linting" ) ;
89
- }
90
- } else {
91
- sourceFile = getSourceFile ( this . fileName , this . source ) ;
92
- }
93
-
94
- if ( sourceFile === undefined ) {
95
- throw new Error ( `Invalid source file: ${ this . fileName } . Ensure that the files supplied to lint have a .ts or .tsx extension.` ) ;
96
- }
97
-
98
- // walk the code first to find all the intervals where rules are disabled
99
- const rulesWalker = new EnableDisableRulesWalker ( sourceFile , {
100
- disabledIntervals : [ ] ,
101
- ruleName : "" ,
102
- } ) ;
103
- rulesWalker . walk ( sourceFile ) ;
104
- const enableDisableRuleMap = rulesWalker . enableDisableRuleMap ;
105
-
106
- const rulesDirectories = this . options . rulesDirectory ;
107
- const configuration = this . options . configuration . rules ;
108
- const configuredRules = loadRules ( configuration , enableDisableRuleMap , rulesDirectories ) ;
109
- const enabledRules = configuredRules . filter ( ( r ) => r . isEnabled ( ) ) ;
110
- for ( let rule of enabledRules ) {
111
- let ruleFailures : RuleFailure [ ] = [ ] ;
112
- if ( this . program && rule instanceof TypedRule ) {
113
- ruleFailures = rule . applyWithProgram ( sourceFile , this . program ) ;
114
- } else {
115
- ruleFailures = rule . apply ( sourceFile ) ;
116
- }
117
- for ( let ruleFailure of ruleFailures ) {
118
- if ( ! this . containsRule ( failures , ruleFailure ) ) {
119
- failures . push ( ruleFailure ) ;
120
- }
121
- }
122
- }
123
-
124
- let formatter : IFormatter ;
125
- const formattersDirectory = getRelativePath ( this . options . formattersDirectory ) ;
126
-
127
- const Formatter = findFormatter ( this . options . formatter , formattersDirectory ) ;
128
- if ( Formatter ) {
129
- formatter = new Formatter ( ) ;
130
- } else {
131
- throw new Error ( `formatter '${ this . options . formatter } ' not found` ) ;
132
- }
133
-
134
- const output = formatter . format ( failures ) ;
135
- return {
136
- failureCount : failures . length ,
137
- failures,
138
- format : this . options . formatter ,
139
- output,
140
- } ;
141
- }
142
-
143
- private containsRule ( rules : RuleFailure [ ] , rule : RuleFailure ) {
144
- return rules . some ( ( r ) => r . equals ( rule ) ) ;
64
+ const multiLinter : MultiLinter = new MultiLinter ( this . options , this . program ) ;
65
+ multiLinter . lint ( this . fileName , this . source , this . options . configuration ) ;
66
+ return multiLinter . getResult ( ) ;
145
67
}
146
68
147
69
private computeFullOptions ( options : ILinterOptionsRaw = { } ) : ILinterOptions {
@@ -157,7 +79,7 @@ class Linter {
157
79
formattersDirectory,
158
80
rulesDirectory : arrayify ( rulesDirectory ) . concat ( arrayify ( configuration . rulesDirectory ) ) ,
159
81
} ;
160
- }
82
+ }
161
83
}
162
84
163
85
// tslint:disable-next-line:no-namespace
0 commit comments