Class: MetzScan::Analyzers::SubclassOverridePressure

Inherits:
Object
  • Object
show all
Includes:
ProjectAnalyzerTriage, FamilyBuilder, Metadata, Triage
Defined in:
lib/metz_scan/analyzers/subclass_override_pressure.rb,
lib/metz_scan/analyzers/subclass_override_pressure/triage.rb,
lib/metz_scan/analyzers/subclass_override_pressure/finding.rb,
lib/metz_scan/analyzers/subclass_override_pressure/metadata.rb,
lib/metz_scan/analyzers/subclass_override_pressure/family_builder.rb,
lib/metz_scan/analyzers/subclass_override_pressure/method_body_facts.rb

Overview

Reports base classes whose descendants repeatedly override the same method.

Defined Under Namespace

Modules: FamilyBuilder, Metadata, Triage Classes: Finding, MethodBodyFacts, OverrideFamily

Constant Summary collapse

RULE_ID =
"MetzProject/SubclassOverridePressure"
PROJECT_ANALYZER_STATUS =
"candidate"
CONFIDENCE =
"medium"
TRIAGE_SEVERITY =
"manual review"
TRIAGE_SUMMARY =
"Candidate subclass override signal; review whether shared hooks hide coupling."
BROAD_ROOT_CONFIDENCE =
"low"
BROAD_ROOT_TRIAGE_SEVERITY =
"broad base"
BROAD_ROOT_TRIAGE_SUMMARY =
"Broad inheritance base with repeated overrides; review only when hook " \
"changes frequently or subclasses diverge."
WHY =
"Repeated subclass overrides can turn inheritance into an implicit protocol that is hard to change."
SUGGESTED_NEXT_MOVES =
[
  "Review whether the base class is defining a hook protocol that should be explicit.",
  "Prefer composition when subclasses override the same behavior for unrelated reasons."
].freeze
MINIMUM_OVERRIDING_DESCENDANTS =
6

Instance Method Summary collapse

Methods included from Triage

#abstract_hook_message_for, #broad_root_triage_attributes, #cooperative_override_message_for, #generic_override_message_for, #generic_triage_profile, #message_for, #message_method_for, #project_analyzer_context_attributes, #replacement_override_message_for, #triage_attributes_for, #triage_profile_for

Methods included from Metadata

#abstract_hook_body?, #body_fact_metadata, #category_metadata, #core_project_analyzer_metadata, #count_metadata, #family_identity_metadata, #family_metadata, #override_identity_location, #override_location, #override_locations, #project_analyzer_metadata_for, #subclass_override_category

Constructor Details

#initialize(paths: nil, index: nil, base_names: nil, minimum_overriding_descendants: MINIMUM_OVERRIDING_DESCENDANTS) ⇒ SubclassOverridePressure

Returns a new instance of SubclassOverridePressure.



48
49
50
51
52
53
54
# File 'lib/metz_scan/analyzers/subclass_override_pressure.rb', line 48

def initialize(paths: nil, index: nil, base_names: nil,
               minimum_overriding_descendants: MINIMUM_OVERRIDING_DESCENDANTS)
  @paths = Array(paths)
  @index = index || ProjectIndex.build(@paths)
  @base_names = Array(base_names).compact
  @minimum_overriding_descendants = minimum_overriding_descendants
end

Instance Method Details

#callObject



56
57
58
59
60
# File 'lib/metz_scan/analyzers/subclass_override_pressure.rb', line 56

def call
  return [] unless index.available?

  base_candidates.flat_map { |base| findings_for(base) }
end