diff --git a/CHANGELOG.md b/CHANGELOG.md index f8996415b..730eb585d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ Bug Fixes: - Fix our keybindings for debug and run without debugging to better match VS Code. [#3507](https://github.com/microsoft/vscode-cmake-tools/issues/3507) - Allow success recovery in the configure precondition handler. [#3554](https://github.com/microsoft/vscode-cmake-tools/issues/3554) - Prevent second configure after `QuickStart` if the `automaticReconfigure` setting is enabled. [#3910](https://github.com/microsoft/vscode-cmake-tools/issues/3910) +- 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) - Set usepresets context after manually creating a CMakePresets.json/CMakeUserPresets.json or using QuickStart to create it. [#3854](https://github.com/microsoft/vscode-cmake-tools/issues/3854) - Only do special handling of `~` for code model reply path on linux. [#3957](https://github.com/microsoft/vscode-cmake-tools/issues/3957) - Fix issues with expanding unnecessary environment variables and incorrectly saving preset environments to cache. Also fixes expansion error reporting issue with not checking for an invalid Configure preset in other types of presets. [#3961](https://github.com/microsoft/vscode-cmake-tools/issues/3961) & [#1841](https://github.com/microsoft/vscode-cmake-tools/issues/1841) diff --git a/src/diagnostics/build.ts b/src/diagnostics/build.ts index 63ffa0534..4e50692f3 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 83f02ce7d..49d8938ea 100644 --- a/src/diagnostics/gcc.ts +++ b/src/diagnostics/gcc.ts @@ -6,7 +6,34 @@ import * as vscode from 'vscode'; import { oneLess, RawDiagnostic, RawDiagnosticParser, RawRelated, FeedLineResult } from './util'; -export const REGEX = /^(.*):(\d+):(\d+):\s+(?:fatal )?(\w*)(?:\sfatale)?\s?:\s+(.*)/; +enum MatchType { + Full, + File, + Line, + Column, + Severity, + Message +} + +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 RegexPattern { + regexPattern: RegExp; + matchTypes: MatchType[]; +} interface PendingTemplateBacktrace { rootInstantiation: string; @@ -28,7 +55,6 @@ export class Parser extends RawDiagnosticParser { }; return FeedLineResult.Ok; } - if (this._pendingTemplateError) { mat = /(.*):(\d+):(\d+):( +required from.+)/.exec(line); if (mat) { @@ -56,44 +82,79 @@ export class Parser extends RawDiagnosticParser { } // Test if this is a diagnostic - mat = REGEX.exec(line); - if (!mat) { + 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 (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) { // Nothing to see on this line of output... 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 === '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) { + 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; } + + 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 6b3bb50d9..653d55840 100644 --- a/src/diagnostics/gnu-ld.ts +++ b/src/diagnostics/gnu-ld.ts @@ -4,33 +4,167 @@ import * as vscode from 'vscode'; -import { FeedLineResult, oneLess, RawDiagnosticParser } from './util'; +import { oneLess, RawDiagnostic, RawDiagnosticParser, RawRelated, FeedLineResult } from './util'; -export const REGEX = /^(.*):(\d+)\s?:\s+(.*[^\]])$/; +enum MatchType { + Full, + File, + Line, + Column, + Severity, + Message +} + +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', () => {