Class: RuboCop::Cop::RSpec::UnusedLet::ExternalDefinitions
- Inherits:
-
Object
- Object
- RuboCop::Cop::RSpec::UnusedLet::ExternalDefinitions
- Defined in:
- lib/rubocop/cop/rspec/unused_let/external_definitions.rb,
sig/rubocop/cop/rspec/unused_let/external_definitions.rbs
Overview
The SharedExamplePaths patterns resolved to file contents: the
absolute paths they expand to, a result-cache checksum covering them,
and their parsed definition maps for SharedExampleRegistry's external
fallback.
Instance Attribute Summary collapse
- #base_dir ⇒ String readonly
- #cache ⇒ Hash[String, cache_entry] readonly
- #patterns ⇒ Array[String] readonly
- #target_ruby_version ⇒ Numeric readonly
Class Method Summary collapse
-
.default_cache ⇒ Hash[String, cache_entry]
Process-wide cache of the external files' definition maps, keyed by absolute path to
[[mtime, size], definitions | nil].
Instance Method Summary collapse
- #build_definitions_for(path) ⇒ SharedExampleRegistry::definition_mapping?
-
#checksum ⇒ String?
The paths' digest for RuboCop's result-cache key, which otherwise covers no project file but the inspected one.
-
#definitions(excluding:) ⇒ Array[SharedExampleRegistry::definition_mapping]
The paths' definition maps, excluding
excludingso the file under investigation is never indexed twice. -
#definitions_for(path) ⇒ SharedExampleRegistry::definition_mapping?
The cached definition map for one external file, or
nilwhen it cannot be read or parsed — in which case the cop stays conservative rather than crashing the run. -
#file_signature(path) ⇒ String
path's identity for the result-cache digest. -
#initialize(patterns:, base_dir:, target_ruby_version:, cache: self.class.default_cache) ⇒ ExternalDefinitions
constructor
A new instance of ExternalDefinitions.
-
#paths ⇒ Array[String]
The absolute paths the patterns expand to, in a stable order.
Constructor Details
#initialize(patterns:, base_dir:, target_ruby_version:, cache: self.class.default_cache) ⇒ ExternalDefinitions
Returns a new instance of ExternalDefinitions.
35 36 37 38 39 40 |
# File 'lib/rubocop/cop/rspec/unused_let/external_definitions.rb', line 35 def initialize(patterns:, base_dir:, target_ruby_version:, cache: self.class.default_cache) #: void @patterns = patterns @base_dir = base_dir @target_ruby_version = target_ruby_version @cache = cache end |
Instance Attribute Details
#base_dir ⇒ String (readonly)
75 76 77 |
# File 'lib/rubocop/cop/rspec/unused_let/external_definitions.rb', line 75 def base_dir @base_dir end |
#cache ⇒ Hash[String, cache_entry] (readonly)
77 78 79 |
# File 'lib/rubocop/cop/rspec/unused_let/external_definitions.rb', line 77 def cache @cache end |
#patterns ⇒ Array[String] (readonly)
74 75 76 |
# File 'lib/rubocop/cop/rspec/unused_let/external_definitions.rb', line 74 def patterns @patterns end |
#target_ruby_version ⇒ Numeric (readonly)
76 77 78 |
# File 'lib/rubocop/cop/rspec/unused_let/external_definitions.rb', line 76 def target_ruby_version @target_ruby_version end |
Class Method Details
.default_cache ⇒ Hash[String, cache_entry]
Process-wide cache of the external files' definition maps, keyed by
absolute path to [[mtime, size], definitions | nil]. Used as the
default so a support file shared by many specs is scanned once per
process, not once per spec (RuboCop builds a fresh cop instance per
inspected file).
27 28 29 |
# File 'lib/rubocop/cop/rspec/unused_let/external_definitions.rb', line 27 def self.default_cache #: Hash[String, cache_entry] @default_cache ||= {} end |
Instance Method Details
#build_definitions_for(path) ⇒ SharedExampleRegistry::definition_mapping?
110 111 112 113 114 115 |
# File 'lib/rubocop/cop/rspec/unused_let/external_definitions.rb', line 110 def build_definitions_for(path) #: SharedExampleRegistry::definition_mapping? ast = RuboCop::AST::ProcessedSource.from_file(path, target_ruby_version).ast ast && SharedExampleRegistry.new(ast).local_definitions rescue RuboCop::Error, SystemCallError nil end |
#checksum ⇒ String?
The paths' digest for RuboCop's result-cache key, which otherwise
covers no project file but the inspected one. nil when there is
nothing to pre-load.
56 57 58 59 60 61 |
# File 'lib/rubocop/cop/rspec/unused_let/external_definitions.rb', line 56 def checksum #: String? found = paths return nil if found.empty? Digest::SHA1.hexdigest(found.map { file_signature(_1) }.join("\n")) end |
#definitions(excluding:) ⇒ Array[SharedExampleRegistry::definition_mapping]
The paths' definition maps, excluding excluding so the file under
investigation is never indexed twice.
67 68 69 70 |
# File 'lib/rubocop/cop/rspec/unused_let/external_definitions.rb', line 67 def definitions(excluding:) #: Array[SharedExampleRegistry::definition_mapping] current = File.(excluding) if excluding paths.reject { _1 == current }.filter_map { definitions_for(_1) } end |
#definitions_for(path) ⇒ SharedExampleRegistry::definition_mapping?
The cached definition map for one external file, or nil when it
cannot be read or parsed — in which case the cop stays conservative
rather than crashing the run.
96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/rubocop/cop/rspec/unused_let/external_definitions.rb', line 96 def definitions_for(path) #: SharedExampleRegistry::definition_mapping? stat = File.stat(path) key = [stat.mtime, stat.size] #: cache_key cached = cache[path] return cached.last if cached && cached.first == key definitions = build_definitions_for(path) cache[path] = [key, definitions] definitions rescue SystemCallError nil end |
#file_signature(path) ⇒ String
path's identity for the result-cache digest. Content rather than
mtime, which git does not preserve: keying on it would let a checkout
discard a persisted cache wholesale. An unreadable path still gets a
stable entry rather than breaking the run.
85 86 87 88 89 |
# File 'lib/rubocop/cop/rspec/unused_let/external_definitions.rb', line 85 def file_signature(path) #: String "#{path}:#{Digest::SHA1.file(path).hexdigest}" rescue SystemCallError "#{path}:" end |
#paths ⇒ Array[String]
The absolute paths the patterns expand to, in a stable order. Not
cached on the instance: a --server process outlives a run, so a
cached expansion would go on ignoring later additions.
45 46 47 48 49 50 51 |
# File 'lib/rubocop/cop/rspec/unused_let/external_definitions.rb', line 45 def paths #: Array[String] patterns .flat_map { Dir.glob(File.(_1, base_dir)) } .map { File.(_1) } .uniq .sort end |