public static void Draw(MaintainerWindow parentWindow)
        {
            if (issues == null)
            {
                LoadLastIssues();
            }

            window = parentWindow;

            GUILayout.BeginHorizontal();
            DrawSettingsSection();
            DrawSearchSection();
            GUILayout.EndHorizontal();

            if (gotoIssue != null)
            {
                ShowIssue(gotoIssue);
                gotoIssue = null;
            }

            if (startSearch)
            {
                startSearch = false;
                window.RemoveNotification();
                IssuesFinder.StartSearch();
                window.Focus();
            }
        }
        private static void DrawIssueIcon(IssueRecord issue)
        {
            string iconName;

            if (issue.severity == IssueSeverity.Error)
            {
                iconName = "d_console.erroricon";
            }
            else if (issue.severity == IssueSeverity.Warning)
            {
                iconName = "d_console.warnicon";
            }
            else
            {
                iconName = "d_console.infoicon";
            }

            Texture icon     = EditorGUIUtility.FindTexture(iconName);
            Rect    iconArea = EditorGUILayout.GetControlRect(GUILayout.Width(20), GUILayout.Height(20));
            Rect    iconRect = new Rect(iconArea);

            iconRect.width = iconRect.height = 30;
            iconRect.x    -= 5;
            iconRect.y    -= 5;
            GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleAndCrop);
        }
        private static void ShowIssue(IssueRecord issueRecord)
        {
            List <GameObject> allObjects;

            if (issueRecord.source == IssueSource.Scene)
            {
                if (EditorApplication.currentScene != issueRecord.path)
                {
                    if (!EditorApplication.SaveCurrentSceneIfUserWantsTo())
                    {
                        return;
                    }
                    EditorApplication.OpenScene(issueRecord.path);
                }
                allObjects = EditorTools.GetAllSuitableGameObjectsInCurrentScene();
                EditorTools.PingObjectDelayed(AssetDatabase.LoadAssetAtPath(issueRecord.path, typeof(Object)));
            }
            else
            {
                allObjects = EditorTools.GetAllSuitablePrefabsInProject();
            }

            GameObject go = FindObjectInCollection(allObjects, issueRecord);

            Selection.activeGameObject = go;
        }
Example #4
0
        public override void WriteIssue(IssueRecord issue)
        {
            Result resultItem = new Result();

            MapRuleToResult(issue.Issue.Rule, ref resultItem);
            AddRuleToSarifRule(issue.Issue.Rule);

            CodeAnalysis.Sarif.Location loc = new CodeAnalysis.Sarif.Location();
            loc.AnalysisTarget = new PhysicalLocation(new Uri(issue.Filename),
                                                      null,
                                                      new Region(issue.Issue.StartLocation.Line,
                                                                 issue.Issue.StartLocation.Column,
                                                                 issue.Issue.EndLocation.Line,
                                                                 issue.Issue.EndLocation.Column,
                                                                 issue.Issue.Boundary.Index,
                                                                 issue.Issue.Boundary.Length
                                                                 ));
            resultItem.Snippet = issue.TextSample;

            if (issue.Issue.Rule.Fixes != null)
            {
                resultItem.Fixes = GetFixits(issue);
            }

            resultItem.Locations = new List <CodeAnalysis.Sarif.Location>();
            resultItem.Locations.Add(loc);
            _results.Add(resultItem);
        }
Example #5
0
        public override void WriteIssue(IssueRecord issue)
        {
            Dictionary <string, object> item = new Dictionary <string, object>();

            if (_formatString.Contains("%F"))
            {
                item.Add("filename", issue.Filename);
            }
            if (_formatString.Contains("%L"))
            {
                item.Add("start_line", issue.Issue.StartLocation.Line);
            }
            if (_formatString.Contains("%C"))
            {
                item.Add("start_column", issue.Issue.StartLocation.Column);
            }
            if (_formatString.Contains("%l"))
            {
                item.Add("end_line", issue.Issue.EndLocation.Line);
            }
            if (_formatString.Contains("%c"))
            {
                item.Add("end_column", issue.Issue.EndLocation.Column);
            }
            if (_formatString.Contains("%I"))
            {
                item.Add("match_index", issue.Issue.Boundary.Index);
            }
            if (_formatString.Contains("%i"))
            {
                item.Add("match_length", issue.Issue.Boundary.Length);
            }
            if (_formatString.Contains("%R"))
            {
                item.Add("rule_id", issue.Issue.Rule.Id);
            }
            if (_formatString.Contains("%N"))
            {
                item.Add("rule_name", issue.Issue.Rule.Name);
            }
            if (_formatString.Contains("%S"))
            {
                item.Add("severity", issue.Issue.Rule.Severity);
            }
            if (_formatString.Contains("%D"))
            {
                item.Add("description", issue.Issue.Rule.Description);
            }
            if (_formatString.Contains("%m"))
            {
                item.Add("match", issue.TextSample);
            }
            if (_formatString.Contains("%T"))
            {
                item.Add("tags", issue.Issue.Rule.Tags);
            }

            // Store the result in the result list
            jsonResult.Add(item);
        }
Example #6
0
 protected override void LoadLastRecords()
 {
     // ReSharper disable CoVariantArrayConversion
     records = SearchResultsStorage.IssuesSearchResults;
     if (records == null)
     {
         records = new IssueRecord[0];
     }
     // ReSharper restore CoVariantArrayConversion
 }
Example #7
0
        public override void WriteIssue(IssueRecord issue)
        {
            string output = _formatString.Replace("%F", issue.Filename);

            output = output.Replace("%L", issue.Issue.StartLocation.Line.ToString());
            output = output.Replace("%C", issue.Issue.StartLocation.Column.ToString());
            output = output.Replace("%l", issue.Issue.EndLocation.Line.ToString());
            output = output.Replace("%c", issue.Issue.EndLocation.Column.ToString());
            output = output.Replace("%I", issue.Issue.Boundary.Index.ToString());
            output = output.Replace("%i", issue.Issue.Boundary.Length.ToString());
            output = output.Replace("%R", issue.Issue.Rule.Id);
            output = output.Replace("%N", issue.Issue.Rule.Name);
            output = output.Replace("%S", issue.Issue.Rule.Severity.ToString());
            output = output.Replace("%D", issue.Issue.Rule.Description);
            output = output.Replace("%m", issue.TextSample);
            output = output.Replace("%T", string.Join(',', issue.Issue.Rule.Tags));

            TextWriter.WriteLine(output);
        }
Example #8
0
        private List <Fix> GetFixits(IssueRecord issue)
        {
            List <Fix> fixes = new List <Fix>();

            if (issue.Issue.Rule.Fixes != null)
            {
                foreach (CodeFix fix in issue.Issue.Rule.Fixes)
                {
                    List <Replacement> replacements = new List <Replacement>();
                    replacements.Add(new Replacement(new Region()
                    {
                        CharOffset = issue.Issue.Boundary.Index,
                        CharLength = issue.Issue.Boundary.Length,
                    }, new ArtifactContent()
                    {
                        Text = RuleProcessor.Fix(issue.TextSample, fix)
                    }, null));

                    var path    = Path.GetFullPath(issue.Filename);
                    var changes = new ArtifactChange[]
                    {
                        new ArtifactChange(
                            new ArtifactLocation()
                        {
                            Uri = new Uri(path)
                        },
                            replacements,
                            null)
                    };

                    fixes.Add(new Fix()
                    {
                        ArtifactChanges = changes,
                        Description     = new Message()
                        {
                            Text = issue.Issue.Rule.Description
                        }
                    });
                }
            }
            return(fixes);
        }
Example #9
0
        public override void WriteIssue(IssueRecord issue)
        {
            Result resultItem = new Result();

            MapRuleToResult(issue.Issue.Rule, ref resultItem);
            AddRuleToSarifRule(issue.Issue.Rule);

            CodeAnalysis.Sarif.Location loc = new CodeAnalysis.Sarif.Location();
            loc.PhysicalLocation = new PhysicalLocation()
            {
                Address = new Address()
                {
                    FullyQualifiedName = Path.GetFullPath(issue.Filename)
                },
                Region = new Region()
                {
                    StartLine   = issue.Issue.StartLocation.Line,
                    StartColumn = issue.Issue.StartLocation.Column,
                    EndLine     = issue.Issue.EndLocation.Line,
                    EndColumn   = issue.Issue.EndLocation.Column,
                    CharOffset  = issue.Issue.Boundary.Index,
                    CharLength  = issue.Issue.Boundary.Length,
                    Snippet     = new ArtifactContent()
                    {
                        Text     = issue.TextSample,
                        Rendered = new MultiformatMessageString(issue.TextSample, $"`{issue.TextSample}`", null),
                    },
                    SourceLanguage = issue.Language
                }
            };

            if (issue.Issue.Rule.Fixes != null)
            {
                resultItem.Fixes = GetFixits(issue);
            }

            resultItem.Locations = new List <CodeAnalysis.Sarif.Location>();
            resultItem.Locations.Add(loc);
            _results.Push(resultItem);
        }
Example #10
0
        private List <Fix> GetFixits(IssueRecord issue)
        {
            List <Fix> fixes = new List <Fix>();

            if (issue.Issue.Rule.Fixes != null)
            {
                foreach (CodeFix fix in issue.Issue.Rule.Fixes)
                {
                    List <Replacement> replacements = new List <Replacement>();
                    replacements.Add(new Replacement(issue.Issue.Boundary.Index,
                                                     issue.Issue.Boundary.Length,
                                                     RuleProcessor.Fix(issue.TextSample, fix)
                                                     ));

                    List <FileChange> changes = new List <FileChange>();
                    changes.Add(new FileChange(new Uri(issue.Filename), null, replacements));

                    fixes.Add(new Fix(fix.Name, changes));
                }
            }
            return(fixes);
        }
Example #11
0
        public int Run()
        {
            if (!Directory.Exists(_path) && !File.Exists(_path))
            {
                Console.Error.WriteLine("Error: Not a valid file or directory {0}", _path);

                return((int)ExitCode.CriticalError);
            }

            Verifier verifier = null;

            if (_rulespath.Count() > 0)
            {
                // Setup the rules
                verifier = new Verifier(_rulespath);
                if (!verifier.Verify())
                {
                    return((int)ExitCode.CriticalError);
                }

                if (verifier.CompiledRuleset.Count() == 0 && _ignoreDefaultRules)
                {
                    Console.Error.WriteLine("Error: No rules were loaded. ");
                    return((int)ExitCode.CriticalError);
                }
            }

            RuleSet rules = new RuleSet();

            if (verifier != null)
            {
                rules = verifier.CompiledRuleset;
            }

            if (!_ignoreDefaultRules)
            {
                Assembly assembly = Assembly.GetExecutingAssembly();
                string   filePath = "Microsoft.DevSkim.CLI.Resources.devskim-rules.json";
                Stream   resource = assembly.GetManifestResourceStream(filePath);
                using (StreamReader file = new StreamReader(resource))
                {
                    rules.AddString(file.ReadToEnd(), filePath, null);
                }
            }

            // Initialize the processor
            RuleProcessor processor = new RuleProcessor(rules);

            if (_severities.Count() > 0)
            {
                processor.SeverityLevel = 0;
                foreach (string severityText in _severities)
                {
                    Severity severity;
                    if (ParseSeverity(severityText, out severity))
                    {
                        processor.SeverityLevel |= severity;
                    }
                    else
                    {
                        Console.Error.WriteLine("Invalid severity: {0}", severityText);
                        return((int)ExitCode.CriticalError);
                    }
                }
            }

            Writer outputWriter = WriterFactory.GetWriter(_fileFormat,
                                                          (string.IsNullOrEmpty(_outputFile)) ? null : "text",
                                                          _outputFormat);

            if (string.IsNullOrEmpty(_outputFile))
            {
                outputWriter.TextWriter = Console.Out;
            }
            else
            {
                outputWriter.TextWriter = File.CreateText(_outputFile);
            }

            int filesAnalyzed = 0;
            int filesSkipped  = 0;
            int filesAffected = 0;
            int issuesCount   = 0;

            // Iterate through all files
            foreach (string filename in Directory.EnumerateFiles(_path, "*.*", SearchOption.AllDirectories))
            {
                string language = Language.FromFileName(filename);

                // Skip files written in unknown language
                if (string.IsNullOrEmpty(language))
                {
                    filesSkipped++;
                    continue;
                }

                filesAnalyzed++;
                string  fileText = File.ReadAllText(filename);
                Issue[] issues   = processor.Analyze(fileText, language);

                if (issues.Count() > 0)
                {
                    filesAffected++;
                    issuesCount += issues.Count();
                    Console.Error.WriteLine("file:{0}", filename);

                    // Iterate through each issue
                    foreach (Issue issue in issues)
                    {
                        Console.Error.WriteLine("\tregion:{0},{1},{2},{3} - {4} [{5}] - {6}",
                                                issue.StartLocation.Line,
                                                issue.StartLocation.Column,
                                                issue.EndLocation.Line,
                                                issue.EndLocation.Column,
                                                issue.Rule.Id,
                                                issue.Rule.Severity,
                                                issue.Rule.Name);

                        IssueRecord record = new IssueRecord()
                        {
                            Filename   = filename,
                            Filesize   = fileText.Length,
                            TextSample = fileText.Substring(issue.Boundary.Index, issue.Boundary.Length),
                            Issue      = issue
                        };

                        outputWriter.WriteIssue(record);
                    }

                    Console.Error.WriteLine();
                }
            }

            outputWriter.FlushAndClose();

            Console.Error.WriteLine("Issues found: {0} in {1} files", issuesCount, filesAffected);
            Console.Error.WriteLine("Files analyzed: {0}", filesAnalyzed);
            Console.Error.WriteLine("Files skipped: {0}", filesSkipped);

            return((int)ExitCode.NoIssues);
        }
Example #12
0
 public override void WriteIssue(IssueRecord issue)
 {
     // This is intentionaly empty
 }
        private static GameObject FindObjectInCollection(List <GameObject> allObjects, IssueRecord issue)
        {
            GameObject candidate = null;

            for (int i = 0; i < allObjects.Count; i++)
            {
                if (EditorTools.GetFullTransformPath(allObjects[i].transform) == issue.gameObject)
                {
                    candidate = allObjects[i];
                    if (issue.gameObjectIndex == i)
                    {
                        break;
                    }
                }
            }
            return(candidate);
        }
Example #14
0
        public int Run()
        {
            if (_suppressError)
            {
                Console.SetError(StreamWriter.Null);
            }

            if (!Directory.Exists(_path) && !File.Exists(_path))
            {
                Console.Error.WriteLine("Error: Not a valid file or directory {0}", _path);

                return((int)ExitCode.CriticalError);
            }

            Verifier?verifier = null;

            if (_rulespath.Count() > 0)
            {
                // Setup the rules
                verifier = new Verifier(_rulespath);
                if (!verifier.Verify())
                {
                    return((int)ExitCode.CriticalError);
                }

                if (verifier.CompiledRuleset.Count() == 0 && _ignoreDefaultRules)
                {
                    Console.Error.WriteLine("Error: No rules were loaded. ");
                    return((int)ExitCode.CriticalError);
                }
            }

            RuleSet rules = new RuleSet();

            if (verifier != null)
            {
                rules = verifier.CompiledRuleset;
            }

            if (!_ignoreDefaultRules)
            {
                Assembly?assembly = Assembly.GetAssembly(typeof(Boundary));
                string   filePath = "Microsoft.DevSkim.Resources.devskim-rules.json";
                Stream?  resource = assembly?.GetManifestResourceStream(filePath);
                if (resource is Stream)
                {
                    using (StreamReader file = new StreamReader(resource))
                    {
                        rules.AddString(file.ReadToEnd(), filePath, null);
                    }
                }
            }

            // Initialize the processor
            RuleProcessor processor = new RuleProcessor(rules);

            processor.EnableSuppressions = !_disableSuppression;

            if (_severities.Count() > 0)
            {
                processor.SeverityLevel = 0;
                foreach (string severityText in _severities)
                {
                    Severity severity;
                    if (ParseSeverity(severityText, out severity))
                    {
                        processor.SeverityLevel |= severity;
                    }
                    else
                    {
                        Console.Error.WriteLine("Invalid severity: {0}", severityText);
                        return((int)ExitCode.CriticalError);
                    }
                }
            }

            Writer outputWriter = WriterFactory.GetWriter(string.IsNullOrEmpty(_fileFormat) ? string.IsNullOrEmpty(_outputFile) ? "_dummy" : "text" : _fileFormat,
                                                          _outputFormat,
                                                          (string.IsNullOrEmpty(_outputFile) ? Console.Out : File.CreateText(_outputFile)),
                                                          _outputFile);

            int filesAnalyzed = 0;
            int filesSkipped  = 0;
            int filesAffected = 0;
            int issuesCount   = 0;

            // We can pass either a file or a directory; if it's a file, make an IEnumerable out of it.
            IEnumerable <FileEntry> fileListing;
            var extractor = new Extractor(new ExtractorOptions()
            {
                ExtractSelfOnFail = false
            });

            if (!Directory.Exists(_path))
            {
                fileListing = extractor.ExtractFile(_path);
            }
            else
            {
                fileListing = Directory.EnumerateFiles(_path, "*.*", SearchOption.AllDirectories).SelectMany(x => _crawlArchives ? extractor.ExtractFile(x) : FilenameToFileEntryArray(x));
            }

            // Iterate through all files
            foreach (FileEntry fileEntry in fileListing)
            {
                string language = Language.FromFileName(fileEntry.FullPath);

                // Skip files written in unknown language
                if (string.IsNullOrEmpty(language))
                {
                    filesSkipped++;
                    continue;
                }

                string fileText = string.Empty;

                try
                {
                    using (StreamReader reader = new StreamReader(fileEntry.Content))
                    {
                        fileText = reader.ReadToEnd();
                    }
                    filesAnalyzed++;
                }
                catch (Exception)
                {
                    // Skip files we can't parse
                    filesSkipped++;
                    continue;
                }

                Issue[] issues = processor.Analyze(fileText, language);

                bool issuesFound = issues.Any(iss => iss.IsSuppressionInfo == false) || _disableSuppression && issues.Count() > 0;

                if (issuesFound)
                {
                    filesAffected++;
                    Console.Error.WriteLine("file:{0}", fileEntry.FullPath);

                    // Iterate through each issue
                    foreach (Issue issue in issues)
                    {
                        if (!issue.IsSuppressionInfo || _disableSuppression)
                        {
                            issuesCount++;
                            Console.Error.WriteLine("\tregion:{0},{1},{2},{3} - {4} [{5}] - {6}",
                                                    issue.StartLocation.Line,
                                                    issue.StartLocation.Column,
                                                    issue.EndLocation.Line,
                                                    issue.EndLocation.Column,
                                                    issue.Rule.Id,
                                                    issue.Rule.Severity,
                                                    issue.Rule.Name);

                            IssueRecord record = new IssueRecord(
                                Filename: fileEntry.FullPath,
                                Filesize: fileText.Length,
                                TextSample: fileText.Substring(issue.Boundary.Index, issue.Boundary.Length),
                                Issue: issue,
                                Language: language);

                            outputWriter.WriteIssue(record);
                        }
                    }

                    Console.Error.WriteLine();
                }
            }

            outputWriter.FlushAndClose();

            Console.Error.WriteLine("Issues found: {0} in {1} files", issuesCount, filesAffected);
            Console.Error.WriteLine("Files analyzed: {0}", filesAnalyzed);
            Console.Error.WriteLine("Files skipped: {0}", filesSkipped);

            return((int)ExitCode.NoIssues);
        }
        private static void DrawSearchSection()
        {
            GUILayout.BeginVertical(UIHelpers.panelWithBackground, GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));
            GUILayout.Space(10);
            if (GUILayout.Button("Find issues!"))
            {
                startSearch = true;
            }
            GUILayout.Space(10);
            if (issues == null || issues.Length == 0)
            {
                GUILayout.Label("No issues");
            }
            else
            {
                int fromIssue = issuesCurrentPage * ISSUES_PER_PAGE;
                int toIssue   = fromIssue + Math.Min(ISSUES_PER_PAGE, issues.Length - fromIssue);

                GUILayout.Label("Issues " + fromIssue + " - " + toIssue + " from " + issues.Length);


                searchSectionScrollPosition = GUILayout.BeginScrollView(searchSectionScrollPosition);
                for (int i = fromIssue; i < toIssue; i++)
                {
                    IssueRecord issue = issues[i];
                    UIHelpers.Separator();
                    GUILayout.BeginVertical();
                    GUILayout.BeginHorizontal();

                    DrawIssueIcon(issue);
                    if (issue.source == IssueSource.Prefab)
                    {
                        DrawPrefabIcon();
                    }
                    GUILayout.Label(issue.GetHeader(), UIHelpers.richLabel, GUILayout.ExpandWidth(false));

                    GUILayout.EndHorizontal();
                    GUILayout.Label(issue.GetBody(), UIHelpers.richLabel);
                    GUILayout.BeginHorizontal(UIHelpers.panelWithBackground);
                    if (GUILayout.Button(new GUIContent("Show", "Selects Game Object with issue in the scene or Project Browser. Opens scene with needed Game Object if necessary and highlights this scene in the Project Browser."), GUILayout.Width(50)))
                    {
                        gotoIssue = issues[i];
                    }

                    if (GUILayout.Button(new GUIContent("Copy", "Copies record text to the clipboard."), GUILayout.Width(50)))
                    {
                        textEditorForClipboard.content = new GUIContent(issue.ToString(true));
                        textEditorForClipboard.SelectAll();
                        textEditorForClipboard.Copy();
                        window.ShowNotification(new GUIContent("Issue record copied to clipboard!"));
                    }
                    GUILayout.EndHorizontal();
                    GUILayout.EndVertical();
                }
                GUILayout.EndScrollView();

                if (issuesTotalPages > 1)
                {
                    GUILayout.Space(5);
                    GUILayout.BeginHorizontal();
                    GUILayout.FlexibleSpace();

                    GUI.enabled = (issuesCurrentPage > 0);
                    if (GUILayout.Button("<<", GUILayout.Width(50)))
                    {
                        window.RemoveNotification();
                        issuesCurrentPage           = 0;
                        searchSectionScrollPosition = Vector2.zero;
                    }
                    if (GUILayout.Button("<", GUILayout.Width(50)))
                    {
                        window.RemoveNotification();
                        issuesCurrentPage--;
                        searchSectionScrollPosition = Vector2.zero;
                    }
                    GUI.enabled = true;
                    GUILayout.Label((issuesCurrentPage + 1) + " of " + issuesTotalPages, UIHelpers.centeredLabel, GUILayout.Width(100));
                    GUI.enabled = (issuesCurrentPage < issuesTotalPages - 1);
                    if (GUILayout.Button(">", GUILayout.Width(50)))
                    {
                        window.RemoveNotification();
                        issuesCurrentPage++;
                        searchSectionScrollPosition = Vector2.zero;
                    }
                    if (GUILayout.Button(">>", GUILayout.Width(50)))
                    {
                        window.RemoveNotification();
                        issuesCurrentPage           = issuesTotalPages - 1;
                        searchSectionScrollPosition = Vector2.zero;
                    }
                    GUI.enabled = true;

                    GUILayout.FlexibleSpace();
                    GUILayout.EndHorizontal();
                }

                GUILayout.Space(5);

                GUILayout.BeginVertical();
                GUILayout.BeginHorizontal();
                if (GUILayout.Button("Copy report to clipboard"))
                {
                    textEditorForClipboard.content = new GUIContent(IssuesFinder.GenerateReport(issues));
                    textEditorForClipboard.SelectAll();
                    textEditorForClipboard.Copy();
                    window.ShowNotification(new GUIContent("Report copied to clipboard!"));
                }
                if (GUILayout.Button("Export report..."))
                {
                    string filePath = EditorUtility.SaveFilePanel("Save Issues Finder report", "", "MaintainerIssuesReport.txt", "txt");
                    if (!String.IsNullOrEmpty(filePath))
                    {
                        StreamWriter sr = File.CreateText(filePath);
                        sr.Write(IssuesFinder.GenerateReport(issues));
                        sr.Close();
                        window.ShowNotification(new GUIContent("Report saved!"));
                    }
                }
                GUILayout.EndHorizontal();
                GUILayout.EndVertical();
            }
            GUILayout.EndVertical();
        }
Example #16
0
        public int RunFileEntries(IEnumerable <FileEntry> fileListing, StreamWriter?outputStreamWriter = null)
        {
            Verifier?verifier = null;

            if (_rulespath.Length > 0)
            {
                // Setup the rules
                verifier = new Verifier(_rulespath);
                if (!verifier.Verify())
                {
                    return((int)ExitCode.CriticalError);
                }

                if (verifier.CompiledRuleset.Count() == 0 && _ignoreDefaultRules)
                {
                    Debug.WriteLine("Error: No rules were loaded. ");
                    return((int)ExitCode.CriticalError);
                }
            }

            RuleSet rules = new RuleSet();

            if (verifier != null)
            {
                rules = verifier.CompiledRuleset;
            }

            if (!_ignoreDefaultRules)
            {
                Assembly?assembly = Assembly.GetAssembly(typeof(Boundary));
                string   filePath = "Microsoft.DevSkim.Resources.devskim-rules.json";
                Stream?  resource = assembly?.GetManifestResourceStream(filePath);
                if (resource is Stream)
                {
                    using (StreamReader file = new StreamReader(resource))
                    {
                        var rulesString = file.ReadToEnd();
                        rules.AddString(rulesString, filePath, null);
                    }
                }
            }

            // Initialize the processor
            RuleProcessor processor = new RuleProcessor(rules);

            processor.EnableSuppressions = !_disableSuppression;

            if (_severities.Count() > 0)
            {
                processor.SeverityLevel = 0;
                foreach (string severityText in _severities)
                {
                    Severity severity;
                    if (ParseSeverity(severityText, out severity))
                    {
                        processor.SeverityLevel |= severity;
                    }
                    else
                    {
                        Debug.WriteLine("Invalid severity: {0}", severityText);
                        return((int)ExitCode.CriticalError);
                    }
                }
            }

            Writer outputWriter = WriterFactory.GetWriter(string.IsNullOrEmpty(_fileFormat) ? string.IsNullOrEmpty(_outputFile) ? "_dummy" : "text" : _fileFormat,
                                                          _outputFormat,
                                                          (outputStreamWriter is null)?(string.IsNullOrEmpty(_outputFile) ? Console.Out : File.CreateText(_outputFile)):outputStreamWriter,
                                                          (outputStreamWriter is null)?_outputFile:null);

            int filesAnalyzed = 0;
            int filesSkipped  = 0;
            int filesAffected = 0;
            int issuesCount   = 0;

            void parseFileEntry(FileEntry fileEntry)
            {
                string language = Language.FromFileName(fileEntry.FullPath);

                // Skip files written in unknown language
                if (string.IsNullOrEmpty(language))
                {
                    Interlocked.Increment(ref filesSkipped);
                }
                else
                {
                    string fileText = string.Empty;

                    try
                    {
                        using (StreamReader reader = new StreamReader(fileEntry.Content))
                        {
                            fileText = reader.ReadToEnd();
                        }
                        Interlocked.Increment(ref filesAnalyzed);
                    }
                    catch (Exception)
                    {
                        // Skip files we can't parse
                        Interlocked.Increment(ref filesSkipped);
                        return;
                    }

                    Issue[] issues = processor.Analyze(fileText, language);

                    bool issuesFound = issues.Any(iss => !iss.IsSuppressionInfo) || _disableSuppression && issues.Any();

                    if (issuesFound)
                    {
                        Interlocked.Increment(ref filesAffected);
                        Debug.WriteLine("file:{0}", fileEntry.FullPath);

                        // Iterate through each issue
                        foreach (Issue issue in issues)
                        {
                            if (!issue.IsSuppressionInfo || _disableSuppression)
                            {
                                Interlocked.Increment(ref issuesCount);
                                Debug.WriteLine("\tregion:{0},{1},{2},{3} - {4} [{5}] - {6}",
                                                issue.StartLocation.Line,
                                                issue.StartLocation.Column,
                                                issue.EndLocation.Line,
                                                issue.EndLocation.Column,
                                                issue.Rule.Id,
                                                issue.Rule.Severity,
                                                issue.Rule.Name);

                                IssueRecord record = new IssueRecord(
                                    Filename: fileEntry.FullPath,
                                    Filesize: fileText.Length,
                                    TextSample: fileText.Substring(issue.Boundary.Index, issue.Boundary.Length),
                                    Issue: issue,
                                    Language: language);

                                outputWriter.WriteIssue(record);
                            }
                        }
                    }
                }
            }

            //Iterate through all files
            if (_disableParallel)
            {
                foreach (var fileEntry in fileListing)
                {
                    parseFileEntry(fileEntry);
                }
            }
            else
            {
                Parallel.ForEach(fileListing, parseFileEntry);
            }

            outputWriter.FlushAndClose();

            Debug.WriteLine("Issues found: {0} in {1} files", issuesCount, filesAffected);
            Debug.WriteLine("Files analyzed: {0}", filesAnalyzed);
            Debug.WriteLine("Files skipped: {0}", filesSkipped);

            return((int)ExitCode.NoIssues);
        }
Example #17
0
 public abstract void WriteIssue(IssueRecord issue);