1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
16 | return new (P || (P = Promise))(function (resolve, reject) {
|
17 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
18 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
19 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
20 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
21 | });
|
22 | };
|
23 | Object.defineProperty(exports, "__esModule", { value: true });
|
24 | const chalk = require("chalk");
|
25 | const code_printer_1 = require("../warning/code-printer");
|
26 | const source_range_1 = require("./source-range");
|
27 | const stable = require('stable');
|
28 | class Warning {
|
29 | constructor(init) {
|
30 | |
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 | this.actions = undefined;
|
37 | ({
|
38 | message: this.message,
|
39 | sourceRange: this.sourceRange,
|
40 | severity: this.severity,
|
41 | code: this.code,
|
42 | parsedDocument: this._parsedDocument
|
43 | } = init);
|
44 | this.fix = init.fix;
|
45 | this.actions = init.actions;
|
46 | if (!this.sourceRange) {
|
47 | throw new Error(`Attempted to construct a ${this.code} ` +
|
48 | `warning without a source range.`);
|
49 | }
|
50 | if (!this._parsedDocument) {
|
51 | throw new Error(`Attempted to construct a ${this.code} ` +
|
52 | `warning without a parsed document.`);
|
53 | }
|
54 | }
|
55 | toString(options = {}) {
|
56 | const opts = Object.assign({}, defaultPrinterOptions, options);
|
57 | const colorize = opts.color ? this._severityToColorFunction(this.severity) :
|
58 | (s) => s;
|
59 | const severity = this._severityToString(colorize);
|
60 | let result = '';
|
61 | if (options.verbosity !== 'one-line') {
|
62 | const underlined = code_printer_1.underlineCode(this.sourceRange, this._parsedDocument, colorize, options.maxCodeLines);
|
63 | if (underlined) {
|
64 | result += underlined;
|
65 | }
|
66 | if (options.verbosity === 'code-only') {
|
67 | return result;
|
68 | }
|
69 | result += '\n\n';
|
70 | }
|
71 | let file = this.sourceRange.file;
|
72 | if (opts.resolver) {
|
73 | file = opts.resolver.relative(this.sourceRange.file);
|
74 | }
|
75 | result += `${file}(${this.sourceRange.start.line + 1},${this.sourceRange.start.column +
|
76 | 1}) ${severity} [${this.code}] - ${this.message}\n`;
|
77 | return result;
|
78 | }
|
79 | _severityToColorFunction(severity) {
|
80 | switch (severity) {
|
81 | case Severity.ERROR:
|
82 | return chalk.red;
|
83 | case Severity.WARNING:
|
84 | return chalk.yellow;
|
85 | case Severity.INFO:
|
86 | return chalk.green;
|
87 | default:
|
88 | const never = severity;
|
89 | throw new Error(`Unknown severity value - ${never}` +
|
90 | ` - encountered while printing warning.`);
|
91 | }
|
92 | }
|
93 | _severityToString(colorize) {
|
94 | switch (this.severity) {
|
95 | case Severity.ERROR:
|
96 | return colorize('error');
|
97 | case Severity.WARNING:
|
98 | return colorize('warning');
|
99 | case Severity.INFO:
|
100 | return colorize('info');
|
101 | default:
|
102 | const never = this.severity;
|
103 | throw new Error(`Unknown severity value - ${never} - ` +
|
104 | `encountered while printing warning.`);
|
105 | }
|
106 | }
|
107 | toJSON() {
|
108 | return {
|
109 | code: this.code,
|
110 | message: this.message,
|
111 | severity: this.severity,
|
112 | sourceRange: this.sourceRange,
|
113 | };
|
114 | }
|
115 | }
|
116 | exports.Warning = Warning;
|
117 | var Severity;
|
118 | (function (Severity) {
|
119 | Severity[Severity["ERROR"] = 0] = "ERROR";
|
120 | Severity[Severity["WARNING"] = 1] = "WARNING";
|
121 | Severity[Severity["INFO"] = 2] = "INFO";
|
122 | })(Severity = exports.Severity || (exports.Severity = {}));
|
123 |
|
124 | class WarningCarryingException extends Error {
|
125 | constructor(warning) {
|
126 | super(warning.message);
|
127 | this.warning = warning;
|
128 | }
|
129 | }
|
130 | exports.WarningCarryingException = WarningCarryingException;
|
131 | const defaultPrinterOptions = {
|
132 | verbosity: 'full',
|
133 | color: true
|
134 | };
|
135 |
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 | function applyEdits(edits, loader) {
|
143 | return __awaiter(this, void 0, void 0, function* () {
|
144 | const result = {
|
145 | appliedEdits: [],
|
146 | incompatibleEdits: [],
|
147 | editedFiles: new Map()
|
148 | };
|
149 | const replacementsByFile = new Map();
|
150 | for (const edit of edits) {
|
151 | if (canApply(edit, replacementsByFile)) {
|
152 | result.appliedEdits.push(edit);
|
153 | }
|
154 | else {
|
155 | result.incompatibleEdits.push(edit);
|
156 | }
|
157 | }
|
158 | for (const [file, replacements] of replacementsByFile) {
|
159 | const document = yield loader(file);
|
160 | let contents = document.contents;
|
161 | |
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 | stable.inplace(replacements, (a, b) => {
|
171 | const leftEdgeComp = source_range_1.comparePositionAndRange(b.range.start, a.range, true);
|
172 | if (leftEdgeComp !== 0) {
|
173 | return leftEdgeComp;
|
174 | }
|
175 | return source_range_1.comparePositionAndRange(b.range.end, a.range, false);
|
176 | });
|
177 | for (const replacement of replacements) {
|
178 | const offsets = document.sourceRangeToOffsets(replacement.range);
|
179 | contents = contents.slice(0, offsets[0]) + replacement.replacementText +
|
180 | contents.slice(offsets[1]);
|
181 | }
|
182 | result.editedFiles.set(file, contents);
|
183 | }
|
184 | return result;
|
185 | });
|
186 | }
|
187 | exports.applyEdits = applyEdits;
|
188 |
|
189 |
|
190 |
|
191 |
|
192 | function canApply(edit, replacements) {
|
193 | for (let i = 0; i < edit.length; i++) {
|
194 | const replacement = edit[i];
|
195 | const fileLocalReplacements = replacements.get(replacement.range.file) || [];
|
196 |
|
197 | for (const acceptedReplacement of fileLocalReplacements) {
|
198 | if (!areReplacementsCompatible(replacement, acceptedReplacement)) {
|
199 | return false;
|
200 | }
|
201 | }
|
202 |
|
203 | for (let j = 0; j < i; j++) {
|
204 | const acceptedReplacement = edit[j];
|
205 | if (!areReplacementsCompatible(replacement, acceptedReplacement)) {
|
206 | return false;
|
207 | }
|
208 | }
|
209 | }
|
210 |
|
211 | for (const replacement of edit) {
|
212 | if (!replacements.has(replacement.range.file)) {
|
213 | replacements.set(replacement.range.file, [replacement]);
|
214 | }
|
215 | else {
|
216 | const fileReplacements = replacements.get(replacement.range.file);
|
217 | fileReplacements.push(replacement);
|
218 | }
|
219 | }
|
220 | return true;
|
221 | }
|
222 | function areReplacementsCompatible(a, b) {
|
223 | if (a.range.file !== b.range.file) {
|
224 | return true;
|
225 | }
|
226 | if (areRangesEqual(a.range, b.range)) {
|
227 |
|
228 |
|
229 | return (a.range.start.column === a.range.end.column &&
|
230 | a.range.start.line === a.range.end.line);
|
231 | }
|
232 | return !(source_range_1.isPositionInsideRange(a.range.start, b.range, false) ||
|
233 | source_range_1.isPositionInsideRange(a.range.end, b.range, false) ||
|
234 | source_range_1.isPositionInsideRange(b.range.start, a.range, false) ||
|
235 | source_range_1.isPositionInsideRange(b.range.end, a.range, false));
|
236 | }
|
237 | function areRangesEqual(a, b) {
|
238 | return a.start.line === b.start.line && a.start.column === b.start.column &&
|
239 | a.end.line === b.end.line && a.end.column === b.end.column;
|
240 | }
|
241 | function makeParseLoader(analyzer, analysis) {
|
242 | return (url) => __awaiter(this, void 0, void 0, function* () {
|
243 | if (analysis) {
|
244 | const cachedResult = analysis.getDocument(url);
|
245 | if (cachedResult.successful) {
|
246 | return cachedResult.value.parsedDocument;
|
247 | }
|
248 | }
|
249 | const result = (yield analyzer.analyze([url])).getDocument(url);
|
250 | if (result.successful) {
|
251 | return result.value.parsedDocument;
|
252 | }
|
253 | let message = '';
|
254 | if (result.error) {
|
255 | message = result.error.message;
|
256 | }
|
257 | throw new Error(`Cannot load file at: ${JSON.stringify(url)}: ${message}`);
|
258 | });
|
259 | }
|
260 | exports.makeParseLoader = makeParseLoader;
|
261 |
|
\ | No newline at end of file |