public override bool TryMatch(InputJob Job, InputJobStep JobStep, InputDiagnostic Diagnostic, List <Issue> Issues) { // Make sure we're running a step that this applies to if (JobStep.Name.IndexOf("Copyright", StringComparison.OrdinalIgnoreCase) == -1) { return(false); } // Find any files in compiler output format HashSet <string> SourceFileNames = new HashSet <string>(StringComparer.OrdinalIgnoreCase); foreach (Match FileMatch in Regex.Matches(Diagnostic.Message, @"^\s*(?:WARNING|ERROR):\s*([^ ]+\.[a-zA-Z]+):", RegexOptions.Multiline)) { if (FileMatch.Success) { string SourceFileName = FileMatch.Groups[1].Value.Replace('\\', '/'); SourceFileNames.Add(SourceFileName); } } // If we found any source files, create a diagnostic category for them if (SourceFileNames.Count > 0) { Issue Issue = new Issue(Job.Project, Category, Job.Url, new IssueDiagnostic(JobStep.Name, JobStep.Url, Diagnostic.Message, Diagnostic.Url)); Issue.FileNames.UnionWith(SourceFileNames); Issues.Add(Issue); return(true); } // Otherwise pass return(false); }
public override bool TryMatch(InputJob Job, InputJobStep JobStep, InputDiagnostic Diagnostic, List <Issue> Issues) { string DefaultProject = String.Format("{0} (Unmatched)", Job.Project); Issue Issue = new Issue(DefaultProject, Category, Job.Url, new IssueDiagnostic(JobStep.Name, JobStep.Url, Diagnostic.Message, Diagnostic.Url)); Issue.Identifiers.Add(Diagnostic.Message); Issues.Add(Issue); return(true); }
public void OnErrorMatch(ErrorMatch Error) { if (Error.Severity == ErrorSeverity.Error) { // Find the longest sequence of spaces common to every non-empty line int WhitespaceLen = int.MaxValue; foreach (string Line in Error.Lines) { int ThisWhitespaceLen = 0; while (ThisWhitespaceLen < Line.Length && Line[ThisWhitespaceLen] == ' ') { ThisWhitespaceLen++; } if (ThisWhitespaceLen < Line.Length) { WhitespaceLen = Math.Min(WhitespaceLen, ThisWhitespaceLen); } } // Remove the whitespace prefix List <string> Lines = Error.Lines; if (WhitespaceLen < int.MaxValue) { Lines = new List <string>(Lines); for (int Idx = 0; Idx < Lines.Count; Idx++) { string Line = Lines[Idx]; if (Line.Length > WhitespaceLen) { Line = Line.Substring(WhitespaceLen); } else { Line = String.Empty; } Lines[Idx] = Line; } } // Add the output diagnostic InputDiagnostic Diagnostic = new InputDiagnostic(); Diagnostic.Type = "Error"; Diagnostic.Message = String.Join("\n", Lines); if (LineUrl != null) { string Url = LineUrl; Url = Url.Replace("{LINE_START}", Error.MinLineNumber.ToString()); Url = Url.Replace("{LINE_END}", Error.MaxLineNumber.ToString()); Url = Url.Replace("{LINE_COUNT}", (Error.MaxLineNumber + 1 - Error.MinLineNumber).ToString()); Diagnostic.Url = Url; } JobStep.Diagnostics.Add(Diagnostic); } }
public override bool TryMatch(InputJob Job, InputJobStep JobStep, InputDiagnostic Diagnostic, List <Issue> Issues) { // Find a list of source files with errors HashSet <string> ErrorFileNames = new HashSet <string>(StringComparer.OrdinalIgnoreCase); foreach (Match FileMatch in Regex.Matches(Diagnostic.Message, @"^\s*((?:[A-Za-z]:)?[^\s(:]+)[\(:]\d[\s\d:\)]+(?:warning|error|fatal error)", RegexOptions.Multiline)) { if (FileMatch.Success) { string FileName = GetNormalizedFileName(FileMatch.Groups[1].Value, JobStep.BaseDirectory); if (SourceFileExtensions.Any(x => FileName.EndsWith(x, StringComparison.OrdinalIgnoreCase))) { ErrorFileNames.Add(FileName); } } } // Find any referenced files in compiler output format HashSet <string> ReferencedFileNames = new HashSet <string>(StringComparer.OrdinalIgnoreCase); foreach (Match FileMatch in Regex.Matches(Diagnostic.Message, @"^\s*(?:In file included from\s*)?((?:[A-Za-z]:)?[^\s(:]+)[\(:]\d", RegexOptions.Multiline)) { if (FileMatch.Success) { string FileName = GetNormalizedFileName(FileMatch.Groups[1].Value, JobStep.BaseDirectory); if (SourceFileExtensions.Any(x => FileName.EndsWith(x, StringComparison.OrdinalIgnoreCase))) { ReferencedFileNames.Add(FileName); } } } // If we found any source files, create a diagnostic category for them if (ReferencedFileNames.Count > 0) { Issue Issue = new Issue(Job.Project, Category, Job.Url, new IssueDiagnostic(JobStep.Name, JobStep.Url, ShortenPaths(Diagnostic.Message), Diagnostic.Url)); Issue.FileNames.UnionWith(ReferencedFileNames); Issue.Identifiers.UnionWith(GetSourceFileNames(ErrorFileNames)); Issues.Add(Issue); return(true); } // Otherwise pass return(false); }
public override bool TryMatch(InputJob Job, InputJobStep JobStep, InputDiagnostic Diagnostic, List <Issue> Issues) { HashSet <string> FileNames = new HashSet <string>(); foreach (Match Match in Regex.Matches(Diagnostic.Message, @"^\s*[a-zA-Z0-9]+:\s+(?:Error:|Warning:)\s+(?:\[AssetLog\] )?((?:[a-zA-Z]:)?[^:]+(?:.uasset|.umap)):\s*(.*)")) { FileNames.Add(GetNormalizedFileName(Match.Groups[1].Value, JobStep.BaseDirectory)); } if (FileNames.Count > 0) { Issue Issue = new Issue(Job.Project, Category, Job.Url, new IssueDiagnostic(JobStep.Name, JobStep.Url, Diagnostic.Message, Diagnostic.Url)); Issue.FileNames.UnionWith(FileNames); Issues.Add(Issue); return(true); } return(false); }
public override bool TryMatch(InputJob Job, InputJobStep JobStep, InputDiagnostic Diagnostic, List <Issue> Issues) { List <string> SymbolMatches = new List <string>(); // Mac link error: // Undefined symbols for architecture arm64: // "Foo::Bar() const", referenced from: if (Regex.IsMatch(Diagnostic.Message, "^Undefined symbols")) { foreach (string Line in Diagnostic.Message.Split('\n')) { Match SymbolMatch = Regex.Match(Line, "^ \"(.+)\""); if (SymbolMatch.Success) { SymbolMatches.Add(SymbolMatch.Groups[1].Value); } } } // Android link error: // Foo.o:(.data.rel.ro + 0x5d88): undefined reference to `Foo::Bar()' Match UndefinedReference = Regex.Match(Diagnostic.Message, ": undefined reference to [`']([^`']+)"); if (UndefinedReference.Success) { SymbolMatches.Add(UndefinedReference.Groups[1].Value); } // LLD link error: // ld.lld.exe: error: undefined symbol: Foo::Bar() const Match LldMatch = Regex.Match(Diagnostic.Message, "error: undefined symbol:\\s*(.+)"); if (LldMatch.Success) { SymbolMatches.Add(LldMatch.Groups[1].Value); } // Link error: // Link: error: L0039: reference to undefined symbol `Foo::Bar() const' in file Match LinkMatch = Regex.Match(Diagnostic.Message, ": reference to undefined symbol [`']([^`']+)"); if (LinkMatch.Success) { SymbolMatches.Add(LinkMatch.Groups[1].Value); } // Microsoft linker error: // Foo.cpp.obj : error LNK2001: unresolved external symbol \"private: virtual void __cdecl UAssetManager::InitializeAssetBundlesFromMetadata_Recursive(class UStruct const *,void const *,struct FAssetBundleData &,class FName,class TSet<void const *,struct DefaultKeyFuncs<void const *,0>,class FDefaultSetAllocator> &)const \" (?InitializeAssetBundlesFromMetadata_Recursive@UAssetManager@@EEBAXPEBVUStruct@@PEBXAEAUFAssetBundleData@@VFName@@AEAV?$TSet@PEBXU?$DefaultKeyFuncs@PEBX$0A@@@VFDefaultSetAllocator@@@@@Z)", Match MicrosoftMatch = Regex.Match(Diagnostic.Message, ": unresolved external symbol \"([^\"]*)\""); if (MicrosoftMatch.Success) { SymbolMatches.Add(MicrosoftMatch.Groups[1].Value); } // Clean up all the symbol names SortedSet <string> SymbolNames = new SortedSet <string>(StringComparer.Ordinal); foreach (string SymbolMatch in SymbolMatches) { string SymbolName = SymbolMatch; // Remove any __declspec qualifiers SymbolName = Regex.Replace(SymbolName, "(?<![^a-zA-Z_])__declspec\\([^\\)]+\\)", ""); // Remove any argument lists for functions (anything after the first paren) SymbolName = Regex.Replace(SymbolName, "\\(.*$", ""); // Remove any decorators and type information (greedy match up to the last space) SymbolName = Regex.Replace(SymbolName, "^.* ", ""); // Add it to the list SymbolNames.Add(SymbolName); } // If we found any symbol names, create a fingerprint for them if (SymbolNames.Count > 0) { Issue Issue = new Issue(Job.Project, Category, Job.Url, new IssueDiagnostic(JobStep.Name, JobStep.Url, Diagnostic.Message, Diagnostic.Url)); Issue.Identifiers.UnionWith(SymbolNames); Issues.Add(Issue); return(true); } // Otherwise pass return(false); }