1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | Object.defineProperty(exports, "__esModule", { value: true });
|
19 | var tslib_1 = require("tslib");
|
20 |
|
21 | var fs = require("fs");
|
22 | var glob = require("glob");
|
23 | var minimatch_1 = require("minimatch");
|
24 | var path = require("path");
|
25 | var ts = require("typescript");
|
26 | var configuration_1 = require("./configuration");
|
27 | var error_1 = require("./error");
|
28 | var linter_1 = require("./linter");
|
29 | var utils_1 = require("./utils");
|
30 | function run(options, logger) {
|
31 | return tslib_1.__awaiter(this, void 0, void 0, function () {
|
32 | var error_2;
|
33 | return tslib_1.__generator(this, function (_a) {
|
34 | switch (_a.label) {
|
35 | case 0:
|
36 | _a.trys.push([0, 2, , 3]);
|
37 | return [4 , runWorker(options, logger)];
|
38 | case 1: return [2 , _a.sent()];
|
39 | case 2:
|
40 | error_2 = _a.sent();
|
41 | if (error_2 instanceof error_1.FatalError) {
|
42 | logger.error(error_2.message + "\n");
|
43 | return [2 , 1 ];
|
44 | }
|
45 | throw error_2;
|
46 | case 3: return [2 ];
|
47 | }
|
48 | });
|
49 | });
|
50 | }
|
51 | exports.run = run;
|
52 | function runWorker(options, logger) {
|
53 | return tslib_1.__awaiter(this, void 0, void 0, function () {
|
54 | var test_1, results, _a, output, errorCount;
|
55 | return tslib_1.__generator(this, function (_b) {
|
56 | switch (_b.label) {
|
57 | case 0:
|
58 | if (options.init) {
|
59 | if (fs.existsSync(configuration_1.JSON_CONFIG_FILENAME)) {
|
60 | throw new error_1.FatalError("Cannot generate " + configuration_1.JSON_CONFIG_FILENAME + ": file already exists");
|
61 | }
|
62 | fs.writeFileSync(configuration_1.JSON_CONFIG_FILENAME, JSON.stringify(configuration_1.DEFAULT_CONFIG, undefined, " "));
|
63 | return [2 , 0 ];
|
64 | }
|
65 | if (!options.test) return [3 , 2];
|
66 | return [4 , Promise.resolve().then(function () { return require("./test"); })];
|
67 | case 1:
|
68 | test_1 = _b.sent();
|
69 | results = test_1.runTests((options.files || []).map(trimSingleQuotes), options.rulesDirectory);
|
70 | return [2 , test_1.consoleTestResultsHandler(results, logger) ? 0 : 1 ];
|
71 | case 2:
|
72 | if (options.config && !fs.existsSync(options.config)) {
|
73 | throw new error_1.FatalError("Invalid option for configuration: " + options.config);
|
74 | }
|
75 | return [4 , runLinter(options, logger)];
|
76 | case 3:
|
77 | _a = _b.sent(), output = _a.output, errorCount = _a.errorCount;
|
78 | if (output && output.trim()) {
|
79 | logger.log(output + "\n");
|
80 | }
|
81 | return [2 , options.force || errorCount === 0 ? 0 : 2 ];
|
82 | }
|
83 | });
|
84 | });
|
85 | }
|
86 | function runLinter(options, logger) {
|
87 | return tslib_1.__awaiter(this, void 0, void 0, function () {
|
88 | var _a, files, program, diagnostics, message;
|
89 | return tslib_1.__generator(this, function (_b) {
|
90 | _a = resolveFilesAndProgram(options, logger), files = _a.files, program = _a.program;
|
91 |
|
92 | if (program && options.typeCheck) {
|
93 | diagnostics = ts.getPreEmitDiagnostics(program);
|
94 | if (diagnostics.length !== 0) {
|
95 | message = diagnostics.map(function (d) { return showDiagnostic(d, program, options.outputAbsolutePaths); }).join("\n");
|
96 | if (options.force) {
|
97 | logger.error(message + "\n");
|
98 | }
|
99 | else {
|
100 | throw new error_1.FatalError(message);
|
101 | }
|
102 | }
|
103 | }
|
104 | return [2 , doLinting(options, files, program, logger)];
|
105 | });
|
106 | });
|
107 | }
|
108 | function resolveFilesAndProgram(_a, logger) {
|
109 | var files = _a.files, project = _a.project, exclude = _a.exclude, outputAbsolutePaths = _a.outputAbsolutePaths;
|
110 |
|
111 | exclude = exclude.map(trimSingleQuotes);
|
112 | if (project === undefined) {
|
113 | return { files: resolveGlobs(files, exclude, outputAbsolutePaths, logger) };
|
114 | }
|
115 | var projectPath = findTsconfig(project);
|
116 | if (projectPath === undefined) {
|
117 | throw new error_1.FatalError("Invalid option for project: " + project);
|
118 | }
|
119 | exclude = exclude.map(function (pattern) { return path.resolve(pattern); });
|
120 | var program = linter_1.Linter.createProgram(projectPath);
|
121 | var filesFound;
|
122 | if (files.length === 0) {
|
123 | filesFound = filterFiles(linter_1.Linter.getFileNames(program), exclude, false);
|
124 | }
|
125 | else {
|
126 | files = files.map(function (f) { return path.resolve(f); });
|
127 | filesFound = filterFiles(program.getSourceFiles().map(function (f) { return f.fileName; }), files, true);
|
128 | filesFound = filterFiles(filesFound, exclude, false);
|
129 |
|
130 | for (var _i = 0, _b = filterFiles(files, exclude, false); _i < _b.length; _i++) {
|
131 | var file = _b[_i];
|
132 | if (!glob.hasMagic(file) && !filesFound.some(minimatch_1.filter(file))) {
|
133 | if (fs.existsSync(file)) {
|
134 | throw new error_1.FatalError("'" + file + "' is not included in project.");
|
135 | }
|
136 | logger.error("'" + file + "' does not exist. This will be an error in TSLint 6.\n");
|
137 | }
|
138 | }
|
139 | }
|
140 | return { files: filesFound, program: program };
|
141 | }
|
142 | function filterFiles(files, patterns, include) {
|
143 | if (patterns.length === 0) {
|
144 | return include ? [] : files;
|
145 | }
|
146 | var matcher = patterns.map(function (pattern) { return new minimatch_1.Minimatch(pattern, { dot: !include }); });
|
147 | return files.filter(function (file) { return include === matcher.some(function (pattern) { return pattern.match(file); }); });
|
148 | }
|
149 | function resolveGlobs(files, ignore, outputAbsolutePaths, logger) {
|
150 | var results = utils_1.flatMap(files, function (file) { return glob.sync(trimSingleQuotes(file), { ignore: ignore, nodir: true }); });
|
151 |
|
152 | for (var _i = 0, _a = filterFiles(files, ignore, false); _i < _a.length; _i++) {
|
153 | var file = _a[_i];
|
154 | if (!glob.hasMagic(file) && !results.some(minimatch_1.filter(file))) {
|
155 | logger.error("'" + file + "' does not exist. This will be an error in TSLint 6.\n");
|
156 | }
|
157 | }
|
158 | var cwd = process.cwd();
|
159 | return results.map(function (file) { return outputAbsolutePaths ? path.resolve(cwd, file) : path.relative(cwd, file); });
|
160 | }
|
161 | function doLinting(options, files, program, logger) {
|
162 | return tslib_1.__awaiter(this, void 0, void 0, function () {
|
163 | function isFileExcluded(filepath) {
|
164 | if (configFile === undefined || configFile.linterOptions == undefined || configFile.linterOptions.exclude == undefined) {
|
165 | return false;
|
166 | }
|
167 | var fullPath = path.resolve(filepath);
|
168 | return configFile.linterOptions.exclude.some(function (pattern) { return new minimatch_1.Minimatch(pattern).match(fullPath); });
|
169 | }
|
170 | var linter, lastFolder, configFile, _i, files_1, file, folder, contents, sourceFile;
|
171 | return tslib_1.__generator(this, function (_a) {
|
172 | switch (_a.label) {
|
173 | case 0:
|
174 | linter = new linter_1.Linter({
|
175 | fix: !!options.fix,
|
176 | formatter: options.format,
|
177 | formattersDirectory: options.formattersDirectory,
|
178 | rulesDirectory: options.rulesDirectory,
|
179 | }, program);
|
180 | configFile = options.config !== undefined ? configuration_1.findConfiguration(options.config).results : undefined;
|
181 | _i = 0, files_1 = files;
|
182 | _a.label = 1;
|
183 | case 1:
|
184 | if (!(_i < files_1.length)) return [3 , 6];
|
185 | file = files_1[_i];
|
186 | if (options.config === undefined) {
|
187 | folder = path.dirname(file);
|
188 | if (lastFolder !== folder) {
|
189 | configFile = configuration_1.findConfiguration(null, folder).results;
|
190 | lastFolder = folder;
|
191 | }
|
192 | }
|
193 | if (isFileExcluded(file)) {
|
194 | return [3 , 5];
|
195 | }
|
196 | contents = void 0;
|
197 | if (!(program !== undefined)) return [3 , 2];
|
198 | sourceFile = program.getSourceFile(file);
|
199 | if (sourceFile !== undefined) {
|
200 | contents = sourceFile.text;
|
201 | }
|
202 | return [3 , 4];
|
203 | case 2: return [4 , tryReadFile(file, logger)];
|
204 | case 3:
|
205 | contents = _a.sent();
|
206 | _a.label = 4;
|
207 | case 4:
|
208 | if (contents !== undefined) {
|
209 | linter.lint(file, contents, configFile);
|
210 | }
|
211 | _a.label = 5;
|
212 | case 5:
|
213 | _i++;
|
214 | return [3 , 1];
|
215 | case 6: return [2 , linter.getResult()];
|
216 | }
|
217 | });
|
218 | });
|
219 | }
|
220 |
|
221 | function tryReadFile(filename, logger) {
|
222 | return tslib_1.__awaiter(this, void 0, void 0, function () {
|
223 | var buffer, fd;
|
224 | return tslib_1.__generator(this, function (_a) {
|
225 | if (!fs.existsSync(filename)) {
|
226 | throw new error_1.FatalError("Unable to open file: " + filename);
|
227 | }
|
228 | buffer = new Buffer(256);
|
229 | fd = fs.openSync(filename, "r");
|
230 | try {
|
231 | fs.readSync(fd, buffer, 0, 256, 0);
|
232 | if (buffer.readInt8(0) === 0x47 && buffer.readInt8(188) === 0x47) {
|
233 |
|
234 |
|
235 |
|
236 | logger.error(filename + ": ignoring MPEG transport stream\n");
|
237 | return [2 , undefined];
|
238 | }
|
239 | }
|
240 | finally {
|
241 | fs.closeSync(fd);
|
242 | }
|
243 | return [2 , fs.readFileSync(filename, "utf8")];
|
244 | });
|
245 | });
|
246 | }
|
247 | function showDiagnostic(_a, program, outputAbsolutePaths) {
|
248 | var file = _a.file, start = _a.start, category = _a.category, messageText = _a.messageText;
|
249 | var message = ts.DiagnosticCategory[category];
|
250 | if (file !== undefined && start !== undefined) {
|
251 | var _b = file.getLineAndCharacterOfPosition(start), line = _b.line, character = _b.character;
|
252 | var currentDirectory = program.getCurrentDirectory();
|
253 | var filePath = outputAbsolutePaths
|
254 | ? path.resolve(currentDirectory, file.fileName)
|
255 | : path.relative(currentDirectory, file.fileName);
|
256 | message += " at " + filePath + ":" + (line + 1) + ":" + (character + 1) + ":";
|
257 | }
|
258 | return message + " " + ts.flattenDiagnosticMessageText(messageText, "\n");
|
259 | }
|
260 | function trimSingleQuotes(str) {
|
261 | return str.replace(/^'|'$/g, "");
|
262 | }
|
263 | function findTsconfig(project) {
|
264 | try {
|
265 | var stats = fs.statSync(project);
|
266 | if (!stats.isDirectory()) {
|
267 | return project;
|
268 | }
|
269 | var projectFile = path.join(project, "tsconfig.json");
|
270 | fs.accessSync(projectFile);
|
271 | return projectFile;
|
272 | }
|
273 | catch (e) {
|
274 | return undefined;
|
275 | }
|
276 | }
|