1 | "use strict";
|
2 |
|
3 |
|
4 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
5 | if (k2 === undefined) k2 = k;
|
6 | var desc = Object.getOwnPropertyDescriptor(m, k);
|
7 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
8 | desc = { enumerable: true, get: function() { return m[k]; } };
|
9 | }
|
10 | Object.defineProperty(o, k2, desc);
|
11 | }) : (function(o, m, k, k2) {
|
12 | if (k2 === undefined) k2 = k;
|
13 | o[k2] = m[k];
|
14 | }));
|
15 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
16 | Object.defineProperty(o, "default", { enumerable: true, value: v });
|
17 | }) : function(o, v) {
|
18 | o["default"] = v;
|
19 | });
|
20 | var __importStar = (this && this.__importStar) || function (mod) {
|
21 | if (mod && mod.__esModule) return mod;
|
22 | var result = {};
|
23 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
24 | __setModuleDefault(result, mod);
|
25 | return result;
|
26 | };
|
27 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
28 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
29 | };
|
30 | Object.defineProperty(exports, "__esModule", { value: true });
|
31 | exports.MessageRouter = void 0;
|
32 | const colors_1 = __importDefault(require("colors"));
|
33 | const ts = __importStar(require("typescript"));
|
34 | const node_core_library_1 = require("@rushstack/node-core-library");
|
35 | const AstDeclaration_1 = require("../analyzer/AstDeclaration");
|
36 | const ExtractorMessage_1 = require("../api/ExtractorMessage");
|
37 | const ExtractorMessageId_1 = require("../api/ExtractorMessageId");
|
38 | class MessageRouter {
|
39 | constructor(options) {
|
40 |
|
41 | this._reportingRuleByMessageId = new Map();
|
42 | this._compilerDefaultRule = {
|
43 | logLevel: "none" ,
|
44 | addToApiReportFile: false
|
45 | };
|
46 | this._extractorDefaultRule = {
|
47 | logLevel: "none" ,
|
48 | addToApiReportFile: false
|
49 | };
|
50 | this._tsdocDefaultRule = { logLevel: "none" , addToApiReportFile: false };
|
51 | this.errorCount = 0;
|
52 | this.warningCount = 0;
|
53 | this._workingPackageFolder = options.workingPackageFolder;
|
54 | this._messageCallback = options.messageCallback;
|
55 | this._messages = [];
|
56 | this._associatedMessagesForAstDeclaration = new Map();
|
57 | this._sourceMapper = options.sourceMapper;
|
58 | this._tsdocConfiguration = options.tsdocConfiguration;
|
59 |
|
60 | this.showVerboseMessages = options.showVerboseMessages || options.showDiagnostics;
|
61 | this.showDiagnostics = options.showDiagnostics;
|
62 | this._applyMessagesConfig(options.messagesConfig);
|
63 | }
|
64 | |
65 |
|
66 |
|
67 | _applyMessagesConfig(messagesConfig) {
|
68 | if (messagesConfig.compilerMessageReporting) {
|
69 | for (const messageId of Object.getOwnPropertyNames(messagesConfig.compilerMessageReporting)) {
|
70 | const reportingRule = MessageRouter._getNormalizedRule(messagesConfig.compilerMessageReporting[messageId]);
|
71 | if (messageId === 'default') {
|
72 | this._compilerDefaultRule = reportingRule;
|
73 | }
|
74 | else if (!/^TS[0-9]+$/.test(messageId)) {
|
75 | throw new Error(`Error in API Extractor config: The messages.compilerMessageReporting table contains` +
|
76 | ` an invalid entry "${messageId}". The identifier format is "TS" followed by an integer.`);
|
77 | }
|
78 | else {
|
79 | this._reportingRuleByMessageId.set(messageId, reportingRule);
|
80 | }
|
81 | }
|
82 | }
|
83 | if (messagesConfig.extractorMessageReporting) {
|
84 | for (const messageId of Object.getOwnPropertyNames(messagesConfig.extractorMessageReporting)) {
|
85 | const reportingRule = MessageRouter._getNormalizedRule(messagesConfig.extractorMessageReporting[messageId]);
|
86 | if (messageId === 'default') {
|
87 | this._extractorDefaultRule = reportingRule;
|
88 | }
|
89 | else if (!/^ae-/.test(messageId)) {
|
90 | throw new Error(`Error in API Extractor config: The messages.extractorMessageReporting table contains` +
|
91 | ` an invalid entry "${messageId}". The name should begin with the "ae-" prefix.`);
|
92 | }
|
93 | else if (!ExtractorMessageId_1.allExtractorMessageIds.has(messageId)) {
|
94 | throw new Error(`Error in API Extractor config: The messages.extractorMessageReporting table contains` +
|
95 | ` an unrecognized identifier "${messageId}". Is it spelled correctly?`);
|
96 | }
|
97 | else {
|
98 | this._reportingRuleByMessageId.set(messageId, reportingRule);
|
99 | }
|
100 | }
|
101 | }
|
102 | if (messagesConfig.tsdocMessageReporting) {
|
103 | for (const messageId of Object.getOwnPropertyNames(messagesConfig.tsdocMessageReporting)) {
|
104 | const reportingRule = MessageRouter._getNormalizedRule(messagesConfig.tsdocMessageReporting[messageId]);
|
105 | if (messageId === 'default') {
|
106 | this._tsdocDefaultRule = reportingRule;
|
107 | }
|
108 | else if (!/^tsdoc-/.test(messageId)) {
|
109 | throw new Error(`Error in API Extractor config: The messages.tsdocMessageReporting table contains` +
|
110 | ` an invalid entry "${messageId}". The name should begin with the "tsdoc-" prefix.`);
|
111 | }
|
112 | else if (!this._tsdocConfiguration.isKnownMessageId(messageId)) {
|
113 | throw new Error(`Error in API Extractor config: The messages.tsdocMessageReporting table contains` +
|
114 | ` an unrecognized identifier "${messageId}". Is it spelled correctly?`);
|
115 | }
|
116 | else {
|
117 | this._reportingRuleByMessageId.set(messageId, reportingRule);
|
118 | }
|
119 | }
|
120 | }
|
121 | }
|
122 | static _getNormalizedRule(rule) {
|
123 | return {
|
124 | logLevel: rule.logLevel || 'none',
|
125 | addToApiReportFile: rule.addToApiReportFile || false
|
126 | };
|
127 | }
|
128 | get messages() {
|
129 | return this._messages;
|
130 | }
|
131 | |
132 |
|
133 |
|
134 | addCompilerDiagnostic(diagnostic) {
|
135 | switch (diagnostic.category) {
|
136 | case ts.DiagnosticCategory.Suggestion:
|
137 | case ts.DiagnosticCategory.Message:
|
138 | return;
|
139 | }
|
140 | const messageText = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
141 | const options = {
|
142 | category: "Compiler" ,
|
143 | messageId: `TS${diagnostic.code}`,
|
144 | text: messageText
|
145 | };
|
146 | if (diagnostic.file) {
|
147 |
|
148 |
|
149 | const sourceFile = diagnostic.file;
|
150 | const sourceLocation = this._sourceMapper.getSourceLocation({
|
151 | sourceFile,
|
152 | pos: diagnostic.start || 0,
|
153 | useDtsLocation: true
|
154 | });
|
155 | options.sourceFilePath = sourceLocation.sourceFilePath;
|
156 | options.sourceFileLine = sourceLocation.sourceFileLine;
|
157 | options.sourceFileColumn = sourceLocation.sourceFileColumn;
|
158 | }
|
159 | this._messages.push(new ExtractorMessage_1.ExtractorMessage(options));
|
160 | }
|
161 | |
162 |
|
163 |
|
164 | addAnalyzerIssue(messageId, messageText, astDeclarationOrSymbol, properties) {
|
165 | let astDeclaration;
|
166 | if (astDeclarationOrSymbol instanceof AstDeclaration_1.AstDeclaration) {
|
167 | astDeclaration = astDeclarationOrSymbol;
|
168 | }
|
169 | else {
|
170 | astDeclaration = astDeclarationOrSymbol.astDeclarations[0];
|
171 | }
|
172 | const extractorMessage = this.addAnalyzerIssueForPosition(messageId, messageText, astDeclaration.declaration.getSourceFile(), astDeclaration.declaration.getStart(), properties);
|
173 | this._associateMessageWithAstDeclaration(extractorMessage, astDeclaration);
|
174 | }
|
175 | |
176 |
|
177 |
|
178 |
|
179 | addTsdocMessages(parserContext, sourceFile, astDeclaration) {
|
180 | for (const message of parserContext.log.messages) {
|
181 | const options = {
|
182 | category: "TSDoc" ,
|
183 | messageId: message.messageId,
|
184 | text: message.unformattedText
|
185 | };
|
186 | const sourceLocation = this._sourceMapper.getSourceLocation({
|
187 | sourceFile,
|
188 | pos: message.textRange.pos
|
189 | });
|
190 | options.sourceFilePath = sourceLocation.sourceFilePath;
|
191 | options.sourceFileLine = sourceLocation.sourceFileLine;
|
192 | options.sourceFileColumn = sourceLocation.sourceFileColumn;
|
193 | const extractorMessage = new ExtractorMessage_1.ExtractorMessage(options);
|
194 | if (astDeclaration) {
|
195 | this._associateMessageWithAstDeclaration(extractorMessage, astDeclaration);
|
196 | }
|
197 | this._messages.push(extractorMessage);
|
198 | }
|
199 | }
|
200 | |
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 | static buildJsonDumpObject(input, options) {
|
209 | if (!options) {
|
210 | options = {};
|
211 | }
|
212 | const keyNamesToOmit = new Set(options.keyNamesToOmit);
|
213 | return MessageRouter._buildJsonDumpObject(input, keyNamesToOmit);
|
214 | }
|
215 |
|
216 | static _buildJsonDumpObject(input, keyNamesToOmit) {
|
217 | if (input === null || input === undefined) {
|
218 | return null;
|
219 | }
|
220 | switch (typeof input) {
|
221 | case 'boolean':
|
222 | case 'number':
|
223 | case 'string':
|
224 | return input;
|
225 | case 'object':
|
226 | if (Array.isArray(input)) {
|
227 |
|
228 | const outputArray = [];
|
229 | for (const element of input) {
|
230 |
|
231 | const serializedElement = MessageRouter._buildJsonDumpObject(element, keyNamesToOmit);
|
232 | if (serializedElement !== undefined) {
|
233 | outputArray.push(serializedElement);
|
234 | }
|
235 | }
|
236 | return outputArray;
|
237 | }
|
238 | const outputObject = {};
|
239 | for (const key of Object.getOwnPropertyNames(input)) {
|
240 | if (keyNamesToOmit.has(key)) {
|
241 | continue;
|
242 | }
|
243 |
|
244 | const value = input[key];
|
245 |
|
246 | const serializedValue = MessageRouter._buildJsonDumpObject(value, keyNamesToOmit);
|
247 | if (serializedValue !== undefined) {
|
248 |
|
249 | outputObject[key] = serializedValue;
|
250 | }
|
251 | }
|
252 | return outputObject;
|
253 | }
|
254 | return undefined;
|
255 | }
|
256 | |
257 |
|
258 |
|
259 | _associateMessageWithAstDeclaration(extractorMessage, astDeclaration) {
|
260 | let associatedMessages = this._associatedMessagesForAstDeclaration.get(astDeclaration);
|
261 | if (!associatedMessages) {
|
262 | associatedMessages = [];
|
263 | this._associatedMessagesForAstDeclaration.set(astDeclaration, associatedMessages);
|
264 | }
|
265 | associatedMessages.push(extractorMessage);
|
266 | }
|
267 | |
268 |
|
269 |
|
270 | addAnalyzerIssueForPosition(messageId, messageText, sourceFile, pos, properties) {
|
271 | const options = {
|
272 | category: "Extractor" ,
|
273 | messageId,
|
274 | text: messageText,
|
275 | properties
|
276 | };
|
277 | const sourceLocation = this._sourceMapper.getSourceLocation({
|
278 | sourceFile,
|
279 | pos
|
280 | });
|
281 | options.sourceFilePath = sourceLocation.sourceFilePath;
|
282 | options.sourceFileLine = sourceLocation.sourceFileLine;
|
283 | options.sourceFileColumn = sourceLocation.sourceFileColumn;
|
284 | const extractorMessage = new ExtractorMessage_1.ExtractorMessage(options);
|
285 | this._messages.push(extractorMessage);
|
286 | return extractorMessage;
|
287 | }
|
288 | |
289 |
|
290 |
|
291 |
|
292 |
|
293 | fetchAssociatedMessagesForReviewFile(astDeclaration) {
|
294 | const messagesForApiReportFile = [];
|
295 | const associatedMessages = this._associatedMessagesForAstDeclaration.get(astDeclaration) || [];
|
296 | for (const associatedMessage of associatedMessages) {
|
297 |
|
298 | if (!associatedMessage.handled) {
|
299 |
|
300 | const reportingRule = this._getRuleForMessage(associatedMessage);
|
301 | if (reportingRule.addToApiReportFile) {
|
302 |
|
303 | messagesForApiReportFile.push(associatedMessage);
|
304 | associatedMessage.handled = true;
|
305 | }
|
306 | }
|
307 | }
|
308 | this._sortMessagesForOutput(messagesForApiReportFile);
|
309 | return messagesForApiReportFile;
|
310 | }
|
311 | |
312 |
|
313 |
|
314 |
|
315 | fetchUnassociatedMessagesForReviewFile() {
|
316 | const messagesForApiReportFile = [];
|
317 | for (const unassociatedMessage of this.messages) {
|
318 |
|
319 | if (!unassociatedMessage.handled) {
|
320 |
|
321 | const reportingRule = this._getRuleForMessage(unassociatedMessage);
|
322 | if (reportingRule.addToApiReportFile) {
|
323 |
|
324 | messagesForApiReportFile.push(unassociatedMessage);
|
325 | unassociatedMessage.handled = true;
|
326 | }
|
327 | }
|
328 | }
|
329 | this._sortMessagesForOutput(messagesForApiReportFile);
|
330 | return messagesForApiReportFile;
|
331 | }
|
332 | |
333 |
|
334 |
|
335 |
|
336 |
|
337 | handleRemainingNonConsoleMessages() {
|
338 | const messagesForLogger = [];
|
339 | for (const message of this.messages) {
|
340 |
|
341 | if (!message.handled) {
|
342 | messagesForLogger.push(message);
|
343 | }
|
344 | }
|
345 | this._sortMessagesForOutput(messagesForLogger);
|
346 | for (const message of messagesForLogger) {
|
347 | this._handleMessage(message);
|
348 | }
|
349 | }
|
350 | logError(messageId, message, properties) {
|
351 | this._handleMessage(new ExtractorMessage_1.ExtractorMessage({
|
352 | category: "console" ,
|
353 | messageId,
|
354 | text: message,
|
355 | properties,
|
356 | logLevel: "error"
|
357 | }));
|
358 | }
|
359 | logWarning(messageId, message, properties) {
|
360 | this._handleMessage(new ExtractorMessage_1.ExtractorMessage({
|
361 | category: "console" ,
|
362 | messageId,
|
363 | text: message,
|
364 | properties,
|
365 | logLevel: "warning"
|
366 | }));
|
367 | }
|
368 | logInfo(messageId, message, properties) {
|
369 | this._handleMessage(new ExtractorMessage_1.ExtractorMessage({
|
370 | category: "console" ,
|
371 | messageId,
|
372 | text: message,
|
373 | properties,
|
374 | logLevel: "info"
|
375 | }));
|
376 | }
|
377 | logVerbose(messageId, message, properties) {
|
378 | this._handleMessage(new ExtractorMessage_1.ExtractorMessage({
|
379 | category: "console" ,
|
380 | messageId,
|
381 | text: message,
|
382 | properties,
|
383 | logLevel: "verbose"
|
384 | }));
|
385 | }
|
386 | logDiagnosticHeader(title) {
|
387 | this.logDiagnostic(MessageRouter.DIAGNOSTICS_LINE);
|
388 | this.logDiagnostic(`DIAGNOSTIC: ` + title);
|
389 | this.logDiagnostic(MessageRouter.DIAGNOSTICS_LINE);
|
390 | }
|
391 | logDiagnosticFooter() {
|
392 | this.logDiagnostic(MessageRouter.DIAGNOSTICS_LINE + '\n');
|
393 | }
|
394 | logDiagnostic(message) {
|
395 | if (this.showDiagnostics) {
|
396 | this.logVerbose("console-diagnostics" , message);
|
397 | }
|
398 | }
|
399 | |
400 |
|
401 |
|
402 | _handleMessage(message) {
|
403 |
|
404 | if (message.handled) {
|
405 | return;
|
406 | }
|
407 |
|
408 | if (message.category === "console" ) {
|
409 |
|
410 | }
|
411 | else {
|
412 | const reportingRule = this._getRuleForMessage(message);
|
413 | message.logLevel = reportingRule.logLevel;
|
414 | }
|
415 |
|
416 | if (this._messageCallback) {
|
417 | this._messageCallback(message);
|
418 | }
|
419 |
|
420 | switch (message.logLevel) {
|
421 | case "error" :
|
422 | ++this.errorCount;
|
423 | break;
|
424 | case "warning" :
|
425 | ++this.warningCount;
|
426 | break;
|
427 | }
|
428 | if (message.handled) {
|
429 | return;
|
430 | }
|
431 |
|
432 | message.handled = true;
|
433 | if (message.logLevel === "none" ) {
|
434 | return;
|
435 | }
|
436 | let messageText;
|
437 | if (message.category === "console" ) {
|
438 | messageText = message.text;
|
439 | }
|
440 | else {
|
441 | messageText = message.formatMessageWithLocation(this._workingPackageFolder);
|
442 | }
|
443 | switch (message.logLevel) {
|
444 | case "error" :
|
445 | console.error(colors_1.default.red('Error: ' + messageText));
|
446 | break;
|
447 | case "warning" :
|
448 | console.warn(colors_1.default.yellow('Warning: ' + messageText));
|
449 | break;
|
450 | case "info" :
|
451 | console.log(messageText);
|
452 | break;
|
453 | case "verbose" :
|
454 | if (this.showVerboseMessages) {
|
455 | console.log(colors_1.default.cyan(messageText));
|
456 | }
|
457 | break;
|
458 | default:
|
459 | throw new Error(`Invalid logLevel value: ${JSON.stringify(message.logLevel)}`);
|
460 | }
|
461 | }
|
462 | |
463 |
|
464 |
|
465 | _getRuleForMessage(message) {
|
466 | const reportingRule = this._reportingRuleByMessageId.get(message.messageId);
|
467 | if (reportingRule) {
|
468 | return reportingRule;
|
469 | }
|
470 | switch (message.category) {
|
471 | case "Compiler" :
|
472 | return this._compilerDefaultRule;
|
473 | case "Extractor" :
|
474 | return this._extractorDefaultRule;
|
475 | case "TSDoc" :
|
476 | return this._tsdocDefaultRule;
|
477 | case "console" :
|
478 | throw new node_core_library_1.InternalError('ExtractorMessageCategory.Console is not supported with IReportingRule');
|
479 | }
|
480 | }
|
481 | |
482 |
|
483 |
|
484 | _sortMessagesForOutput(messages) {
|
485 | messages.sort((a, b) => {
|
486 | let diff;
|
487 |
|
488 | diff = node_core_library_1.Sort.compareByValue(a.sourceFilePath, b.sourceFilePath);
|
489 | if (diff !== 0) {
|
490 | return diff;
|
491 | }
|
492 |
|
493 | diff = node_core_library_1.Sort.compareByValue(a.sourceFileLine, b.sourceFileLine);
|
494 | if (diff !== 0) {
|
495 | return diff;
|
496 | }
|
497 |
|
498 | return node_core_library_1.Sort.compareByValue(a.messageId, b.messageId);
|
499 | });
|
500 | }
|
501 | }
|
502 | exports.MessageRouter = MessageRouter;
|
503 | MessageRouter.DIAGNOSTICS_LINE = '============================================================';
|
504 |
|
\ | No newline at end of file |