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; }
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); }
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); }
protected override void LoadLastRecords() { // ReSharper disable CoVariantArrayConversion records = SearchResultsStorage.IssuesSearchResults; if (records == null) { records = new IssueRecord[0]; } // ReSharper restore CoVariantArrayConversion }
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); }
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); }
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); }
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); }
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); }
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); }
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(); }
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); }
public abstract void WriteIssue(IssueRecord issue);