UNPKG

@ui5/linter

Version:

A static code analysis tool for UI5

120 lines 5.21 kB
import path from "node:path/posix"; import { TraceMap } from "@jridgewell/trace-mapping"; import { resolveLinks } from "../../formatter/lib/resolveLinks.js"; import { MESSAGE } from "../messages.js"; import { getPositionsForNode } from "../../utils/nodePosition.js"; export default class SourceFileReporter { #context; #resourcePath; #originalResourcePath; #sourceFile; #traceMap; #rawMessages = []; #coverageInfo = []; constructor(context, sourceFile, sourceMap) { this.#context = context; this.#resourcePath = sourceFile.fileName; this.#sourceFile = sourceFile; if (sourceMap) { const parsedSourceMap = JSON.parse(sourceMap); if (parsedSourceMap.mappings !== "" && !("sections" in parsedSourceMap)) { // Only create a trace map if there are mappings. // Otherwise, it will be useless and causes errors in some cases (Failed to map back to source). // Also, sections are not supported as they only appear in bundles, which in general are not supported // as source files should be linted individually. this.#traceMap = new TraceMap(parsedSourceMap); } } this.#originalResourcePath = this.#getOriginalResourcePath() ?? this.#resourcePath; // Do not use messages from context yet, to allow local de-duplication this.#coverageInfo = context.getCoverageInfo(this.#originalResourcePath); } addMessage(id, args, options) { let position; const { node, ui5TypeInfo, fix } = options; if (node) { const { start } = this.getPositionsForNode(node); // One-based to be aligned with most IDEs position = start; } else { // If no node is provided, use the first column of the first line of the source file position = { line: 1, column: 1, }; } args ??= null; this.#rawMessages.push({ id, args, position, fix, ui5TypeInfo }); } addCoverageInfo({ node, message, messageDetails, category }) { const { start } = this.getPositionsForNode(node); const coverageInfo = { category, // One-based to be aligned with most IDEs line: start.line, column: start.column, // endLine: end.line + 1, // endColumn: end.column + 1, message, }; if (messageDetails) { coverageInfo.messageDetails = resolveLinks(messageDetails); } this.#coverageInfo.push(coverageInfo); } getPositionsForNode(node) { return getPositionsForNode({ node, sourceFile: this.#sourceFile, traceMap: this.#traceMap, resourcePath: this.#resourcePath, }); } #getOriginalResourcePath() { if (this.#traceMap?.sources?.length && this.#traceMap.sources[0] && this.#traceMap.sources[0] !== "UNKNOWN") { return path.join(path.dirname(this.#resourcePath), this.#traceMap.sources[0]); } } addMessagesToContext() { const lineColumnRawMessagesMap = new Map(); const rawMessages = []; if (this.#rawMessages.length === 0) { return; } for (const message of this.#rawMessages) { // Group messages by line/column so that we can deduplicate them if (!message.position?.line || !message.position?.column) { // If there is no line or column, we cannot group/deduplicate rawMessages.push(message); continue; } const lineColumnKey = `${message.position.line}:${message.position.column}`; let lineColumnMessages = lineColumnRawMessagesMap.get(lineColumnKey); if (!lineColumnMessages) { lineColumnMessages = []; lineColumnRawMessagesMap.set(lineColumnKey, lineColumnMessages); } lineColumnMessages.push(message); } // Add deduplicated messages to the result for (const lineColumnMessages of lineColumnRawMessagesMap.values()) { // If there are multiple messages for the same line/column, // and at least one of them is NOT a "no-globals-js" message, // we can deduplicate the "no-globals-js" messages. const deduplicateGlobalMessages = lineColumnMessages.length > 1 && lineColumnMessages.some((message) => message.id !== MESSAGE.NO_GLOBALS); lineColumnMessages.forEach((message) => { if (deduplicateGlobalMessages && message.id === MESSAGE.NO_GLOBALS) { // Skip global messages if there are other messages for the same line/column return; } rawMessages.push(message); }); } this.#context.addLintingMessages(this.#originalResourcePath, rawMessages); this.#rawMessages = []; // Prevent messages from being added multiple times } } //# sourceMappingURL=SourceFileReporter.js.map