Module: Snoot::AnalyserOrchestration::Default
- Defined in:
- lib/snoot/analyser_orchestration/default.rb
Overview
Default is the production adapter for AnalyserOrchestration. It invokes the real Reek/Flog/Flay APIs in-process (no shellouts) and resolves vendored_doc against the reek docs vendored at data/reek_docs/<PascalCase-Hyphen>.md (synced via ‘rake docs:sync`, pinned to the bundled reek version). Reek invocation honours a project-local `.reek.yml` (or any ancestor’s, falling back to ‘~/.reek.yml`) via `AppConfiguration.from_default_path`, matching reek’s own CLI discovery. Flog scoring uses Flog’s default options (every scored method emits a ComplexityHit; selection happens in AnalyseRun). Flay duplication uses Flay’s default mass threshold (16). Stateless: implemented as a module of module functions, used as the orchestration value directly (no ‘.new`).
Default’s public surface is exactly the five contracted methods (vendored_doc, significant_smells, significant_complexities, significant_duplications, analyse). The per-analyser drivers (reek_analyse, flog_analyse, flay_analyse) and the per-pathname helper (reek_smells_for) are private; their behaviour is observed through analyse. Pure third-party-output translation is delegated to the sibling module ResultMapping.
Per-analyser directory expansion mirrors each tool’s own CLI default rather than imposing a snoot-wide glob, so a directory Path resolves exactly as that tool would resolve it on the command line. Reek defers to ‘Reek::Source::SourceLocator` (which also honours `.reek.yml exclude_paths`); Flog uses `*/.rb,rake` to match `Flog::CLI`; Flay uses `*/.rb` (Flay’s CLI additionally appends extensions advertised by installed Flay plugins, which snoot does not load). The orchestration contract is path-abstract (snoot.allium:150), so this is implementation policy each adapter owns.
Constant Summary collapse
- DOCS_ROOT =
File.("../../../data/reek_docs", __dir__).freeze
- DOC_FILENAME_PATTERN =
/([a-z])([A-Z])/- SMELL_TYPE_INSTANCE_FLOOR =
2- COMPLEXITY_SCORE_FLOOR =
BigDecimal("25")
- ANALYSER_PROBES =
[ %i[reek reek_analyse], %i[flog flog_analyse], %i[flay flay_analyse] ].freeze
Class Method Summary collapse
-
.analyse(paths) ⇒ Object
analyse runs the three analysers in canonical order (Reek -> Flog -> Flay), capturing each result as it succeeds.
- .significant_complexities(complexities) ⇒ Object
- .significant_duplications(duplications) ⇒ Object
- .significant_smells(smells) ⇒ Object
- .vendored_doc(smell_type) ⇒ Object
Class Method Details
.analyse(paths) ⇒ Object
analyse runs the three analysers in canonical order (Reek -> Flog -> Flay), capturing each result as it succeeds. On the first failure it returns an AnalyserFailure tagged with that analyser and does not invoke the remaining ones. On full success it returns a Sources bundling the three result sets.
128 129 130 131 132 133 134 135 |
# File 'lib/snoot/analyser_orchestration/default.rb', line 128 def analyse(paths) outputs = collect_outputs(paths) return outputs if outputs.is_a?(AnalyserFailure) Sources.new( smells: outputs[:reek], complexities: outputs[:flog], duplications: outputs[:flay] ) end |
.significant_complexities(complexities) ⇒ Object
117 118 119 |
# File 'lib/snoot/analyser_orchestration/default.rb', line 117 def significant_complexities(complexities) complexities.select { |hit| hit.score >= COMPLEXITY_SCORE_FLOOR }.to_set end |
.significant_duplications(duplications) ⇒ Object
121 |
# File 'lib/snoot/analyser_orchestration/default.rb', line 121 def significant_duplications(duplications) = duplications |
.significant_smells(smells) ⇒ Object
112 113 114 115 |
# File 'lib/snoot/analyser_orchestration/default.rb', line 112 def significant_smells(smells) counts = smells.group_by(&:smell_type).transform_values(&:size) smells.select { |smell| counts[smell.smell_type] >= SMELL_TYPE_INSTANCE_FLOOR }.to_set end |
.vendored_doc(smell_type) ⇒ Object
104 105 106 107 108 109 110 |
# File 'lib/snoot/analyser_orchestration/default.rb', line 104 def vendored_doc(smell_type) name = smell_type.name @vendored_doc_cache.fetch(name) do path = File.join(DOCS_ROOT, "#{name.gsub(DOC_FILENAME_PATTERN, '\1-\2')}.md") @vendored_doc_cache[name] = File.exist?(path) ? File.read(path) : nil end end |