Fix GCC linker errors not showing up in Problems View (#3950)
* gcc.ts: Replace single regex pattern with array * CHANGELOG.md: Add GCC parsing fix * Change parser from gnuLD to gcc for linker error diagnostics unit test * Fix GNU LD diagnostics parser not being enabled due to inconsistency in config and in build.ts by_source strings * Improve GCC and GNU LD diagnostics parsers * Remove obsolete french linker error unit test * Add gcc and gnuld diagnostics unit tests * Clean up regexes, add unit tests * Make gcc and gnuld parsers execution order agnostic * Share the RegexPattern interface and the MatchType interface rather than doubly defining it * Remove C++ template compiler error detection from gnu-ld, move common data types to util.ts * fix extra line * update changelog * Remove obsolete return statement * Add comments --------- Co-authored-by: 0xemgy <0xemgy> Co-authored-by: Garrett Campbell <86264750+gcampbell-msft@users.noreply.github.com> Co-authored-by: Garrett Campbell <gcampbell@microsoft.com>
This commit is contained in:
Родитель
c3a5713a69
Коммит
220ac74783
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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({
|
||||
file,
|
||||
location: new vscode.Range(lineno, column, lineno, 999),
|
||||
message
|
||||
});
|
||||
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,
|
||||
// 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,
|
||||
severity,
|
||||
message,
|
||||
related
|
||||
};
|
||||
file,
|
||||
message: this._pendingTemplateError.rootInstantiation
|
||||
});
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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+(.+)(?<!:)$/,
|
||||
matchTypes: [MatchType.Full, MatchType.File, MatchType.Message]
|
||||
},
|
||||
{ // /path/to/file:line: message (without "[fatal] severity:" or trailing colon)
|
||||
regexPattern: /^(.+?):(\d+):\s+(?!fatal\s+\w+:)(?!\w+:)(.+)(?<!:)$/,
|
||||
matchTypes: [MatchType.Full, MatchType.File, MatchType.Line, MatchType.Message]
|
||||
}
|
||||
];
|
||||
|
||||
export class Parser extends RawDiagnosticParser {
|
||||
private _prevDiag?: RawDiagnostic;
|
||||
|
||||
doHandleLine(line: string) {
|
||||
// Try to parse for GNU ld
|
||||
if (line.startsWith('make')) {
|
||||
// This is a Make error. It may *look* like an LD error, so we abort early
|
||||
// Test if this is a diagnostic
|
||||
let mat = null;
|
||||
|
||||
let full = "";
|
||||
let file = "";
|
||||
let lineno = oneLess("1");
|
||||
let columnno = oneLess("1");
|
||||
let severity = 'error';
|
||||
let message = "foobar";
|
||||
|
||||
for (const [, regexPattern] of regexPatterns.entries()) {
|
||||
mat = line.match(regexPattern.regexPattern);
|
||||
|
||||
if (mat !== null) {
|
||||
// For each matchType in the pattern, assign values accordingly
|
||||
for (let i = 0; i < mat.length; i++) {
|
||||
switch (regexPattern.matchTypes[i]) {
|
||||
case MatchType.Full:
|
||||
full = mat[i];
|
||||
break;
|
||||
case MatchType.File:
|
||||
file = mat[i];
|
||||
break;
|
||||
case MatchType.Line:
|
||||
lineno = oneLess(mat[i]);
|
||||
break;
|
||||
case MatchType.Column:
|
||||
columnno = oneLess(mat[i]);
|
||||
break;
|
||||
case MatchType.Severity:
|
||||
severity = mat[i];
|
||||
break;
|
||||
case MatchType.Message:
|
||||
message = mat[i];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mat) {
|
||||
// Ignore this line because it is no matching diagnostic
|
||||
return FeedLineResult.NotMine;
|
||||
} else {
|
||||
// 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[] = [];
|
||||
|
||||
// Store and return the current diagnostic
|
||||
return this._prevDiag = {
|
||||
full,
|
||||
file,
|
||||
location: new vscode.Range(lineno, columnno, lineno, 999),
|
||||
severity,
|
||||
message,
|
||||
related
|
||||
};
|
||||
}
|
||||
}
|
||||
const res = REGEX.exec(line);
|
||||
if (!res) {
|
||||
return FeedLineResult.NotMine;
|
||||
}
|
||||
const [full, file, lineno_, message] = res;
|
||||
const lineno = oneLess(lineno_);
|
||||
if (file && lineno && message) {
|
||||
return {
|
||||
full,
|
||||
file,
|
||||
location: new vscode.Range(lineno, 0, lineno, 999),
|
||||
severity: 'error',
|
||||
message,
|
||||
related: []
|
||||
};
|
||||
}
|
||||
return FeedLineResult.NotMine;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,3 +117,23 @@ export abstract class RawDiagnosticParser {
|
|||
*/
|
||||
protected abstract doHandleLine(line: string): RawDiagnostic | FeedLineResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match types for gcc related regex diagnostics
|
||||
*/
|
||||
export enum MatchType {
|
||||
Full,
|
||||
File,
|
||||
Line,
|
||||
Column,
|
||||
Severity,
|
||||
Message
|
||||
}
|
||||
|
||||
/**
|
||||
* Regex pattern interface for generic gcc related regex diagnostics
|
||||
*/
|
||||
export interface RegexPattern {
|
||||
regexPattern: RegExp;
|
||||
matchTypes: MatchType[];
|
||||
}
|
||||
|
|
|
@ -206,20 +206,6 @@ suite('Diagnostics', () => {
|
|||
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,20 +232,6 @@ 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’'];
|
||||
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(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(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'];
|
||||
feedLines(build_consumer, [], lines);
|
||||
|
@ -267,32 +239,322 @@ suite('Diagnostics', () => {
|
|||
const resolved = await build_consumer.resolveDiagnostics('dummyPath');
|
||||
expect(resolved.length).to.eq(0);
|
||||
});
|
||||
test('Parsing linker error', () => {
|
||||
const lines = ['/some/path/here:101: undefined reference to `some_function\''];
|
||||
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(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(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(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 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/ld.exe: severity: message"', () => {
|
||||
const lines = ['/path/to/ld.exe: warning: some 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(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 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(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 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(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', () => {
|
||||
|
|
Загрузка…
Ссылка в новой задаче