Module: Sord::Resolver
- Defined in:
- lib/sord/resolver.rb
Class Method Summary collapse
- .add_rbi_objects_to_paths(nodes, names_to_paths, path = []) ⇒ Object
- .add_rbs_objects_to_paths(all_decls, names_to_paths, path = []) ⇒ Object
- .builtin_classes ⇒ Array<String>
- .clear ⇒ void
- .load_gem_objects(hash) ⇒ Object
- .path_for(name) ⇒ String?
- .paths_for(name) ⇒ Array<String>
- .prepare ⇒ void
- .resolvable?(name, item) ⇒ Boolean
Class Method Details
.add_rbi_objects_to_paths(nodes, names_to_paths, path = []) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/sord/resolver.rb', line 60 def self.add_rbi_objects_to_paths(nodes, names_to_paths, path=[]) klasses = [ Parlour::RbiGenerator::Constant, Parlour::RbiGenerator::ModuleNamespace, Parlour::RbiGenerator::ClassNamespace ] nodes.each do |node| next unless klasses.include?(node.class) new_path = path + [node.name] names_to_paths[node.name] ||= Set.new names_to_paths[node.name] << new_path.join('::') add_rbi_objects_to_paths(node.children, names_to_paths, new_path) if node.respond_to?(:children) end end |
.add_rbs_objects_to_paths(all_decls, names_to_paths, path = []) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/sord/resolver.rb', line 44 def self.add_rbs_objects_to_paths(all_decls, names_to_paths, path=[]) klasses = [ RBS::AST::Declarations::Module, RBS::AST::Declarations::Class, RBS::AST::Declarations::Constant ] all_decls.each do |decl| next unless klasses.include?(decl.class) name = decl.name.to_s new_path = path + [name] names_to_paths[name] ||= Set.new names_to_paths[name] << new_path.join('::') add_rbs_objects_to_paths(decl.members, names_to_paths, new_path) if decl.respond_to?(:members) end end |
.builtin_classes ⇒ Array<String>
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/sord/resolver.rb', line 99 def self.builtin_classes # This prints some deprecation warnings, so suppress them prev_stderr = $stderr $stderr = StringIO.new major = RUBY_VERSION.split('.').first.to_i sorted_set_removed = major >= 3 Object.constants .reject { |x| sorted_set_removed && x == :SortedSet } .select { |x| Object.const_get(x).is_a?(Class) } .map(&:to_s) ensure $stderr = prev_stderr end |
.clear ⇒ void
This method returns an undefined value.
76 77 78 |
# File 'lib/sord/resolver.rb', line 76 def self.clear @names_to_paths = nil end |
.load_gem_objects(hash) ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/sord/resolver.rb', line 24 def self.load_gem_objects(hash) all_decls = [] begin RBS::CLI::LibraryOptions.new.loader.load(env: all_decls) rescue RBS::Collection::Config::CollectionNotAvailable Sord::Logging.warn("Could not load RBS collection - run rbs collection install for dependencies") end add_rbs_objects_to_paths(all_decls, hash) gem_paths = Bundler.load.specs.map(&:full_gem_path) gem_paths.each do |path| next unless File.exist?("#{path}/rbi") Dir["#{path}/rbi/**/*.rbi"].each do |sigfile| tree = Parlour::TypeLoader.load_file(sigfile) add_rbi_objects_to_paths(tree.children, hash) end end end |
.path_for(name) ⇒ String?
94 95 96 |
# File 'lib/sord/resolver.rb', line 94 def self.path_for(name) paths_for(name).one? ? paths_for(name).first : nil end |
.paths_for(name) ⇒ Array<String>
82 83 84 85 86 87 88 89 90 |
# File 'lib/sord/resolver.rb', line 82 def self.paths_for(name) prepare # If the name starts with ::, then we've been given an explicit path from root - just use that return [name] if name.start_with?('::') (@names_to_paths[name.split('::').last] || []) .select { |x| x.end_with?(name) } end |
.prepare ⇒ void
This method returns an undefined value.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/sord/resolver.rb', line 9 def self.prepare return @names_to_paths if @names_to_paths gem_objects = {} load_gem_objects(gem_objects) # Construct a hash of class names to full paths @names_to_paths = YARD::Registry.all(:class) .group_by(&:name) .map { |k, v| [k.to_s, v.map(&:path).to_set] } .to_h .merge(builtin_classes.map { |x| [x, Set.new([x])] }.to_h) { |_k, a, b| a.union(b) } .merge(gem_objects) { |_k, a, b| a.union(b) } end |
.resolvable?(name, item) ⇒ Boolean
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/sord/resolver.rb', line 118 def self.resolvable?(name, item) current_context = item current_context = current_context.parent \ until current_context.is_a?(YARD::CodeObjects::NamespaceObject) # If there is any matching object directly in the heirarchy, this is # always true. Ruby can do the resolution. unless name.include?('::') return true if current_context.path.split('::').include?(name) end name_parts = name.split('::') matching_paths = [] loop do # Try to find that class in this context path_followed_context = current_context name_parts.each do |name_part| path_followed_context = path_followed_context&.child( name: name_part, type: [:class, :method, :module] ) end # Return true if we found the constant we're looking for here matching_paths |= [path_followed_context.path] if path_followed_context # Move up one context break if current_context.root? current_context = current_context.parent end return (builtin_classes.include?(name) && matching_paths.empty?) || (matching_paths.one? && !builtin_classes.include?(name)) end |