diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c3b6d33a..99891b996 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Bug Fixes: - Fix our setting of `isUserPreset` for presets, only set it to `true` if it's defined in a user presets file. [#4059](https://github.com/microsoft/vscode-cmake-tools/issues/4059) - Fix issue where duplicate presets are being listed in dropdown. [#4104](https://github.com/microsoft/vscode-cmake-tools/issues/4104) +- Fix various GCC compiler errors and GCC linker errors not showing up in Problems View [#2864](https://github.com/microsoft/vscode-cmake-tools/issues/2864) ## 1.19.52 diff --git a/src/diagnostics/build.ts b/src/diagnostics/build.ts index 867d18f08..17c7e4809 100644 --- a/src/diagnostics/build.ts +++ b/src/diagnostics/build.ts @@ -21,9 +21,9 @@ export class Compilers { [compiler: string]: RawDiagnosticParser; gcc = new gcc.Parser(); + gnuld = new gnu_ld.Parser(); ghs = new ghs.Parser(); diab = new diab.Parser(); - gnuLD = new gnu_ld.Parser(); msvc = new mvsc.Parser(); iar = new iar.Parser(); } @@ -82,7 +82,7 @@ export class CompileOutputConsumer implements OutputConsumer { MSVC: this.compilers.msvc.diagnostics, GHS: this.compilers.ghs.diagnostics, DIAB: this.compilers.diab.diagnostics, - link: this.compilers.gnuLD.diagnostics, + GNULD: this.compilers.gnuld.diagnostics, IAR: this.compilers.iar.diagnostics }; const parsers = util.objectPairs(by_source) diff --git a/src/diagnostics/gcc.ts b/src/diagnostics/gcc.ts index 1dc02997b..8bc0eff9d 100644 --- a/src/diagnostics/gcc.ts +++ b/src/diagnostics/gcc.ts @@ -4,9 +4,23 @@ import * as vscode from 'vscode'; -import { oneLess, RawDiagnostic, RawDiagnosticParser, RawRelated, FeedLineResult } from '@cmt/diagnostics/util'; +import { oneLess, RawDiagnostic, RawDiagnosticParser, RawRelated, FeedLineResult, MatchType, RegexPattern } from '@cmt/diagnostics/util'; -export const REGEX = /^(.*):(\d+):(\d+):\s+(?:fatal )?(\w*)(?:\sfatale)?\s?:\s+(.*)/; +// Patterns to identify and capture GCC diagnostic messages. +const regexPatterns: RegexPattern[] = [ + { // path/to/file:line:column: severity: message + regexPattern: /^(.+):(\d+):(\d+):\s+(?:fatal\s+)?(\w+):\s+(.+)/, + matchTypes: [MatchType.Full, MatchType.File, MatchType.Line, MatchType.Column, MatchType.Severity, MatchType.Message] + }, + { // path/to/file:line: severity: message (but not starting with "path/to/ld[.exe]:") + regexPattern: /^(?!.*?ld(?:\.exe)?:)(.+):(\d+):\s+(?:fatal\s+)?(\w+):\s+(.+)/, + matchTypes: [MatchType.Full, MatchType.File, MatchType.Line, MatchType.Severity, MatchType.Message] + }, + { // path/to/cc1[.exe]|arm-none-eabi-gcc[.exe]: severity: message + regexPattern: /^(.*(?:cc1|arm-none-eabi-gcc)(?:\.exe)?):\s+(?:fatal\s+)?(\w+):\s+(.+)/, + matchTypes: [MatchType.Full, MatchType.File, MatchType.Severity, MatchType.Message] + } +]; interface PendingTemplateBacktrace { rootInstantiation: string; @@ -19,6 +33,11 @@ export class Parser extends RawDiagnosticParser { private _pendingTemplateError?: PendingTemplateBacktrace; doHandleLine(line: string) { + // Detect the first line of a C++ template error + // This is a special case which consists of 3 lines: + // path/to/file: In instantiation of ‘...’: + // path/to/file:lineno:columnno: required from here + // path/to/file:lineno:columnno: severity: message let mat = /(.*): (In instantiation of.+)/.exec(line); if (mat) { const [, , message] = mat; @@ -28,8 +47,8 @@ export class Parser extends RawDiagnosticParser { }; return FeedLineResult.Ok; } - if (this._pendingTemplateError) { + // Detect the second line of a pending C++ template error mat = /(.*):(\d+):(\d+):( +required from.+)/.exec(line); if (mat) { const [, file, linestr, column, message] = mat; @@ -43,7 +62,7 @@ export class Parser extends RawDiagnosticParser { } } - // Early-catch backtrace limit notes + // Detect backtrace limit notes in GCC diagnostics and append them to the previous diagnostic if one exists mat = /note: \((.*backtrace-limit.*)\)/.exec(line); if (mat && this._prevDiag && this._prevDiag.related.length !== 0) { const prevRelated = this._prevDiag.related[0]; @@ -55,47 +74,85 @@ export class Parser extends RawDiagnosticParser { return FeedLineResult.Ok; } - // Test if this is a diagnostic - mat = REGEX.exec(line); - if (!mat) { - // Nothing to see on this line of output... + // Attempt to parse a general diagnostic message using regex patterns defined in regexPatterns + let mat2 = null; + + let full = ""; + let file = ""; + let lineno = oneLess("1"); + let columnno = oneLess("1"); + let severity = 'error'; + let message = ""; + + for (const [, regexPattern] of regexPatterns.entries()) { + mat2 = line.match(regexPattern.regexPattern); + + if (mat2 !== null) { + // For each matchType in the pattern, assign values accordingly + for (let i = 0; i < mat2.length; i++) { + switch (regexPattern.matchTypes[i]) { + case MatchType.Full: + full = mat2[i]; + break; + case MatchType.File: + file = mat2[i]; + break; + case MatchType.Line: + lineno = oneLess(mat2[i]); + break; + case MatchType.Column: + columnno = oneLess(mat2[i]); + break; + case MatchType.Severity: + severity = mat2[i]; + break; + case MatchType.Message: + message = mat2[i]; + break; + default: + break; + } + } + break; + } + } + + if (!mat2) { + // Ignore this line because it is no matching diagnostic return FeedLineResult.NotMine; } else { - const [full, file, lineno_, column_, severity, message] = mat; - if (file && lineno_ && column_ && severity && message) { - const lineno = oneLess(lineno_); - const column = oneLess(column_); - if (severity === 'note' && this._prevDiag) { - this._prevDiag.related.push({ + // If severity is "note", append the message to the previous diagnostic's related messages + if (severity === 'note' && this._prevDiag) { + this._prevDiag.related.push({ + file, + location: new vscode.Range(lineno, columnno, lineno, 999), + message + }); + return FeedLineResult.Ok; + } else { + const related: RawRelated[] = []; + const location = new vscode.Range(lineno, columnno, lineno, 999); + if (this._pendingTemplateError) { + // If the diagnostic is the third line of a pending C++ template error, finalize it here + related.push({ + location, file, - location: new vscode.Range(lineno, column, lineno, 999), - message + message: this._pendingTemplateError.rootInstantiation }); - return FeedLineResult.Ok; - } else { - const related: RawRelated[] = []; - const location = new vscode.Range(lineno, column, lineno, 999); - if (this._pendingTemplateError) { - related.push({ - location, - file, - message: this._pendingTemplateError.rootInstantiation - }); - related.push(...this._pendingTemplateError.requiredFrom); - this._pendingTemplateError = undefined; - } - - return this._prevDiag = { - full, - file, - location, - severity, - message, - related - }; + related.push(...this._pendingTemplateError.requiredFrom); + this._pendingTemplateError = undefined; } + + // Store and return the current diagnostic + return this._prevDiag = { + full, + file, + location, + severity, + message, + related + }; } - return FeedLineResult.NotMine; } } } diff --git a/src/diagnostics/gnu-ld.ts b/src/diagnostics/gnu-ld.ts index b4c5d75bc..2cc0824d9 100644 --- a/src/diagnostics/gnu-ld.ts +++ b/src/diagnostics/gnu-ld.ts @@ -4,33 +4,104 @@ import * as vscode from 'vscode'; -import { FeedLineResult, oneLess, RawDiagnosticParser } from '@cmt/diagnostics/util'; +import { oneLess, RawDiagnostic, RawDiagnosticParser, RawRelated, FeedLineResult, MatchType, RegexPattern } from '@cmt/diagnostics/util'; -export const REGEX = /^(.*):(\d+)\s?:\s+(.*[^\]])$/; +// Patterns to identify and capture GNU linker diagnostic messages +const regexPatterns: RegexPattern[] = [ + { // path/to/ld[.exe]:[ ]path/to/file:line: severity: message + regexPattern: /^(?:.*ld(?:\.exe)?:)(?:\s*)?(.+):(\d+):\s+(?:fatal )?(\w+):\s+(.+)/, + matchTypes: [MatchType.Full, MatchType.File, MatchType.Line, MatchType.Severity, MatchType.Message] + }, + { // path/to/ld[.exe]:[ ]path/to/file:line: message + regexPattern: /^(?:.*ld(?:\.exe)?\:)(?:\s*)?(.+):(\d+):\s+(.+)/, + matchTypes: [MatchType.Full, MatchType.File, MatchType.Line, MatchType.Message] + }, + { // path/to/ld[.exe]: severity: message + regexPattern: /^(.*ld(?:\.exe)?):\s+(?:fatal )?(\w+):\s+(.+)/, + matchTypes: [MatchType.Full, MatchType.File, MatchType.Severity, MatchType.Message] + }, + { // path/to/ld[.exe]: message (without trailing colon) + regexPattern: /^(.*ld(?:\.exe)?):\s+(.+)(? { expect(path.posix.isAbsolute(diag.file)).to.be.true; }); - test('Parsing fatal error diagnostics in french', () => { - const lines = ['/home/romain/TL/test/base.c:2:21: erreur fatale : bonjour.h : Aucun fichier ou dossier de ce type']; - feedLines(build_consumer, [], lines); - expect(build_consumer.compilers.gcc.diagnostics).to.have.length(1); - const diag = build_consumer.compilers.gcc.diagnostics[0]; - - expect(diag.location.start.line).to.eq(1); - expect(diag.message).to.eq('bonjour.h : Aucun fichier ou dossier de ce type'); - expect(diag.location.start.character).to.eq(20); - expect(diag.file).to.eq('/home/romain/TL/test/base.c'); - expect(diag.severity).to.eq('erreur'); - expect(path.posix.normalize(diag.file)).to.eq(diag.file); - expect(path.posix.isAbsolute(diag.file)).to.be.true; - }); test('Parsing warning diagnostics', () => { const lines = ['/some/path/here:4:26: warning: unused parameter \'data\'']; feedLines(build_consumer, [], lines); @@ -246,53 +232,329 @@ suite('Diagnostics', () => { expect(diag.message).to.eq(`unused parameter ‘v’ [-Wunused-parameter]`); expect(diag.severity).to.eq('warning'); }); - test('Parsing warning diagnostics in french', () => { - const lines = ['/home/romain/TL/test/base.c:155:2: attention : déclaration implicite de la fonction ‘create’']; + test('Parsing non-diagnostic', async () => { + const lines = ['/usr/include/c++/10/bits/stl_vector.h:98:47: optimized: basic block part vectorized using 32 byte vectors']; feedLines(build_consumer, [], lines); expect(build_consumer.compilers.gcc.diagnostics).to.have.length(1); - const diag = build_consumer.compilers.gcc.diagnostics[0]; + const resolved = await build_consumer.resolveDiagnostics('dummyPath'); + expect(resolved.length).to.eq(0); + }); + test('Parsing linker error of type "/path/to/ld:path/to/file:line: severity: message"', () => { + const lines = ['/path/to/ld:path/to/file:42: severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gnuld.diagnostics[0]; + + expect(diag.location.start.line).to.eq(41); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('path/to/file'); + expect(diag.severity).to.eq('severity'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.false; + }); + test('Parsing linker error of type "/path/to/ld.exe:path/to/file:line: severity: message"', () => { + const lines = ['/path/to/ld.exe:path/to/file:42: severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gnuld.diagnostics[0]; + + expect(diag.location.start.line).to.eq(41); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('path/to/file'); + expect(diag.severity).to.eq('severity'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.false; + }); + test('Parsing linker error of type "/path/to/ld: path/to/file:line: severity: message"', () => { + const lines = ['/path/to/ld: path/to/file:42: severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gnuld.diagnostics[0]; + + expect(diag.location.start.line).to.eq(41); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('path/to/file'); + expect(diag.severity).to.eq('severity'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.false; + }); + test('Parsing linker error of type "/path/to/ld.exe: path/to/file:line: severity: message"', () => { + const lines = ['/path/to/ld.exe: path/to/file:42: severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gnuld.diagnostics[0]; + + expect(diag.location.start.line).to.eq(41); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('path/to/file'); + expect(diag.severity).to.eq('severity'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.false; + }); + test('Parsing linker error of type "/path/to/ld:path/to/file:line: message"', () => { + const lines = ['/path/to/ld:path/to/file:42: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gnuld.diagnostics[0]; + + expect(diag.location.start.line).to.eq(41); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('path/to/file'); + expect(diag.severity).to.eq('error'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.false; + }); + test('Parsing linker error of type "/path/to/ld.exe:path/to/file:line: message"', () => { + const lines = ['/path/to/ld.exe:path/to/file:42: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gnuld.diagnostics[0]; + + expect(diag.location.start.line).to.eq(41); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('path/to/file'); + expect(diag.severity).to.eq('error'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.false; + }); + test('Parsing linker error of type "/path/to/ld: path/to/file:line: message"', () => { + const lines = ['/path/to/ld: path/to/file:42: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gnuld.diagnostics[0]; - expect(diag.location.start.line).to.eq(154); - expect(diag.message).to.eq('déclaration implicite de la fonction ‘create’'); - expect(diag.location.start.character).to.eq(1); - expect(diag.file).to.eq('/home/romain/TL/test/base.c'); - expect(diag.severity).to.eq('attention'); + expect(diag.location.start.line).to.eq(41); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('path/to/file'); + expect(diag.severity).to.eq('error'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.false; + }); + test('Parsing linker error of type "/path/to/ld.exe: path/to/file:line: message"', () => { + const lines = ['/path/to/ld.exe: path/to/file:42: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gnuld.diagnostics[0]; + + expect(diag.location.start.line).to.eq(41); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('path/to/file'); + expect(diag.severity).to.eq('error'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.false; + }); + test('Parsing linker error of type "/path/to/ld: severity: message"', () => { + const lines = ['/path/to/ld: error: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gnuld.diagnostics[0]; + + expect(diag.location.start.line).to.eq(0); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('/path/to/ld'); + expect(diag.severity).to.eq('error'); expect(path.posix.normalize(diag.file)).to.eq(diag.file); expect(path.posix.isAbsolute(diag.file)).to.be.true; }); - test('Parsing non-diagnostic', async () => { - const lines = ['/usr/include/c++/10/bits/stl_vector.h:98:47: optimized: basic block part vectorized using 32 byte vectors']; + test('Parsing linker error of type "/path/to/ld.exe: severity: message"', () => { + const lines = ['/path/to/ld.exe: warning: some message']; feedLines(build_consumer, [], lines); - expect(build_consumer.compilers.gcc.diagnostics).to.have.length(1); - const resolved = await build_consumer.resolveDiagnostics('dummyPath'); - expect(resolved.length).to.eq(0); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gnuld.diagnostics[0]; + + expect(diag.location.start.line).to.eq(0); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('some message'); + expect(diag.file).to.eq('/path/to/ld.exe'); + expect(diag.severity).to.eq('warning'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.true; }); - test('Parsing linker error', () => { - const lines = ['/some/path/here:101: undefined reference to `some_function\'']; + test('Parsing linker error of type "/path/to/ld: message (without trailing colon)"', () => { + const lines = ['/path/to/ld: message']; feedLines(build_consumer, [], lines); - expect(build_consumer.compilers.gnuLD.diagnostics).to.have.length(1); - const diag = build_consumer.compilers.gnuLD.diagnostics[0]; + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gnuld.diagnostics[0]; - expect(diag.location.start.line).to.eq(100); - expect(diag.message).to.eq('undefined reference to `some_function\''); - expect(diag.file).to.eq('/some/path/here'); + expect(diag.location.start.line).to.eq(0); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('/path/to/ld'); + expect(diag.severity).to.eq('error'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.true; + }); + test('Parsing linker error of type "/path/to/ld.exe: message (without trailing colon)"', () => { + const lines = ['/path/to/ld.exe: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gnuld.diagnostics[0]; + + expect(diag.location.start.line).to.eq(0); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('/path/to/ld.exe'); expect(diag.severity).to.eq('error'); expect(path.posix.normalize(diag.file)).to.eq(diag.file); expect(path.posix.isAbsolute(diag.file)).to.be.true; }); - test('Parsing linker error in french', () => { - const lines = ['/home/romain/TL/test/test_fa_tp4.c:9 : référence indéfinie vers « create_automaton_product56 »']; + test('Parsing linker error of type "/path/to/file:line: message (without "[fatal] severity:" or trailing colon)"', () => { + const lines = ['/path/to/file:42: message']; feedLines(build_consumer, [], lines); - expect(build_consumer.compilers.gnuLD.diagnostics).to.have.length(1); - const diag = build_consumer.compilers.gnuLD.diagnostics[0]; + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gnuld.diagnostics[0]; - expect(diag.location.start.line).to.eq(8); - expect(diag.message).to.eq('référence indéfinie vers « create_automaton_product56 »'); - expect(diag.file).to.eq('/home/romain/TL/test/test_fa_tp4.c'); + expect(diag.location.start.line).to.eq(41); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('/path/to/file'); expect(diag.severity).to.eq('error'); expect(path.posix.normalize(diag.file)).to.eq(diag.file); expect(path.posix.isAbsolute(diag.file)).to.be.true; }); + test('Parsing gcc error of type "/path/to/file:line:column: severity: message"', () => { + const lines = ['/path/to/file:42:24: severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gcc.diagnostics[0]; + + expect(diag.location.start.line).to.eq(41); + expect(diag.location.start.character).to.eq(23); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('/path/to/file'); + expect(diag.severity).to.eq('severity'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.true; + }); + test('Parsing gcc error of type "/path/to/file:line: severity: message"', () => { + const lines = ['/path/to/file:42: severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gcc.diagnostics[0]; + + expect(diag.location.start.line).to.eq(41); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('/path/to/file'); + expect(diag.severity).to.eq('severity'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.true; + }); + test('Parsing gcc error of type "/path/to/cc1: severity: message"', () => { + const lines = ['/path/to/cc1: severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gcc.diagnostics[0]; + + expect(diag.location.start.line).to.eq(0); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('/path/to/cc1'); + expect(diag.severity).to.eq('severity'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.true; + }); + test('Parsing gcc error of type "/path/to/cc1.exe: severity: message"', () => { + const lines = ['/path/to/cc1.exe: severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gcc.diagnostics[0]; + + expect(diag.location.start.line).to.eq(0); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('/path/to/cc1.exe'); + expect(diag.severity).to.eq('severity'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.true; + }); + test('Parsing gcc error of type "/path/to/arm-none-eabi-gcc: severity: message"', () => { + const lines = ['/path/to/arm-none-eabi-gcc: severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gcc.diagnostics[0]; + + expect(diag.location.start.line).to.eq(0); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('/path/to/arm-none-eabi-gcc'); + expect(diag.severity).to.eq('severity'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.true; + }); + test('Parsing gcc error of type "/path/to/arm-none-eabi-gcc.exe: severity: message"', () => { + const lines = ['/path/to/arm-none-eabi-gcc.exe: severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(1); + const diag = build_consumer.compilers.gcc.diagnostics[0]; + + expect(diag.location.start.line).to.eq(0); + expect(diag.location.start.character).to.eq(0); + expect(diag.message).to.eq('message'); + expect(diag.file).to.eq('/path/to/arm-none-eabi-gcc.exe'); + expect(diag.severity).to.eq('severity'); + expect(path.posix.normalize(diag.file)).to.eq(diag.file); + expect(path.posix.isAbsolute(diag.file)).to.be.true; + }); + test('Parse GCC error on line zero', () => { + const lines = ['/foo.h:66:0: warning: ignoring #pragma comment [-Wunknown-pragmas]']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(1); + expect(build_consumer.compilers.gcc.diagnostics[0].file).to.eq('/foo.h'); + expect(build_consumer.compilers.gcc.diagnostics[0].location.start.line).to.eq(65); + expect(build_consumer.compilers.gcc.diagnostics[0].location.start.character).to.eq(0); + }); + test('No gcc and linker error on "/path/to/ld: message:" (trailing colon)', () => { + const lines = ['/path/to/ld: message:']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(0); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(0); + }); + test('No gcc and linker error on "/path/to/ld.exe: message:" (trailing colon)', () => { + const lines = ['/path/to/ld.exe: message:']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(0); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(0); + }); + test('No gcc and linker error on "/path/to/file:line:column severity: message" (missing colon after column)', () => { + const lines = ['path/to/file:42:24 severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(0); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(0); + }); + test('No gcc and linker error on "/path/to/file:line severity: message" (missing colon after line)', () => { + const lines = ['path/to/file:42 severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(0); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(0); + }); + test('No linker error on "/path/to/file:line: severity: message" ("severity:" is gcc diagnostic)', () => { + const lines = ['/path/to/file:42: severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(0); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(1); + }); + test('No linker error on "/path/to/file:line: fatal severity: message" ("fatal severity:" is gcc diagnostic)', () => { + const lines = ['/path/to/file:42: fatal severity: message']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(0); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(1); + }); + test('No gcc and linker error on "/path/to/file:line: message:" (trailing colon)', () => { + const lines = ['/path/to/file:42: message:']; + feedLines(build_consumer, [], lines); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(0); + expect(build_consumer.compilers.gnuld.diagnostics).to.have.length(0); + }); test('Parsing GHS Diagnostics', () => { const lines = [ '"C:\\path\\source\\debug\\debug.c", line 631 (col. 3): warning #68-D: integer conversion resulted in a change of sign' @@ -400,16 +662,7 @@ suite('Diagnostics', () => { `make: *** [Makefile:84 all] Error 2` ]; feedLines(build_consumer, [], lines); - expect(build_consumer.compilers.gnuLD.diagnostics).to.have.length(0); - }); - - test('Parse GCC error on line zero', () => { - const lines = ['/foo.h:66:0: warning: ignoring #pragma comment [-Wunknown-pragmas]']; - feedLines(build_consumer, [], lines); - expect(build_consumer.compilers.gcc.diagnostics).to.have.length(1); - expect(build_consumer.compilers.gcc.diagnostics[0].file).to.eq('/foo.h'); - expect(build_consumer.compilers.gcc.diagnostics[0].location.start.line).to.eq(65); - expect(build_consumer.compilers.gcc.diagnostics[0].location.start.character).to.eq(0); + expect(build_consumer.compilers.gcc.diagnostics).to.have.length(0); }); test('Parse MSVC single proc error', () => {