Module: MetzScan::Commands::Scan::ProjectAnalyzerRunner
- Defined in:
- lib/metz_scan/commands/scan/project_analyzer_runner.rb
Overview
Runs wrapper-level project analyzers and merges their findings into the same report shape produced by RuboCop's JSON formatter.
Constant Summary collapse
- ANALYZERS =
[ Analyzers::RepeatedBranching, Analyzers::ServiceSoup, Analyzers::InheritanceDescendants, Analyzers::PackageDependencyPressure, Analyzers::NamespaceLeakPressure, Analyzers::ImplicitContextPressure, Analyzers::RepeatedQueryCriteria, Analyzers::SubclassOverridePressure ].freeze
- INDEX_BACKED_ANALYZERS =
[Analyzers::InheritanceDescendants, Analyzers::PackageDependencyPressure, Analyzers::NamespaceLeakPressure, Analyzers::SubclassOverridePressure].freeze
- DEFAULT_OUTPUT_STATUS =
"validated"- DEFAULT_OUTPUT_CONFIDENCE =
"medium"- DEFAULT_OUTPUT_TRIAGE_SEVERITY =
"design pressure"
Class Method Summary collapse
- .analyzer_paths(paths, index: nil, force_default_config: false) ⇒ Object
- .analyzers_for(default_output:) ⇒ Object
- .append_file(files, path) ⇒ Object
- .default_output_analyzer?(analyzer) ⇒ Boolean
- .default_output_finding?(finding) ⇒ Boolean
- .display_path(path) ⇒ Object
- .file_for(parsed, path) ⇒ Object
- .merge!(parsed, paths) ⇒ Object
- .merge_findings(parsed, findings) ⇒ Object
- .merge_offenses(parsed, grouped_offenses) ⇒ Object
- .project_findings(paths, index: nil, default_output: false) ⇒ Object
- .project_findings_for(paths, index: nil, default_output: false, force_default_config: false) ⇒ Object
- .project_index_for(paths, index, analyzers) ⇒ Object
- .rubocop_target_files(paths, force_default_config: false) ⇒ Object
- .same_path?(left, right) ⇒ Boolean
- .update_file_counts(summary, file_count) ⇒ Object
- .update_summary(parsed, findings, project_offenses) ⇒ Object
Class Method Details
.analyzer_paths(paths, index: nil, force_default_config: false) ⇒ Object
94 95 96 97 98 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 94 def analyzer_paths(paths, index: nil, force_default_config: false) return Array(paths) if index rubocop_target_files(paths, force_default_config: force_default_config) end |
.analyzers_for(default_output:) ⇒ Object
68 69 70 71 72 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 68 def analyzers_for(default_output:) return ANALYZERS unless default_output ANALYZERS.select { |analyzer| default_output_analyzer?(analyzer) } end |
.append_file(files, path) ⇒ Object
121 122 123 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 121 def append_file(files, path) { "path" => display_path(path), "offenses" => [] }.tap { |file| files << file } end |
.default_output_analyzer?(analyzer) ⇒ Boolean
74 75 76 77 78 79 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 74 def default_output_analyzer?(analyzer) analyzer.const_defined?(:DEFAULT_OUTPUT_ELIGIBLE) && analyzer::DEFAULT_OUTPUT_ELIGIBLE && analyzer.const_defined?(:PROJECT_ANALYZER_STATUS) && analyzer::PROJECT_ANALYZER_STATUS == DEFAULT_OUTPUT_STATUS end |
.default_output_finding?(finding) ⇒ Boolean
88 89 90 91 92 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 88 def default_output_finding?(finding) finding.project_analyzer_status == DEFAULT_OUTPUT_STATUS && finding.confidence == DEFAULT_OUTPUT_CONFIDENCE && finding.triage_severity == DEFAULT_OUTPUT_TRIAGE_SEVERITY end |
.display_path(path) ⇒ Object
125 126 127 128 129 130 131 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 125 def display_path(path) = File.(path) cwd = "#{File.(Dir.pwd)}#{File::SEPARATOR}" return .delete_prefix(cwd) if .start_with?(cwd) path end |
.file_for(parsed, path) ⇒ Object
112 113 114 115 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 112 def file_for(parsed, path) files = parsed["files"] ||= [] files.find { |file| same_path?(file["path"], path) } || append_file(files, path) end |
.merge!(parsed, paths) ⇒ Object
40 41 42 43 44 45 46 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 40 def merge!(parsed, paths, **) findings = project_findings_for(paths, **) return parsed if findings.empty? merge_findings(parsed, findings) parsed end |
.merge_findings(parsed, findings) ⇒ Object
56 57 58 59 60 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 56 def merge_findings(parsed, findings) offense_set = ProjectAnalyzerOffenses.build(findings) merge_offenses(parsed, offense_set.by_path) update_summary(parsed, findings, offense_set.offenses) end |
.merge_offenses(parsed, grouped_offenses) ⇒ Object
106 107 108 109 110 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 106 def merge_offenses(parsed, grouped_offenses) grouped_offenses.each do |path, offenses| file_for(parsed, path)["offenses"].concat(offenses) end end |
.project_findings(paths, index: nil, default_output: false) ⇒ Object
62 63 64 65 66 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 62 def project_findings(paths, index: nil, default_output: false) analyzers = analyzers_for(default_output: default_output) index = project_index_for(paths, index, analyzers) analyzers.flat_map { |analyzer| analyzer.new(paths: paths, index: index).call } end |
.project_findings_for(paths, index: nil, default_output: false, force_default_config: false) ⇒ Object
48 49 50 51 52 53 54 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 48 def project_findings_for(paths, index: nil, default_output: false, force_default_config: false) paths = analyzer_paths(paths, index: index, force_default_config: force_default_config) return [] if paths.empty? && !index findings = project_findings(paths, index: index, default_output: default_output) default_output ? findings.select { |finding| default_output_finding?(finding) } : findings end |
.project_index_for(paths, index, analyzers) ⇒ Object
81 82 83 84 85 86 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 81 def project_index_for(paths, index, analyzers) return index if index return nil unless analyzers.any? { |analyzer| INDEX_BACKED_ANALYZERS.include?(analyzer) } ProjectIndex.build(paths) end |
.rubocop_target_files(paths, force_default_config: false) ⇒ Object
100 101 102 103 104 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 100 def rubocop_target_files(paths, force_default_config: false) return TargetFileDiscovery.with_forced_defaults(paths) if force_default_config TargetFileDiscovery.for_project_config(paths) end |
.same_path?(left, right) ⇒ Boolean
117 118 119 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 117 def same_path?(left, right) File.(left) == File.(right) end |
.update_file_counts(summary, file_count) ⇒ Object
141 142 143 144 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 141 def update_file_counts(summary, file_count) summary["target_file_count"] = [summary["target_file_count"].to_i, file_count].max summary["inspected_file_count"] = [summary["inspected_file_count"].to_i, file_count].max end |
.update_summary(parsed, findings, project_offenses) ⇒ Object
133 134 135 136 137 138 139 |
# File 'lib/metz_scan/commands/scan/project_analyzer_runner.rb', line 133 def update_summary(parsed, findings, project_offenses) summary = parsed["summary"] ||= {} files = Array(parsed["files"]) summary["offense_count"] = files.sum { |file| Array(file["offenses"]).size } update_file_counts(summary, files.size) summary["project_analyzers"] = ProjectAnalyzerMetadata.summary(findings, project_offenses) end |