From 2ba8ac8c2b4c0c998895bc284def630a8526bbcb Mon Sep 17 00:00:00 2001 From: johnny-keker Date: Mon, 12 Sep 2022 13:31:24 +0200 Subject: [PATCH 1/8] fixed parsing script errors with multiple locations --- VSRAD.Package/BuildTools/Errors/Parser.cs | 53 +++++++++++++------ .../BuildTools/Errors/ParserTests.cs | 6 ++- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/VSRAD.Package/BuildTools/Errors/Parser.cs b/VSRAD.Package/BuildTools/Errors/Parser.cs index ab2290307..9876f314c 100644 --- a/VSRAD.Package/BuildTools/Errors/Parser.cs +++ b/VSRAD.Package/BuildTools/Errors/Parser.cs @@ -20,11 +20,20 @@ public static ICollection ParseStderr(IEnumerable outputs) string line; while ((line = reader.ReadLine()) != null) { - var message = ParseScriptMessage(line) ?? ParseKeywordMessage(line) ?? ParseClangMessage(line); - if (message != null) + var message = ParseKeywordMessage(line) ?? ParseClangMessage(line); + var scriptMessages = ParseScriptMessage(line); + if (message != null || scriptMessages != null) { - lastMessage = message; - messages.Add(message); + if (message != null) + { + lastMessage = message; + messages.Add(message); + } + else + { + lastMessage = scriptMessages[scriptMessages.Count - 1]; + messages.AddRange(scriptMessages); + } } else if (lastMessage != null) { @@ -54,12 +63,15 @@ private static Message ParseClangMessage(string header) } private static readonly Regex ScriptErrorRegex = new Regex( - @"\*(?[EW]),(?[^:(]+)(?>\s\((?.+):(?\d+)\))?:\s(?.+)", RegexOptions.Compiled); + @"\*(?[EW]),(?[^:(]+)(?>\s\((?.+)\))?:\s(?.+)", RegexOptions.Compiled); - private static readonly Regex ScriptErrorLocationInTextRegex = new Regex( - @"(?.+)\s\((?.+):(?\d+)\)", RegexOptions.Compiled); + private static readonly Regex ScriptErrorTextRegex = new Regex( + @"(?.+)\s\((?.+)\)", RegexOptions.Compiled); - private static Message ParseScriptMessage(string header) + private static readonly Regex ScriptErrorLocationsRegex = new Regex( + @"(?.+):(?\d+)", RegexOptions.Compiled); + + private static List ParseScriptMessage(string header) { var match = ScriptErrorRegex.Match(header); if (!match.Success) return null; @@ -67,20 +79,31 @@ private static Message ParseScriptMessage(string header) var code = match.Groups["code"].Value; var textAndMaybeLocation = match.Groups["text"].Value; - var message = new Message { Kind = ParseMessageKind(match.Groups["kind"].Value) }; + var kind = ParseMessageKind(match.Groups["kind"].Value); if (!match.Groups["file"].Success) - match = ScriptErrorLocationInTextRegex.Match(textAndMaybeLocation); + match = ScriptErrorTextRegex.Match(textAndMaybeLocation); + + var messages = new List(); if (match.Success) { - message.SourceFile = match.Groups["file"].Value; - message.Line = int.Parse(match.Groups["line"].Value); + foreach (var source in match.Groups["file"].Value.Split(',')) + { + var message = new Message { Kind = kind }; + var locationMatch = ScriptErrorLocationsRegex.Match(source); + message.SourceFile = locationMatch.Groups["file"].Value.Trim(); + message.Line = int.Parse(locationMatch.Groups["line"].Value); + message.Text = code + ": " + match.Groups["text"].Value; + messages.Add(message); + } + } + else + { + messages.Add(new Message { Kind = kind, Text = code + ": " + textAndMaybeLocation }); } - message.Text = code + ": " + (match.Success ? match.Groups["text"].Value : textAndMaybeLocation); - - return message; + return messages; } private static readonly Regex KeywordErrorRegex = new Regex( diff --git a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs index 7113d69bd..359b57994 100644 --- a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs +++ b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs @@ -61,6 +61,7 @@ public void ClangErrorTest() parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM did you really mean to use the scope resolution op here? *E,fatal (C:\Absolute\Path\source.c:35): Uncaught error: Undefined variable: user +*W,undefined: undefined reference to 'printf' (C:\Absolute\Path\source.c:3, C:\Absolute\Path\source.c:5, C:\Absolute\Path\include.h:10) "; public static readonly Message[] ScriptExpectedMessages = new Message[] @@ -72,7 +73,10 @@ did you really mean to use the scope resolution op here? @"syntax error: at symbol 'printf' parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM did you really mean to use the scope resolution op here?" }, - new Message { Kind = MessageKind.Error, Line = 35, SourceFile = @"C:\Absolute\Path\source.c", Text = "fatal: Uncaught error: Undefined variable: user" } + new Message { Kind = MessageKind.Error, Line = 35, SourceFile = @"C:\Absolute\Path\source.c", Text = "fatal: Uncaught error: Undefined variable: user" }, + new Message { Kind = MessageKind.Warning, Line = 3, SourceFile = @"C:\Absolute\Path\source.c", Text = "undefined: undefined reference to 'printf'" }, + new Message { Kind = MessageKind.Warning, Line = 5, SourceFile = @"C:\Absolute\Path\source.c", Text = "undefined: undefined reference to 'printf'" }, + new Message { Kind = MessageKind.Warning, Line = 10, SourceFile = @"C:\Absolute\Path\include.h", Text = "undefined: undefined reference to 'printf'" } }; [Fact] From 67bc4bc5e24b6787ba248b64113e09dc5d01a83b Mon Sep 17 00:00:00 2001 From: johnny-keker Date: Tue, 13 Sep 2022 18:02:57 +0200 Subject: [PATCH 2/8] changed parser functions signatures --- VSRAD.Package/BuildTools/Errors/Parser.cs | 58 +++++++------------ .../BuildTools/Errors/ParserTests.cs | 2 +- 2 files changed, 22 insertions(+), 38 deletions(-) diff --git a/VSRAD.Package/BuildTools/Errors/Parser.cs b/VSRAD.Package/BuildTools/Errors/Parser.cs index 9876f314c..75f47c0ad 100644 --- a/VSRAD.Package/BuildTools/Errors/Parser.cs +++ b/VSRAD.Package/BuildTools/Errors/Parser.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; +using System.Linq; using static VSRAD.BuildTools.IPCBuildResult; namespace VSRAD.Package.BuildTools.Errors @@ -15,30 +16,16 @@ public static ICollection ParseStderr(IEnumerable outputs) { using (var reader = new StringReader(output)) { - Message lastMessage = null; - string line; while ((line = reader.ReadLine()) != null) { - var message = ParseKeywordMessage(line) ?? ParseClangMessage(line); - var scriptMessages = ParseScriptMessage(line); - if (message != null || scriptMessages != null) - { - if (message != null) - { - lastMessage = message; - messages.Add(message); - } - else - { - lastMessage = scriptMessages[scriptMessages.Count - 1]; - messages.AddRange(scriptMessages); - } - } - else if (lastMessage != null) - { - lastMessage.Text += Environment.NewLine + line; - } + var currentLineParsed = + ParseScriptMessage(line, messages) || + ParseKeywordMessage(line, messages) || + ParseClangMessage(line, messages); + if (!currentLineParsed && !string.IsNullOrWhiteSpace(line) + && messages.Count > 0) + messages.Last().Text += Environment.NewLine + line; } } } @@ -48,18 +35,19 @@ public static ICollection ParseStderr(IEnumerable outputs) private static readonly Regex ClangErrorRegex = new Regex( @"(?.+):(?\d+):(?\d+):\s*(?error|warning|note|fatal error):\s(?.+)", RegexOptions.Compiled); - private static Message ParseClangMessage(string header) + private static bool ParseClangMessage(string header, List messages) { var match = ClangErrorRegex.Match(header); - if (!match.Success) return null; - return new Message + if (!match.Success) return false; + messages.Add(new Message { Kind = ParseMessageKind(match.Groups["kind"].Value), Text = match.Groups["text"].Value, SourceFile = match.Groups["file"].Value, Line = int.Parse(match.Groups["line"].Value), Column = int.Parse(match.Groups["col"].Value) - }; + }); + return true; } private static readonly Regex ScriptErrorRegex = new Regex( @@ -71,10 +59,10 @@ private static Message ParseClangMessage(string header) private static readonly Regex ScriptErrorLocationsRegex = new Regex( @"(?.+):(?\d+)", RegexOptions.Compiled); - private static List ParseScriptMessage(string header) + private static bool ParseScriptMessage(string header, List messages) { var match = ScriptErrorRegex.Match(header); - if (!match.Success) return null; + if (!match.Success) return false; var code = match.Groups["code"].Value; var textAndMaybeLocation = match.Groups["text"].Value; @@ -84,8 +72,6 @@ private static List ParseScriptMessage(string header) if (!match.Groups["file"].Success) match = ScriptErrorTextRegex.Match(textAndMaybeLocation); - var messages = new List(); - if (match.Success) { foreach (var source in match.Groups["file"].Value.Split(',')) @@ -102,25 +88,23 @@ private static List ParseScriptMessage(string header) { messages.Add(new Message { Kind = kind, Text = code + ": " + textAndMaybeLocation }); } - - return messages; + return true; } private static readonly Regex KeywordErrorRegex = new Regex( @"(?ERROR|WARNING):\s*(?.+)", RegexOptions.Compiled); - private static Message ParseKeywordMessage(string header) + private static bool ParseKeywordMessage(string header, List messages) { var match = KeywordErrorRegex.Match(header); - if (!match.Success) return null; + if (!match.Success) return false; - var message = new Message + messages.Add(new Message { Kind = ParseMessageKind(match.Groups["kind"].Value), Text = match.Groups["text"].Value - }; - - return message; + }); + return true; } private static MessageKind ParseMessageKind(string kind) diff --git a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs index 359b57994..4bff3ddae 100644 --- a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs +++ b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs @@ -39,7 +39,7 @@ public class ParserTests printf(""h""); ^"}, new Message { Kind = MessageKind.Note, Line = 4, Column = 2, SourceFile = @"C:\Absolute\Path\host.c", Text = - "include the header or explicitly provide a declaration for 'printf'\r\n" }, + "include the header or explicitly provide a declaration for 'printf'" }, new Message { Kind = MessageKind.Error, Line = 16, Column = 10, SourceFile = "input.s", Text = @"'abcde.s' file not found #include ""abcde.s"" From b9e745e6c88bf7a552d9b4016db8a84ab27d8e4c Mon Sep 17 00:00:00 2001 From: johnny-keker Date: Tue, 13 Sep 2022 19:36:51 +0200 Subject: [PATCH 3/8] fixed parsing of script errors with arbitrary message in parentheses --- VSRAD.Package/BuildTools/Errors/Parser.cs | 30 ++++++++++++++----- .../BuildTools/Errors/ParserTests.cs | 5 ++-- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/VSRAD.Package/BuildTools/Errors/Parser.cs b/VSRAD.Package/BuildTools/Errors/Parser.cs index 75f47c0ad..233f59eba 100644 --- a/VSRAD.Package/BuildTools/Errors/Parser.cs +++ b/VSRAD.Package/BuildTools/Errors/Parser.cs @@ -57,7 +57,7 @@ private static bool ParseClangMessage(string header, List messages) @"(?.+)\s\((?.+)\)", RegexOptions.Compiled); private static readonly Regex ScriptErrorLocationsRegex = new Regex( - @"(?.+):(?\d+)", RegexOptions.Compiled); + @"(?[^,]+):(?\d+)", RegexOptions.Compiled); private static bool ParseScriptMessage(string header, List messages) { @@ -74,14 +74,28 @@ private static bool ParseScriptMessage(string header, List messages) if (match.Success) { - foreach (var source in match.Groups["file"].Value.Split(',')) + var locationMatch = ScriptErrorLocationsRegex.Matches(match.Groups["file"].Value); + if (locationMatch.Count == 0) { - var message = new Message { Kind = kind }; - var locationMatch = ScriptErrorLocationsRegex.Match(source); - message.SourceFile = locationMatch.Groups["file"].Value.Trim(); - message.Line = int.Parse(locationMatch.Groups["line"].Value); - message.Text = code + ": " + match.Groups["text"].Value; - messages.Add(message); + messages.Add(new Message { Kind = kind, Text = code + ": " + textAndMaybeLocation }); + return true; + } + foreach (Match lMatch in locationMatch) + { + if (!lMatch.Success) + { + messages.Add(new Message { Kind = kind, Text = code + ": " + textAndMaybeLocation }); + } + else + { + messages.Add(new Message + { + Kind = kind, + SourceFile = lMatch.Groups["file"].Value.Trim(), + Line = int.Parse(lMatch.Groups["line"].Value), + Text = code + ": " + match.Groups["text"].Value + }); + } } } else diff --git a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs index 4bff3ddae..51e71c7d7 100644 --- a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs +++ b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs @@ -62,7 +62,7 @@ public void ClangErrorTest() did you really mean to use the scope resolution op here? *E,fatal (C:\Absolute\Path\source.c:35): Uncaught error: Undefined variable: user *W,undefined: undefined reference to 'printf' (C:\Absolute\Path\source.c:3, C:\Absolute\Path\source.c:5, C:\Absolute\Path\include.h:10) -"; +*W,undefined: undefined reference to 'printf' (undefref)"; public static readonly Message[] ScriptExpectedMessages = new Message[] { @@ -76,7 +76,8 @@ did you really mean to use the scope resolution op here? new Message { Kind = MessageKind.Error, Line = 35, SourceFile = @"C:\Absolute\Path\source.c", Text = "fatal: Uncaught error: Undefined variable: user" }, new Message { Kind = MessageKind.Warning, Line = 3, SourceFile = @"C:\Absolute\Path\source.c", Text = "undefined: undefined reference to 'printf'" }, new Message { Kind = MessageKind.Warning, Line = 5, SourceFile = @"C:\Absolute\Path\source.c", Text = "undefined: undefined reference to 'printf'" }, - new Message { Kind = MessageKind.Warning, Line = 10, SourceFile = @"C:\Absolute\Path\include.h", Text = "undefined: undefined reference to 'printf'" } + new Message { Kind = MessageKind.Warning, Line = 10, SourceFile = @"C:\Absolute\Path\include.h", Text = "undefined: undefined reference to 'printf'" }, + new Message { Kind = MessageKind.Warning, Line = 0, SourceFile = "", Text = "undefined: undefined reference to 'printf' (undefref)" } }; [Fact] From 0e4a4325d17d8d1f4260d038dd954e6012875073 Mon Sep 17 00:00:00 2001 From: johnny-keker Date: Tue, 13 Sep 2022 19:43:32 +0200 Subject: [PATCH 4/8] fixed namings --- VSRAD.Package/BuildTools/Errors/Parser.cs | 26 +++++++++---------- .../BuildTools/Errors/ParserTests.cs | 24 ++++++++--------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/VSRAD.Package/BuildTools/Errors/Parser.cs b/VSRAD.Package/BuildTools/Errors/Parser.cs index 233f59eba..34646dee6 100644 --- a/VSRAD.Package/BuildTools/Errors/Parser.cs +++ b/VSRAD.Package/BuildTools/Errors/Parser.cs @@ -20,8 +20,8 @@ public static ICollection ParseStderr(IEnumerable outputs) while ((line = reader.ReadLine()) != null) { var currentLineParsed = + ParseAsmMessage(line, messages) || ParseScriptMessage(line, messages) || - ParseKeywordMessage(line, messages) || ParseClangMessage(line, messages); if (!currentLineParsed && !string.IsNullOrWhiteSpace(line) && messages.Count > 0) @@ -50,18 +50,18 @@ private static bool ParseClangMessage(string header, List messages) return true; } - private static readonly Regex ScriptErrorRegex = new Regex( + private static readonly Regex AsmErrorRegex = new Regex( @"\*(?[EW]),(?[^:(]+)(?>\s\((?.+)\))?:\s(?.+)", RegexOptions.Compiled); - private static readonly Regex ScriptErrorTextRegex = new Regex( + private static readonly Regex AsmErrorTextRegex = new Regex( @"(?.+)\s\((?.+)\)", RegexOptions.Compiled); - private static readonly Regex ScriptErrorLocationsRegex = new Regex( - @"(?[^,]+):(?\d+)", RegexOptions.Compiled); + private static readonly Regex AsmErrorLocationsRegex = new Regex( + @"(?[^,]+):(?\d+)", RegexOptions.Compiled); - private static bool ParseScriptMessage(string header, List messages) + private static bool ParseAsmMessage(string header, List messages) { - var match = ScriptErrorRegex.Match(header); + var match = AsmErrorRegex.Match(header); if (!match.Success) return false; var code = match.Groups["code"].Value; @@ -70,11 +70,11 @@ private static bool ParseScriptMessage(string header, List messages) var kind = ParseMessageKind(match.Groups["kind"].Value); if (!match.Groups["file"].Success) - match = ScriptErrorTextRegex.Match(textAndMaybeLocation); + match = AsmErrorTextRegex.Match(textAndMaybeLocation); if (match.Success) { - var locationMatch = ScriptErrorLocationsRegex.Matches(match.Groups["file"].Value); + var locationMatch = AsmErrorLocationsRegex.Matches(match.Groups["file"].Value); if (locationMatch.Count == 0) { messages.Add(new Message { Kind = kind, Text = code + ": " + textAndMaybeLocation }); @@ -91,7 +91,7 @@ private static bool ParseScriptMessage(string header, List messages) messages.Add(new Message { Kind = kind, - SourceFile = lMatch.Groups["file"].Value.Trim(), + SourceFile = lMatch.Groups["fileOrText"].Value.Trim(), Line = int.Parse(lMatch.Groups["line"].Value), Text = code + ": " + match.Groups["text"].Value }); @@ -105,12 +105,12 @@ private static bool ParseScriptMessage(string header, List messages) return true; } - private static readonly Regex KeywordErrorRegex = new Regex( + private static readonly Regex ScriptErrorRegex = new Regex( @"(?ERROR|WARNING):\s*(?.+)", RegexOptions.Compiled); - private static bool ParseKeywordMessage(string header, List messages) + private static bool ParseScriptMessage(string header, List messages) { - var match = KeywordErrorRegex.Match(header); + var match = ScriptErrorRegex.Match(header); if (!match.Success) return false; messages.Add(new Message diff --git a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs index 51e71c7d7..0aa539d86 100644 --- a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs +++ b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs @@ -53,7 +53,7 @@ public void ClangErrorTest() Assert.Equal(ClangExpectedMessages, messages); } - public const string ScriptStderr = @" + public const string AsmStderr = @" *E,fatal: undefined reference to 'printf' (:3) *E,fatal: undefined reference to 'printf' (C:\Absolute\Path\source.c:3) *W,undefined: 1 undefined references found @@ -64,7 +64,7 @@ did you really mean to use the scope resolution op here? *W,undefined: undefined reference to 'printf' (C:\Absolute\Path\source.c:3, C:\Absolute\Path\source.c:5, C:\Absolute\Path\include.h:10) *W,undefined: undefined reference to 'printf' (undefref)"; - public static readonly Message[] ScriptExpectedMessages = new Message[] + public static readonly Message[] AsmExpectedMessages = new Message[] { new Message { Kind = MessageKind.Error, Line = 3, SourceFile = "", Text = "fatal: undefined reference to 'printf'"}, new Message { Kind = MessageKind.Error, Line = 3, SourceFile = @"C:\Absolute\Path\source.c", Text = "fatal: undefined reference to 'printf'"}, @@ -81,20 +81,20 @@ did you really mean to use the scope resolution op here? }; [Fact] - public void ScriptErrorTest() + public void AsmErrorTest() { - var messages = ParseStderr(new string[] { ScriptStderr }).ToArray(); - Assert.Equal(ScriptExpectedMessages, messages); + var messages = ParseStderr(new string[] { AsmStderr }).ToArray(); + Assert.Equal(AsmExpectedMessages, messages); } - public const string KeywordStderr = @" + public const string ScriptStderr = @" *E,fatal: undefined reference to 'printf' (:3) ERROR: check if app exists and can be executed 'C:\NEVER\GONNA\GIVE\YOU\UP.exe' WARNING: you are incredibly beautiful! *E,fatal (auth.c:35): Uncaught error: Undefined variable: user "; - public static readonly Message[] KeywordErrorExpectedMessages = new Message[] + public static readonly Message[] ScriptErrorExpectedMessages = new Message[] { new Message { Kind = MessageKind.Error, Line = 3, SourceFile = "", Text = "fatal: undefined reference to 'printf'" }, new Message { Kind = MessageKind.Error, Line = 0, SourceFile = "", Text = @"check if app exists and can be executed 'C:\NEVER\GONNA\GIVE\YOU\UP.exe'" }, @@ -103,18 +103,18 @@ public void ScriptErrorTest() }; [Fact] - public void KeywordErrorTest() + public void ScriptErrorTest() { - var messages = ParseStderr(new string[] { KeywordStderr }).ToArray(); - Assert.Equal(KeywordErrorExpectedMessages, messages); + var messages = ParseStderr(new string[] { ScriptStderr }).ToArray(); + Assert.Equal(ScriptErrorExpectedMessages, messages); } [Fact] public void MixedErrorFormatsTest() { - var expectedMessages = ClangExpectedMessages.Concat(KeywordErrorExpectedMessages).Concat(ScriptExpectedMessages).ToArray(); + var expectedMessages = ClangExpectedMessages.Concat(ScriptErrorExpectedMessages).Concat(AsmExpectedMessages).ToArray(); - var separateOutputs = new[] { ClangStderr, KeywordStderr, ScriptStderr }; + var separateOutputs = new[] { ClangStderr, ScriptStderr, AsmStderr }; var separateOutputsMessages = ParseStderr(separateOutputs).ToArray(); Assert.Equal(expectedMessages, separateOutputsMessages); From 580c94b77a1094c40272eb5b000ee39521a6b091 Mon Sep 17 00:00:00 2001 From: johnny-keker Date: Tue, 13 Sep 2022 19:45:36 +0200 Subject: [PATCH 5/8] naming: Parse...Message->Parse...Messages --- VSRAD.Package/BuildTools/Errors/Parser.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/VSRAD.Package/BuildTools/Errors/Parser.cs b/VSRAD.Package/BuildTools/Errors/Parser.cs index 34646dee6..6acd0b8f9 100644 --- a/VSRAD.Package/BuildTools/Errors/Parser.cs +++ b/VSRAD.Package/BuildTools/Errors/Parser.cs @@ -20,9 +20,9 @@ public static ICollection ParseStderr(IEnumerable outputs) while ((line = reader.ReadLine()) != null) { var currentLineParsed = - ParseAsmMessage(line, messages) || - ParseScriptMessage(line, messages) || - ParseClangMessage(line, messages); + ParseAsmMessages(line, messages) || + ParseScriptMessages(line, messages) || + ParseClangMessages(line, messages); if (!currentLineParsed && !string.IsNullOrWhiteSpace(line) && messages.Count > 0) messages.Last().Text += Environment.NewLine + line; @@ -35,7 +35,7 @@ public static ICollection ParseStderr(IEnumerable outputs) private static readonly Regex ClangErrorRegex = new Regex( @"(?.+):(?\d+):(?\d+):\s*(?error|warning|note|fatal error):\s(?.+)", RegexOptions.Compiled); - private static bool ParseClangMessage(string header, List messages) + private static bool ParseClangMessages(string header, List messages) { var match = ClangErrorRegex.Match(header); if (!match.Success) return false; @@ -59,7 +59,7 @@ private static bool ParseClangMessage(string header, List messages) private static readonly Regex AsmErrorLocationsRegex = new Regex( @"(?[^,]+):(?\d+)", RegexOptions.Compiled); - private static bool ParseAsmMessage(string header, List messages) + private static bool ParseAsmMessages(string header, List messages) { var match = AsmErrorRegex.Match(header); if (!match.Success) return false; @@ -108,7 +108,7 @@ private static bool ParseAsmMessage(string header, List messages) private static readonly Regex ScriptErrorRegex = new Regex( @"(?ERROR|WARNING):\s*(?.+)", RegexOptions.Compiled); - private static bool ParseScriptMessage(string header, List messages) + private static bool ParseScriptMessages(string header, List messages) { var match = ScriptErrorRegex.Match(header); if (!match.Success) return false; From 5f579bdf88856a31c83a51c4f3da90e066174475 Mon Sep 17 00:00:00 2001 From: johnny-keker Date: Tue, 13 Sep 2022 19:55:24 +0200 Subject: [PATCH 6/8] preserving empty lines in the error text, updated tests accordingly --- VSRAD.Package/BuildTools/Errors/Parser.cs | 3 +-- .../BuildTools/Errors/ParserTests.cs | 15 ++++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/VSRAD.Package/BuildTools/Errors/Parser.cs b/VSRAD.Package/BuildTools/Errors/Parser.cs index 6acd0b8f9..60ea315c9 100644 --- a/VSRAD.Package/BuildTools/Errors/Parser.cs +++ b/VSRAD.Package/BuildTools/Errors/Parser.cs @@ -23,8 +23,7 @@ public static ICollection ParseStderr(IEnumerable outputs) ParseAsmMessages(line, messages) || ParseScriptMessages(line, messages) || ParseClangMessages(line, messages); - if (!currentLineParsed && !string.IsNullOrWhiteSpace(line) - && messages.Count > 0) + if (!currentLineParsed && messages.Count > 0) messages.Last().Text += Environment.NewLine + line; } } diff --git a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs index 0aa539d86..f44f3c4cc 100644 --- a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs +++ b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs @@ -18,11 +18,9 @@ public class ParserTests printf(""h""); ^ C:\Absolute\Path\host.c:4:2: note: include the header or explicitly provide a declaration for 'printf' - input.s:16:10: fatal error: 'abcde.s' file not found #include ""abcde.s"" - ^~~~~~~~~ -"; + ^~~~~~~~~"; public static readonly Message[] ClangExpectedMessages = new Message[] { @@ -53,8 +51,8 @@ public void ClangErrorTest() Assert.Equal(ClangExpectedMessages, messages); } - public const string AsmStderr = @" -*E,fatal: undefined reference to 'printf' (:3) + public const string AsmStderr = +@"*E,fatal: undefined reference to 'printf' (:3) *E,fatal: undefined reference to 'printf' (C:\Absolute\Path\source.c:3) *W,undefined: 1 undefined references found *E,syntax error (:12): at symbol 'printf' @@ -87,12 +85,11 @@ public void AsmErrorTest() Assert.Equal(AsmExpectedMessages, messages); } - public const string ScriptStderr = @" -*E,fatal: undefined reference to 'printf' (:3) + public const string ScriptStderr = +@"*E,fatal: undefined reference to 'printf' (:3) ERROR: check if app exists and can be executed 'C:\NEVER\GONNA\GIVE\YOU\UP.exe' WARNING: you are incredibly beautiful! -*E,fatal (auth.c:35): Uncaught error: Undefined variable: user -"; +*E,fatal (auth.c:35): Uncaught error: Undefined variable: user"; public static readonly Message[] ScriptErrorExpectedMessages = new Message[] { From 9fd8cb261da14a3095dad0908931131f32f29002 Mon Sep 17 00:00:00 2001 From: johnny-keker Date: Thu, 15 Sep 2022 15:37:47 +0200 Subject: [PATCH 7/8] returned old Message|null signature to parser functions, got rid of multiple locations error as well as errors with location after message in general --- VSRAD.Package/BuildTools/Errors/Parser.cs | 83 +++++++------------ .../BuildTools/Errors/ParserTests.cs | 14 +--- 2 files changed, 34 insertions(+), 63 deletions(-) diff --git a/VSRAD.Package/BuildTools/Errors/Parser.cs b/VSRAD.Package/BuildTools/Errors/Parser.cs index 60ea315c9..87c2977a8 100644 --- a/VSRAD.Package/BuildTools/Errors/Parser.cs +++ b/VSRAD.Package/BuildTools/Errors/Parser.cs @@ -19,11 +19,13 @@ public static ICollection ParseStderr(IEnumerable outputs) string line; while ((line = reader.ReadLine()) != null) { - var currentLineParsed = - ParseAsmMessages(line, messages) || - ParseScriptMessages(line, messages) || - ParseClangMessages(line, messages); - if (!currentLineParsed && messages.Count > 0) + var message = + ParseAsmMessage(line) ?? + ParseScriptMessage(line) ?? + ParseClangMessage(line); + if (message != null) + messages.Add(message); + else if (messages.Count > 0) messages.Last().Text += Environment.NewLine + line; } } @@ -34,90 +36,67 @@ public static ICollection ParseStderr(IEnumerable outputs) private static readonly Regex ClangErrorRegex = new Regex( @"(?.+):(?\d+):(?\d+):\s*(?error|warning|note|fatal error):\s(?.+)", RegexOptions.Compiled); - private static bool ParseClangMessages(string header, List messages) + private static Message ParseClangMessage(string header) { var match = ClangErrorRegex.Match(header); - if (!match.Success) return false; - messages.Add(new Message + if (!match.Success) return null; + return new Message { Kind = ParseMessageKind(match.Groups["kind"].Value), Text = match.Groups["text"].Value, SourceFile = match.Groups["file"].Value, Line = int.Parse(match.Groups["line"].Value), Column = int.Parse(match.Groups["col"].Value) - }); - return true; + }; } private static readonly Regex AsmErrorRegex = new Regex( - @"\*(?[EW]),(?[^:(]+)(?>\s\((?.+)\))?:\s(?.+)", RegexOptions.Compiled); + @"\*(?[EW]),(?[^:(]+)(?>\s\((?.+):(?\d+)\))?:\s(?.+)", RegexOptions.Compiled); - private static readonly Regex AsmErrorTextRegex = new Regex( - @"(?.+)\s\((?.+)\)", RegexOptions.Compiled); - - private static readonly Regex AsmErrorLocationsRegex = new Regex( - @"(?[^,]+):(?\d+)", RegexOptions.Compiled); - - private static bool ParseAsmMessages(string header, List messages) + private static Message ParseAsmMessage(string header) { var match = AsmErrorRegex.Match(header); - if (!match.Success) return false; + if (!match.Success) return null; var code = match.Groups["code"].Value; var textAndMaybeLocation = match.Groups["text"].Value; var kind = ParseMessageKind(match.Groups["kind"].Value); - if (!match.Groups["file"].Success) - match = AsmErrorTextRegex.Match(textAndMaybeLocation); - if (match.Success) { - var locationMatch = AsmErrorLocationsRegex.Matches(match.Groups["file"].Value); - if (locationMatch.Count == 0) - { - messages.Add(new Message { Kind = kind, Text = code + ": " + textAndMaybeLocation }); - return true; - } - foreach (Match lMatch in locationMatch) - { - if (!lMatch.Success) - { - messages.Add(new Message { Kind = kind, Text = code + ": " + textAndMaybeLocation }); - } - else - { - messages.Add(new Message - { - Kind = kind, - SourceFile = lMatch.Groups["fileOrText"].Value.Trim(), - Line = int.Parse(lMatch.Groups["line"].Value), - Text = code + ": " + match.Groups["text"].Value - }); - } - } + var source = match.Groups["file"].Success + ? match.Groups["file"].Value.Trim() + : ""; + var line = match.Groups["line"].Success + ? int.Parse(match.Groups["line"].Value) + : 0; + return new Message { + Kind = kind, + SourceFile = source, + Line = line, + Text = code + ": " + match.Groups["text"].Value + }; } else { - messages.Add(new Message { Kind = kind, Text = code + ": " + textAndMaybeLocation }); + return new Message { Kind = kind, Text = code + ": " + textAndMaybeLocation }; } - return true; } private static readonly Regex ScriptErrorRegex = new Regex( @"(?ERROR|WARNING):\s*(?.+)", RegexOptions.Compiled); - private static bool ParseScriptMessages(string header, List messages) + private static Message ParseScriptMessage(string header) { var match = ScriptErrorRegex.Match(header); - if (!match.Success) return false; + if (!match.Success) return null; - messages.Add(new Message + return new Message { Kind = ParseMessageKind(match.Groups["kind"].Value), Text = match.Groups["text"].Value - }); - return true; + }; } private static MessageKind ParseMessageKind(string kind) diff --git a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs index f44f3c4cc..98915196f 100644 --- a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs +++ b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs @@ -52,30 +52,22 @@ public void ClangErrorTest() } public const string AsmStderr = -@"*E,fatal: undefined reference to 'printf' (:3) -*E,fatal: undefined reference to 'printf' (C:\Absolute\Path\source.c:3) -*W,undefined: 1 undefined references found +@"*W,undefined: 1 undefined references found *E,syntax error (:12): at symbol 'printf' parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM did you really mean to use the scope resolution op here? *E,fatal (C:\Absolute\Path\source.c:35): Uncaught error: Undefined variable: user -*W,undefined: undefined reference to 'printf' (C:\Absolute\Path\source.c:3, C:\Absolute\Path\source.c:5, C:\Absolute\Path\include.h:10) -*W,undefined: undefined reference to 'printf' (undefref)"; +*W,undefined: undefined reference to 'printf'"; public static readonly Message[] AsmExpectedMessages = new Message[] { - new Message { Kind = MessageKind.Error, Line = 3, SourceFile = "", Text = "fatal: undefined reference to 'printf'"}, - new Message { Kind = MessageKind.Error, Line = 3, SourceFile = @"C:\Absolute\Path\source.c", Text = "fatal: undefined reference to 'printf'"}, new Message { Kind = MessageKind.Warning, Line = 0, SourceFile = "", Text = "undefined: 1 undefined references found" }, new Message { Kind = MessageKind.Error, Line = 12, SourceFile = "", Text = @"syntax error: at symbol 'printf' parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM did you really mean to use the scope resolution op here?" }, new Message { Kind = MessageKind.Error, Line = 35, SourceFile = @"C:\Absolute\Path\source.c", Text = "fatal: Uncaught error: Undefined variable: user" }, - new Message { Kind = MessageKind.Warning, Line = 3, SourceFile = @"C:\Absolute\Path\source.c", Text = "undefined: undefined reference to 'printf'" }, - new Message { Kind = MessageKind.Warning, Line = 5, SourceFile = @"C:\Absolute\Path\source.c", Text = "undefined: undefined reference to 'printf'" }, - new Message { Kind = MessageKind.Warning, Line = 10, SourceFile = @"C:\Absolute\Path\include.h", Text = "undefined: undefined reference to 'printf'" }, - new Message { Kind = MessageKind.Warning, Line = 0, SourceFile = "", Text = "undefined: undefined reference to 'printf' (undefref)" } + new Message { Kind = MessageKind.Warning, Line = 0, SourceFile = "", Text = "undefined: undefined reference to 'printf'" } }; [Fact] From ed8a20929cdd8a62a0c09d65b0acb4eb0fead6b4 Mon Sep 17 00:00:00 2001 From: johnny-keker Date: Thu, 15 Sep 2022 15:40:30 +0200 Subject: [PATCH 8/8] removed last () error from tests --- VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs index 98915196f..16415fa58 100644 --- a/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs +++ b/VSRAD.PackageTests/BuildTools/Errors/ParserTests.cs @@ -78,7 +78,7 @@ public void AsmErrorTest() } public const string ScriptStderr = -@"*E,fatal: undefined reference to 'printf' (:3) +@"*E,fatal (:3): undefined reference to 'printf' ERROR: check if app exists and can be executed 'C:\NEVER\GONNA\GIVE\YOU\UP.exe' WARNING: you are incredibly beautiful! *E,fatal (auth.c:35): Uncaught error: Undefined variable: user";