Class: ReferenceExtractor::Internal::ConstantDiscovery

Inherits:
Object
  • Object
show all
Defined in:
lib/reference_extractor/internal/constant_discovery.rb

Overview

Get information about unresolved constants without loading the application code. Information gathered: Fully qualified name and path to file containing the definition.

The implementation makes a few assumptions about the code base:

  • ‘Something::SomeOtherThing` is defined in a path of either `something/some_other_thing.rb` or `something.rb`, relative to the load path. Rails’ ‘zeitwerk` autoloader makes the same assumption.

  • It is OK to not always infer the exact file defining the constant. For example, when a constant is inherited, we have no way of inferring the file it is defined in. You could argue though that inheritance means that another constant with the same name exists in the inheriting class, and this view is sufficient for all our use cases.

Defined Under Namespace

Classes: Error

Instance Method Summary collapse

Constructor Details

#initialize(root_path:, loaders:) ⇒ ConstantDiscovery

Returns a new instance of ConstantDiscovery.



17
18
19
20
# File 'lib/reference_extractor/internal/constant_discovery.rb', line 17

def initialize(root_path:, loaders:)
  @root_path = root_path
  @loaders = loaders
end

Instance Method Details

#context_for(const_name, current_namespace_path: []) ⇒ ConstantContext

Analyze a constant via its name. If the constant is unresolved, we need the current namespace path to correctly infer its full name

Parameters:

  • const_name (String)

    The unresolved constant’s name.

  • current_namespace_path (Array<String>) (defaults to: [])

    (optional) The namespace of the context in which the constant is used, e.g. [“Apps”, “Models”] for ‘Apps::Models`. Defaults to [] which means top level.

Returns:



29
30
31
32
33
34
35
36
37
# File 'lib/reference_extractor/internal/constant_discovery.rb', line 29

def context_for(const_name, current_namespace_path: [])
  current_namespace_path = [] if const_name.start_with?("::")
  const_name, location = resolve_constant(const_name.delete_prefix("::"), current_namespace_path)

  return unless location

  relative_location = Pathname.new(location).relative_path_from(@root_path)
  ConstantContext.new(const_name, relative_location)
end

#validate_constantsConstantDiscovery

Analyze the constants and raise errors if any potential issues are encountered that would prevent resolving the context for constants, such as ambiguous constant locations.

Returns:



43
44
45
46
# File 'lib/reference_extractor/internal/constant_discovery.rb', line 43

def validate_constants
  const_locations
  true
end