.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / tslint / lib / linter.js
1 "use strict";
2 /**
3  * @license
4  * Copyright 2013 Palantir Technologies, Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 Object.defineProperty(exports, "__esModule", { value: true });
19 var tslib_1 = require("tslib");
20 var fs = require("fs");
21 var path = require("path");
22 var ts = require("typescript");
23 var configuration_1 = require("./configuration");
24 var enableDisableRules_1 = require("./enableDisableRules");
25 var error_1 = require("./error");
26 var formatterLoader_1 = require("./formatterLoader");
27 var rule_1 = require("./language/rule/rule");
28 var utils = require("./language/utils");
29 var ruleLoader_1 = require("./ruleLoader");
30 var utils_1 = require("./utils");
31 /**
32  * Linter that can lint multiple files in consecutive runs.
33  */
34 var Linter = /** @class */ (function () {
35     function Linter(options, program) {
36         this.options = options;
37         this.program = program;
38         this.failures = [];
39         this.fixes = [];
40         this.fileNames = [];
41         if (typeof options !== "object") {
42             throw new Error("Unknown Linter options type: " + typeof options);
43         }
44         if (options.configuration != undefined) {
45             throw new Error("ILinterOptions does not contain the property `configuration` as of version 4. " +
46                 "Did you mean to pass the `IConfigurationFile` object to lint() ? ");
47         }
48     }
49     /**
50      * Creates a TypeScript program object from a tsconfig.json file path and optional project directory.
51      */
52     Linter.createProgram = function (configFile, projectDirectory) {
53         if (projectDirectory === void 0) { projectDirectory = path.dirname(configFile); }
54         var config = ts.readConfigFile(configFile, ts.sys.readFile);
55         if (config.error !== undefined) {
56             throw new error_1.FatalError(ts.formatDiagnostics([config.error], {
57                 getCanonicalFileName: function (f) { return f; },
58                 getCurrentDirectory: process.cwd,
59                 getNewLine: function () { return "\n"; },
60             }));
61         }
62         var parseConfigHost = {
63             fileExists: fs.existsSync,
64             readDirectory: ts.sys.readDirectory,
65             readFile: function (file) { return fs.readFileSync(file, "utf8"); },
66             useCaseSensitiveFileNames: true,
67         };
68         var parsed = ts.parseJsonConfigFileContent(config.config, parseConfigHost, path.resolve(projectDirectory), { noEmit: true });
69         if (parsed.errors !== undefined) {
70             // ignore warnings and 'TS18003: No inputs were found in config file ...'
71             var errors = parsed.errors.filter(function (d) { return d.category === ts.DiagnosticCategory.Error && d.code !== 18003; });
72             if (errors.length !== 0) {
73                 throw new error_1.FatalError(ts.formatDiagnostics(errors, {
74                     getCanonicalFileName: function (f) { return f; },
75                     getCurrentDirectory: process.cwd,
76                     getNewLine: function () { return "\n"; },
77                 }));
78             }
79         }
80         var host = ts.createCompilerHost(parsed.options, true);
81         var program = ts.createProgram(parsed.fileNames, parsed.options, host);
82         return program;
83     };
84     /**
85      * Returns a list of source file names from a TypeScript program. This includes all referenced
86      * files and excludes declaration (".d.ts") files, as well as JSON files, to avoid problems with
87      * `resolveJsonModule`.
88      */
89     Linter.getFileNames = function (program) {
90         return utils_1.mapDefined(program.getSourceFiles(), function (file) {
91             return file.fileName.endsWith(".d.ts") ||
92                 file.fileName.endsWith(".json") ||
93                 program.isSourceFileFromExternalLibrary(file)
94                 ? undefined
95                 : file.fileName;
96         });
97     };
98     Linter.prototype.lint = function (fileName, source, configuration) {
99         if (configuration === void 0) { configuration = configuration_1.DEFAULT_CONFIG; }
100         if (configuration_1.isFileExcluded(fileName, configuration)) {
101             return;
102         }
103         this.fileNames.push(fileName);
104         var sourceFile = this.getSourceFile(fileName, source);
105         var isJs = /\.jsx?$/i.test(fileName);
106         var enabledRules = this.getEnabledRules(configuration, isJs);
107         if (enabledRules.length === 0) {
108             error_1.showWarningOnce("Tried to lint " + fileName + " but found no valid, enabled rules for this file type and file path in the resolved configuration.");
109         }
110         var fileFailures = this.getAllFailures(sourceFile, enabledRules);
111         if (fileFailures.length === 0) {
112             // Usual case: no errors.
113             return;
114         }
115         if (this.options.fix && fileFailures.some(function (f) { return f.hasFix(); })) {
116             fileFailures = this.applyAllFixes(enabledRules, fileFailures, sourceFile, fileName);
117         }
118         // add rule severity to failures
119         var ruleSeverityMap = new Map(enabledRules.map(function (rule) { return [
120             rule.getOptions().ruleName,
121             rule.getOptions().ruleSeverity,
122         ]; }));
123         for (var _i = 0, fileFailures_1 = fileFailures; _i < fileFailures_1.length; _i++) {
124             var failure = fileFailures_1[_i];
125             var severity = ruleSeverityMap.get(failure.getRuleName());
126             if (severity === undefined) {
127                 throw new Error("Severity for rule '" + failure.getRuleName() + "' not found");
128             }
129             failure.setRuleSeverity(severity);
130         }
131         this.failures = this.failures.concat(fileFailures);
132     };
133     Linter.prototype.getResult = function () {
134         var errors = this.failures.filter(function (failure) { return failure.getRuleSeverity() === "error"; });
135         var failures = this.options.quiet ? errors : this.failures;
136         var formatterName = this.options.formatter !== undefined ? this.options.formatter : "prose";
137         var Formatter = formatterLoader_1.findFormatter(formatterName, this.options.formattersDirectory);
138         if (Formatter === undefined) {
139             throw new Error("formatter '" + String(formatterName) + "' not found");
140         }
141         var formatter = new Formatter();
142         var output = formatter.format(failures, this.fixes, this.fileNames);
143         var errorCount = errors.length;
144         return {
145             errorCount: errorCount,
146             failures: failures,
147             fixes: this.fixes,
148             format: formatterName,
149             output: output,
150             warningCount: failures.length - errorCount,
151         };
152     };
153     Linter.prototype.getAllFailures = function (sourceFile, enabledRules) {
154         var _this = this;
155         var failures = utils_1.flatMap(enabledRules, function (rule) { return _this.applyRule(rule, sourceFile); });
156         return enableDisableRules_1.removeDisabledFailures(sourceFile, failures);
157     };
158     Linter.prototype.applyAllFixes = function (enabledRules, fileFailures, sourceFile, sourceFileName) {
159         // When fixing, we need to be careful as a fix in one rule may affect other rules.
160         // So fix each rule separately.
161         var source = sourceFile.text;
162         var _loop_1 = function (rule) {
163             var hasFixes = fileFailures.some(function (f) { return f.hasFix() && f.getRuleName() === rule.getOptions().ruleName; });
164             if (hasFixes) {
165                 // Get new failures in case the file changed.
166                 var updatedFailures = enableDisableRules_1.removeDisabledFailures(sourceFile, this_1.applyRule(rule, sourceFile));
167                 var fixableFailures = updatedFailures.filter(function (f) { return f.hasFix(); });
168                 this_1.fixes = this_1.fixes.concat(fixableFailures);
169                 source = this_1.applyFixes(sourceFileName, source, fixableFailures);
170                 sourceFile = this_1.getSourceFile(sourceFileName, source);
171             }
172         };
173         var this_1 = this;
174         for (var _i = 0, enabledRules_1 = enabledRules; _i < enabledRules_1.length; _i++) {
175             var rule = enabledRules_1[_i];
176             _loop_1(rule);
177         }
178         // If there were fixes, get the *new* list of failures.
179         return this.getAllFailures(sourceFile, enabledRules);
180     };
181     // Only "protected" because a test directly accesses it.
182     // tslint:disable-next-line member-ordering
183     Linter.prototype.applyFixes = function (sourceFilePath, source, fixableFailures) {
184         var _this = this;
185         var fixesByFile = createMultiMap(fixableFailures, function (f) { return [f.getFileName(), f.getFix()]; });
186         fixesByFile.forEach(function (fileFixes, filePath) {
187             var fileNewSource;
188             if (path.resolve(filePath) === path.resolve(sourceFilePath)) {
189                 source = rule_1.Replacement.applyFixes(source, fileFixes);
190                 fileNewSource = source;
191             }
192             else {
193                 var oldSource = fs.readFileSync(filePath, "utf-8");
194                 fileNewSource = rule_1.Replacement.applyFixes(oldSource, fileFixes);
195             }
196             fs.writeFileSync(filePath, fileNewSource);
197             _this.updateProgram(filePath);
198         });
199         return source;
200     };
201     Linter.prototype.updateProgram = function (sourceFilePath) {
202         if (this.program !== undefined &&
203             this.program.getSourceFile(sourceFilePath) !== undefined) {
204             var options = this.program.getCompilerOptions();
205             this.program = ts.createProgram(this.program.getRootFileNames(), options, ts.createCompilerHost(options, true), this.program);
206         }
207     };
208     Linter.prototype.applyRule = function (rule, sourceFile) {
209         try {
210             if (this.program !== undefined && rule_1.isTypedRule(rule)) {
211                 return rule.applyWithProgram(sourceFile, this.program);
212             }
213             else {
214                 return rule.apply(sourceFile);
215             }
216         }
217         catch (error) {
218             if (error_1.isError(error) && error.stack !== undefined) {
219                 error_1.showRuleCrashWarning(error.stack, rule.getOptions().ruleName, sourceFile.fileName);
220             }
221             else {
222                 error_1.showRuleCrashWarning(String(error), rule.getOptions().ruleName, sourceFile.fileName);
223             }
224             return [];
225         }
226     };
227     Linter.prototype.getEnabledRules = function (configuration, isJs) {
228         if (configuration === void 0) { configuration = configuration_1.DEFAULT_CONFIG; }
229         var ruleOptionsList = configuration_1.convertRuleOptions(isJs ? configuration.jsRules : configuration.rules);
230         var rulesDirectories = utils_1.arrayify(this.options.rulesDirectory).concat(utils_1.arrayify(configuration.rulesDirectory));
231         return ruleLoader_1.loadRules(ruleOptionsList, rulesDirectories, isJs);
232     };
233     Linter.prototype.getSourceFile = function (fileName, source) {
234         if (this.program !== undefined) {
235             var sourceFile = this.program.getSourceFile(fileName);
236             if (sourceFile === undefined) {
237                 var INVALID_SOURCE_ERROR = utils_1.dedent(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n                    Invalid source file: ", ". Ensure that the files supplied to lint have a .ts, .tsx, .d.ts, .js or .jsx extension.\n                "], ["\n                    Invalid source file: ", ". Ensure that the files supplied to lint have a .ts, .tsx, .d.ts, .js or .jsx extension.\n                "])), fileName);
238                 throw new error_1.FatalError(INVALID_SOURCE_ERROR);
239             }
240             return sourceFile;
241         }
242         else {
243             return utils.getSourceFile(fileName, source);
244         }
245     };
246     Linter.VERSION = "5.20.1";
247     Linter.findConfiguration = configuration_1.findConfiguration;
248     Linter.findConfigurationPath = configuration_1.findConfigurationPath;
249     Linter.getRulesDirectories = configuration_1.getRulesDirectories;
250     Linter.loadConfigurationFromPath = configuration_1.loadConfigurationFromPath;
251     return Linter;
252 }());
253 exports.Linter = Linter;
254 function createMultiMap(inputs, getPair) {
255     var map = new Map();
256     for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) {
257         var input = inputs_1[_i];
258         var pair = getPair(input);
259         if (pair !== undefined) {
260             var k = pair[0], v = pair[1];
261             var vs = map.get(k);
262             if (vs !== undefined) {
263                 vs.push(v);
264             }
265             else {
266                 map.set(k, [v]);
267             }
268         }
269     }
270     return map;
271 }
272 var templateObject_1;