Example #1
0
        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);
        }