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 chalk_1 = require("chalk");
|
20 | var diff = require("diff");
|
21 | var fs = require("fs");
|
22 | var glob = require("glob");
|
23 | var path = require("path");
|
24 | var semver = require("semver");
|
25 | var ts = require("typescript");
|
26 | var rule_1 = require("./language/rule/rule");
|
27 | var linter_1 = require("./linter");
|
28 | var utils_1 = require("./utils");
|
29 | var parse = require("./verify/parse");
|
30 | var MARKUP_FILE_EXTENSION = ".lint";
|
31 | var FIXES_FILE_EXTENSION = ".fix";
|
32 | function runTests(patterns, rulesDirectory) {
|
33 | var files = [];
|
34 | for (var _i = 0, patterns_1 = patterns; _i < patterns_1.length; _i++) {
|
35 | var pattern = patterns_1[_i];
|
36 | if (path.basename(pattern) !== "tslint.json") {
|
37 | pattern = path.join(pattern, "tslint.json");
|
38 | }
|
39 | files.push.apply(files, glob.sync(pattern));
|
40 | }
|
41 | return files.map(function (directory) { return runTest(path.dirname(directory), rulesDirectory); });
|
42 | }
|
43 | exports.runTests = runTests;
|
44 | function runTest(testDirectory, rulesDirectory) {
|
45 | var filesToLint = glob.sync(path.join(testDirectory, "**/*" + MARKUP_FILE_EXTENSION));
|
46 | var tslintConfig = linter_1.Linter.findConfiguration(path.join(testDirectory, "tslint.json"), "")
|
47 | .results;
|
48 | var tsConfig = path.join(testDirectory, "tsconfig.json");
|
49 | var compilerOptions = { allowJs: true };
|
50 | var hasConfig = fs.existsSync(tsConfig);
|
51 | if (hasConfig) {
|
52 | var _a = ts.readConfigFile(tsConfig, ts.sys.readFile), config = _a.config, error = _a.error;
|
53 | if (error !== undefined) {
|
54 | throw new Error(ts.formatDiagnostics([error], ts.createCompilerHost({})));
|
55 | }
|
56 | var parseConfigHost = {
|
57 | fileExists: fs.existsSync,
|
58 | readDirectory: ts.sys.readDirectory,
|
59 | readFile: function (file) { return fs.readFileSync(file, "utf8"); },
|
60 | useCaseSensitiveFileNames: true,
|
61 | };
|
62 | compilerOptions = ts.parseJsonConfigFileContent(config, parseConfigHost, testDirectory)
|
63 | .options;
|
64 | }
|
65 | var results = { directory: testDirectory, results: {} };
|
66 | var _loop_1 = function (fileToLint) {
|
67 | var isEncodingRule = path.basename(testDirectory) === "encoding";
|
68 | var fileCompileName = utils_1.denormalizeWinPath(path.resolve(fileToLint.replace(/\.lint$/, "")));
|
69 | var fileText = isEncodingRule
|
70 | ? utils_1.readBufferWithDetectedEncoding(fs.readFileSync(fileToLint))
|
71 | : fs.readFileSync(fileToLint, "utf-8");
|
72 | var tsVersionRequirement = parse.getTypescriptVersionRequirement(fileText);
|
73 | if (tsVersionRequirement !== undefined) {
|
74 |
|
75 | if (!semver.satisfies(parse.getNormalizedTypescriptVersion(), tsVersionRequirement)) {
|
76 | results.results[fileToLint] = {
|
77 | requirement: tsVersionRequirement,
|
78 | skipped: true,
|
79 | };
|
80 | return "continue";
|
81 | }
|
82 |
|
83 | var lineBreak = fileText.search(/\n/);
|
84 | fileText = lineBreak === -1 ? "" : fileText.substr(lineBreak + 1);
|
85 | }
|
86 | fileText = parse.preprocessDirectives(fileText);
|
87 | var fileTextWithoutMarkup = parse.removeErrorMarkup(fileText);
|
88 | var errorsFromMarkup = parse.parseErrorsFromMarkup(fileText);
|
89 | var program = void 0;
|
90 | if (hasConfig) {
|
91 | var compilerHost = {
|
92 | fileExists: function (file) { return file === fileCompileName || fs.existsSync(file); },
|
93 | getCanonicalFileName: function (filename) { return filename; },
|
94 | getCurrentDirectory: function () { return process.cwd(); },
|
95 | getDefaultLibFileName: function () { return ts.getDefaultLibFileName(compilerOptions); },
|
96 | getDirectories: function (dir) { return fs.readdirSync(dir); },
|
97 | getNewLine: function () { return "\n"; },
|
98 | getSourceFile: function (filenameToGet, target) {
|
99 | if (utils_1.denormalizeWinPath(filenameToGet) === fileCompileName) {
|
100 | return ts.createSourceFile(filenameToGet, fileTextWithoutMarkup, target, true);
|
101 | }
|
102 | if (path.basename(filenameToGet) === filenameToGet) {
|
103 |
|
104 | filenameToGet = path.join(path.dirname(ts.getDefaultLibFilePath(compilerOptions)), filenameToGet);
|
105 | }
|
106 | var text = fs.readFileSync(filenameToGet, "utf8");
|
107 | return ts.createSourceFile(filenameToGet, text, target, true);
|
108 | },
|
109 | readFile: function (x) { return x; },
|
110 | useCaseSensitiveFileNames: function () { return true; },
|
111 | writeFile: function () { return null; },
|
112 | };
|
113 | program = ts.createProgram([fileCompileName], compilerOptions, compilerHost);
|
114 | }
|
115 | var lintOptions = {
|
116 | fix: false,
|
117 | formatter: "prose",
|
118 | formattersDirectory: "",
|
119 | rulesDirectory: rulesDirectory,
|
120 | };
|
121 | var linter = new linter_1.Linter(lintOptions, program);
|
122 |
|
123 | linter.lint(isEncodingRule ? fileToLint : fileCompileName, fileTextWithoutMarkup, tslintConfig);
|
124 | var failures = linter.getResult().failures;
|
125 | var errorsFromLinter = failures.map(function (failure) {
|
126 | var startLineAndCharacter = failure.getStartPosition().getLineAndCharacter();
|
127 | var endLineAndCharacter = failure.getEndPosition().getLineAndCharacter();
|
128 | return {
|
129 | endPos: {
|
130 | col: endLineAndCharacter.character,
|
131 | line: endLineAndCharacter.line,
|
132 | },
|
133 | message: failure.getFailure(),
|
134 | startPos: {
|
135 | col: startLineAndCharacter.character,
|
136 | line: startLineAndCharacter.line,
|
137 | },
|
138 | };
|
139 | });
|
140 |
|
141 | var fixedFileText = "";
|
142 | var newFileText = "";
|
143 | try {
|
144 | var fixedFile = fileToLint.replace(/\.lint$/, FIXES_FILE_EXTENSION);
|
145 | var stat = fs.statSync(fixedFile);
|
146 | if (stat.isFile()) {
|
147 | fixedFileText = fs.readFileSync(fixedFile, "utf8");
|
148 | var fixes = utils_1.mapDefined(failures, function (f) { return f.getFix(); });
|
149 | newFileText = rule_1.Replacement.applyFixes(fileTextWithoutMarkup, fixes);
|
150 | }
|
151 | }
|
152 | catch (e) {
|
153 | fixedFileText = "";
|
154 | newFileText = "";
|
155 | }
|
156 | results.results[fileToLint] = {
|
157 | errorsFromLinter: errorsFromLinter,
|
158 | errorsFromMarkup: errorsFromMarkup,
|
159 | fixesFromLinter: newFileText,
|
160 | fixesFromMarkup: fixedFileText,
|
161 | markupFromLinter: parse.createMarkupFromErrors(fileTextWithoutMarkup, errorsFromMarkup),
|
162 | markupFromMarkup: parse.createMarkupFromErrors(fileTextWithoutMarkup, errorsFromLinter),
|
163 | skipped: false,
|
164 | };
|
165 | };
|
166 | for (var _i = 0, filesToLint_1 = filesToLint; _i < filesToLint_1.length; _i++) {
|
167 | var fileToLint = filesToLint_1[_i];
|
168 | _loop_1(fileToLint);
|
169 | }
|
170 | return results;
|
171 | }
|
172 | exports.runTest = runTest;
|
173 | function consoleTestResultsHandler(testResults, logger) {
|
174 | var didAllTestsPass = true;
|
175 | for (var _i = 0, testResults_1 = testResults; _i < testResults_1.length; _i++) {
|
176 | var testResult = testResults_1[_i];
|
177 | if (!consoleTestResultHandler(testResult, logger)) {
|
178 | didAllTestsPass = false;
|
179 | }
|
180 | }
|
181 | return didAllTestsPass;
|
182 | }
|
183 | exports.consoleTestResultsHandler = consoleTestResultsHandler;
|
184 | function consoleTestResultHandler(testResult, logger) {
|
185 |
|
186 | chalk_1.default.enabled = true;
|
187 | var didAllTestsPass = true;
|
188 | for (var _i = 0, _a = Object.keys(testResult.results); _i < _a.length; _i++) {
|
189 | var fileName = _a[_i];
|
190 | var results = testResult.results[fileName];
|
191 | logger.log(fileName + ":");
|
192 | if (results.skipped) {
|
193 | logger.log(chalk_1.default.yellow(" Skipped, requires typescript " + results.requirement + "\n"));
|
194 | }
|
195 | else {
|
196 | var markupDiffResults = diff.diffLines(results.markupFromMarkup, results.markupFromLinter);
|
197 | var fixesDiffResults = diff.diffLines(results.fixesFromLinter, results.fixesFromMarkup);
|
198 | var didMarkupTestPass = !markupDiffResults.some(function (hunk) { return hunk.added === true || hunk.removed === true; });
|
199 | var didFixesTestPass = !fixesDiffResults.some(function (hunk) { return hunk.added === true || hunk.removed === true; });
|
200 | if (didMarkupTestPass && didFixesTestPass) {
|
201 | logger.log(chalk_1.default.green(" Passed\n"));
|
202 | }
|
203 | else {
|
204 | logger.log(chalk_1.default.red(" Failed!\n"));
|
205 | didAllTestsPass = false;
|
206 | if (!didMarkupTestPass) {
|
207 | displayDiffResults(markupDiffResults, MARKUP_FILE_EXTENSION, logger);
|
208 | }
|
209 | if (!didFixesTestPass) {
|
210 | displayDiffResults(fixesDiffResults, FIXES_FILE_EXTENSION, logger);
|
211 | }
|
212 | }
|
213 | }
|
214 | }
|
215 | return didAllTestsPass;
|
216 | }
|
217 | exports.consoleTestResultHandler = consoleTestResultHandler;
|
218 | function displayDiffResults(diffResults, extension, logger) {
|
219 | logger.log(chalk_1.default.green("Expected (from " + extension + " file)\n"));
|
220 | logger.log(chalk_1.default.red("Actual (from TSLint)\n"));
|
221 | var _loop_2 = function (diffResult) {
|
222 | var color = chalk_1.default.grey;
|
223 | var prefix = " ";
|
224 | if (diffResult.added) {
|
225 | color = chalk_1.default.green.underline;
|
226 | prefix = "+ ";
|
227 | }
|
228 | else if (diffResult.removed) {
|
229 | color = chalk_1.default.red.underline;
|
230 | prefix = "- ";
|
231 | }
|
232 | logger.log(color(diffResult.value
|
233 | .split(/\r\n|\r|\n/)
|
234 |
|
235 |
|
236 | .map(function (line, index, array) {
|
237 | return index === array.length - 1 ? line : "" + prefix + line + "\n";
|
238 | })
|
239 | .join("")));
|
240 | };
|
241 | for (var _i = 0, diffResults_1 = diffResults; _i < diffResults_1.length; _i++) {
|
242 | var diffResult = diffResults_1[_i];
|
243 | _loop_2(diffResult);
|
244 | }
|
245 | }
|