From 4da922fe1fcc0ccab06b975c77f7fbaeecb712e5 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 11 Jul 2025 17:37:41 -0400 Subject: [PATCH 01/10] Various linting fixes --- lib/solargraph/doc_map.rb | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/lib/solargraph/doc_map.rb b/lib/solargraph/doc_map.rb index d51fc3022..45a669678 100644 --- a/lib/solargraph/doc_map.rb +++ b/lib/solargraph/doc_map.rb @@ -2,6 +2,7 @@ require 'pathname' require 'benchmark' +require 'open3' module Solargraph # A collection of pins generated from required gems. @@ -32,8 +33,10 @@ def uncached_gemspecs # @return [Array] attr_reader :uncached_rbs_collection_gemspecs + # @return [String, nil] attr_reader :rbs_collection_path + # @return [String, nil] attr_reader :rbs_collection_config_path # @return [Workspace, nil] @@ -56,6 +59,8 @@ def initialize(requires, preferences, workspace = nil) pins.concat @environ.pins end + # @param out [IO] + # @return [void] def cache_all!(out) # if we log at debug level: if logger.info? @@ -73,12 +78,18 @@ def cache_all!(out) @uncached_yard_gemspecs = [] end + # @param gemspec [Gem::Specification] + # @param out [IO] + # @return [void] def cache_yard_pins(gemspec, out) pins = GemPins.build_yard_pins(gemspec) PinCache.serialize_yard_gem(gemspec, pins) logger.info { "Cached #{pins.length} YARD pins for gem #{gemspec.name}:#{gemspec.version}" } unless pins.empty? end + # @param gemspec [Gem::Specification] + # @param out [IO] + # @return [void] def cache_rbs_collection_pins(gemspec, out) rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path) pins = rbs_map.pins @@ -90,6 +101,9 @@ def cache_rbs_collection_pins(gemspec, out) end # @param gemspec [Gem::Specification] + # @param rebuild [Boolean] whether to rebuild the pins even if they are cached + # @param out [IO, nil] output stream for logging + # @return [void] def cache(gemspec, rebuild: false, out: nil) build_yard = uncached_yard_gemspecs.include?(gemspec) || rebuild build_rbs_collection = uncached_rbs_collection_gemspecs.include?(gemspec) || rebuild @@ -113,26 +127,33 @@ def unresolved_requires @unresolved_requires ||= required_gems_map.select { |_, gemspecs| gemspecs.nil? }.keys end + # @return [Hash{Array(String, String) => Array}] Indexed by gemspec name and version def self.all_yard_gems_in_memory @yard_gems_in_memory ||= {} end + # @return [Hash{String => Array}] stored by RBS collection path def self.all_rbs_collection_gems_in_memory @rbs_collection_gems_in_memory ||= {} end + # @return [Hash{Array(String, String) => Array}] Indexed by gemspec name and version def yard_pins_in_memory self.class.all_yard_gems_in_memory end + # @return [Hash{Array(String, String) => Array}] Indexed by gemspec name and version def rbs_collection_pins_in_memory self.class.all_rbs_collection_gems_in_memory[rbs_collection_path] ||= {} end + # @return [Hash{Array(String, String) => Array}] Indexed by gemspec name and version def self.all_combined_pins_in_memory @combined_pins_in_memory ||= {} end + # @todo this should also include an index by the hash of the RBS collection + # @return [Hash{Array(String, String) => Array}] Indexed by gemspec name and version def combined_pins_in_memory self.class.all_combined_pins_in_memory end @@ -150,7 +171,9 @@ def load_serialized_gem_pins @uncached_yard_gemspecs = [] @uncached_rbs_collection_gemspecs = [] with_gemspecs, without_gemspecs = required_gems_map.partition { |_, v| v } + # @type [Array] paths = Hash[without_gemspecs].keys + # @type [Array] gemspecs = Hash[with_gemspecs].values.flatten.compact + dependencies.to_a paths.each do |path| @@ -259,6 +282,8 @@ def deserialize_stdlib_rbs_map path end end + # @param gemspec [Gem::Specification] + # @param rbs_version_cache_key [String] # @return [Array, nil] def deserialize_rbs_collection_cache gemspec, rbs_version_cache_key return if rbs_collection_pins_in_memory.key?([gemspec, rbs_version_cache_key]) @@ -274,22 +299,13 @@ def deserialize_rbs_collection_cache gemspec, rbs_version_cache_key end end - # @param gemspec [Gem::Specification] - # @return [Boolean] - def try_gem_in_memory gemspec - gempins = DocMap.gems_in_memory[gemspec] - return false unless gempins - Solargraph.logger.debug "Found #{gemspec.name} #{gemspec.version} in memory" - @pins.concat gempins - true - end - # @param path [String] # @return [::Array, nil] def resolve_path_to_gemspecs path return nil if path.empty? return gemspecs_required_from_bundler if path == 'bundler/require' + # @type [Gem::Specification, nil] gemspec = Gem::Specification.find_by_path(path) if gemspec.nil? gem_name_guess = path.split('/').first @@ -355,6 +371,7 @@ def inspect self.class.inspect end + # @return [Array] def gemspecs_required_from_bundler # @todo Handle projects with custom Bundler/Gemfile setups return unless workspace.gemfile? @@ -377,6 +394,7 @@ def gemspecs_required_from_bundler end end + # @return [Array] def gemspecs_required_from_external_bundle logger.info 'Fetching gemspecs required from external bundle' return [] unless workspace&.directory From 6014c699bb767cb1cee68e1474e5e15f04a5b5cd Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 11 Jul 2025 17:48:29 -0400 Subject: [PATCH 02/10] Linting for Library class --- lib/solargraph/library.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/solargraph/library.rb b/lib/solargraph/library.rb index 8eadeed62..75b0e3e2b 100644 --- a/lib/solargraph/library.rb +++ b/lib/solargraph/library.rb @@ -621,6 +621,7 @@ def cache_next_gemspec end end + # @return [Array] def cacheable_specs cacheable = api_map.uncached_yard_gemspecs + api_map.uncached_rbs_collection_gemspecs - @@ -631,6 +632,7 @@ def cacheable_specs queued_gemspec_cache end + # @return [Array] def queued_gemspec_cache @queued_gemspec_cache ||= [] end @@ -672,6 +674,7 @@ def end_cache_progress @total = nil end + # @return [void] def sync_catalog return if @sync_count == 0 From b10791202d100fc612c2cb7cba72f272e5c7056a Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 11 Jul 2025 18:17:36 -0400 Subject: [PATCH 03/10] Linting fixes --- lib/solargraph/rbs_map.rb | 17 +++++++++++++++-- lib/solargraph/shell.rb | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/solargraph/rbs_map.rb b/lib/solargraph/rbs_map.rb index c2673c71b..2f36ce991 100644 --- a/lib/solargraph/rbs_map.rb +++ b/lib/solargraph/rbs_map.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require 'digest' require 'pathname' require 'rbs' @@ -22,7 +23,8 @@ class RbsMap attr_reader :rbs_collection_config_path # @param library [String] - # @param version [String, nil] + # @param version [String, nil + # @param rbs_collection_config_path [String, Pathname, nil] # @param rbs_collection_paths [Array] def initialize library, version = nil, rbs_collection_config_path: nil, rbs_collection_paths: [] if rbs_collection_config_path.nil? && !rbs_collection_paths.empty? @@ -35,11 +37,13 @@ def initialize library, version = nil, rbs_collection_config_path: nil, rbs_coll add_library loader, library, version end + # @return [RBS::EnvironmentLoader] def loader @loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository) end - # @return string representing the version of the RBS info fetched + # @sg-ignore + # @return [String] representing the version of the RBS info fetched # for the given library. Must change when the RBS info is # updated upstream for the same library and version. May change # if the config for where information comes form changes. @@ -68,6 +72,10 @@ def cache_key end end + # @param gemspec [Gem::Specification] + # @param rbs_collection_path [String, Pathname, nil] + # @param rbs_collection_config_path [String, Pathname, nil] + # @return [RbsMap] def self.from_gemspec gemspec, rbs_collection_path, rbs_collection_config_path rbs_map = RbsMap.new(gemspec.name, gemspec.version, rbs_collection_paths: [rbs_collection_path].compact, @@ -80,6 +88,7 @@ def self.from_gemspec gemspec, rbs_collection_path, rbs_collection_config_path rbs_collection_config_path: rbs_collection_config_path) end + # @return [Array] def pins @pins ||= resolved? ? conversions.pins : [] end @@ -103,6 +112,7 @@ def resolved? @resolved end + # @return [RBS::Repository] def repository @repository ||= RBS::Repository.new(no_stdlib: false).tap do |repo| @rbs_collection_paths.each do |dir| @@ -120,16 +130,19 @@ def self.load library private + # @return [RBS::EnvironmentLoader] def loader @loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository) end + # @return [Conversions] def conversions @conversions ||= Conversions.new(loader: loader) end # @param loader [RBS::EnvironmentLoader] # @param library [String] + # @param version [String, nil] # @return [Boolean] true if adding the library succeeded def add_library loader, library, version @resolved = if loader.has_library?(library: library, version: version) diff --git a/lib/solargraph/shell.rb b/lib/solargraph/shell.rb index 8f02f6ec9..afea86a92 100755 --- a/lib/solargraph/shell.rb +++ b/lib/solargraph/shell.rb @@ -258,6 +258,7 @@ def pin_description pin end # @param gemspec [Gem::Specification] + # @param api_map [ApiMap] # @return [void] def do_cache gemspec, api_map # @todo if the rebuild: option is passed as a positional arg, From 876bc4227650aba472e39f010a4fcff4124baf60 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sat, 12 Jul 2025 10:04:07 -0400 Subject: [PATCH 04/10] Linting fixes --- lib/solargraph/api_map/index.rb | 3 +++ lib/solargraph/api_map/store.rb | 10 +++++++--- lib/solargraph/diagnostics/rubocop_helpers.rb | 1 + .../message/text_document/formatting.rb | 8 ++++++++ lib/solargraph/page.rb | 4 ++++ lib/solargraph/parser/flow_sensitive_typing.rb | 1 + lib/solargraph/source/chain/link.rb | 1 + lib/solargraph/workspace.rb | 1 + 8 files changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/solargraph/api_map/index.rb b/lib/solargraph/api_map/index.rb index 810600534..990fc7169 100644 --- a/lib/solargraph/api_map/index.rb +++ b/lib/solargraph/api_map/index.rb @@ -15,6 +15,9 @@ def pins @pins ||= [] end + # @return [Set] + attr_reader :namespaces + # @return [Hash{String => Array}] def namespace_hash @namespace_hash ||= Hash.new { |h, k| h[k] = [] } diff --git a/lib/solargraph/api_map/store.rb b/lib/solargraph/api_map/store.rb index 47f92194c..d41a2a0ae 100644 --- a/lib/solargraph/api_map/store.rb +++ b/lib/solargraph/api_map/store.rb @@ -8,6 +8,7 @@ class ApiMap class Store # @param pinsets [Array>] def initialize *pinsets + @pinsets = pinsets catalog pinsets end @@ -200,10 +201,13 @@ def fqns_pins fqns private + # @return [Index] def index @indexes.last end + # @param pinsets [Array>] + # @return [Boolean] def catalog pinsets @pinsets = pinsets @indexes = [] @@ -235,17 +239,17 @@ def superclass_references index.superclass_references end - # @return [Hash{String => Array}] + # @return [Hash{String => Array}] def include_references index.include_references end - # @return [Hash{String => Array}] + # @return [Hash{String => Array}] def prepend_references index.prepend_references end - # @return [Hash{String => Array}] + # @return [Hash{String => Array}] def extend_references index.extend_references end diff --git a/lib/solargraph/diagnostics/rubocop_helpers.rb b/lib/solargraph/diagnostics/rubocop_helpers.rb index 8e2e13359..4eb2c711d 100644 --- a/lib/solargraph/diagnostics/rubocop_helpers.rb +++ b/lib/solargraph/diagnostics/rubocop_helpers.rb @@ -15,6 +15,7 @@ module RubocopHelpers # @return [void] def require_rubocop(version = nil) begin + # @type [String] gem_path = Gem::Specification.find_by_name('rubocop', version).full_gem_path gem_lib_path = File.join(gem_path, 'lib') $LOAD_PATH.unshift(gem_lib_path) unless $LOAD_PATH.include?(gem_lib_path) diff --git a/lib/solargraph/language_server/message/text_document/formatting.rb b/lib/solargraph/language_server/message/text_document/formatting.rb index 15117e0f4..036375ccd 100644 --- a/lib/solargraph/language_server/message/text_document/formatting.rb +++ b/lib/solargraph/language_server/message/text_document/formatting.rb @@ -34,6 +34,7 @@ def process private # @param corrections [String] + # @return [void] def log_corrections(corrections) corrections = corrections&.strip return if corrections&.empty? @@ -45,6 +46,8 @@ def log_corrections(corrections) end end + # @param file_uri [String] + # @return [Hash{String => undefined}] def config_for(file_uri) conf = host.formatter_config(file_uri) return {} unless conf.is_a?(Hash) @@ -52,7 +55,9 @@ def config_for(file_uri) conf['rubocop'] || {} end + # @param file_uri [String] # @param config [Hash{String => String}] + # @return [Array] def cli_args file_uri, config file = UriHelpers.uri_to_file(file_uri) args = [ @@ -71,6 +76,8 @@ def cli_args file_uri, config end # @param config [Hash{String => String}] + # @sg-ignore + # @return [Class] def formatter_class(config) if self.class.const_defined?('BlankRubocopFormatter') # @sg-ignore @@ -83,6 +90,7 @@ def formatter_class(config) end # @param value [Array, String] + # @return [String] def cop_list(value) value = value.join(',') if value.respond_to?(:join) return nil if value == '' || !value.is_a?(String) diff --git a/lib/solargraph/page.rb b/lib/solargraph/page.rb index 99b9e8f6d..34ae12fb0 100644 --- a/lib/solargraph/page.rb +++ b/lib/solargraph/page.rb @@ -27,8 +27,10 @@ def initialize locals, render_method end # @param text [String] + # @sg-ignore # @return [String] def htmlify text + # @type [String] YARD::Templates::Helpers::Markup::RDocMarkup.new(text).to_html end @@ -70,8 +72,10 @@ def initialize directory = VIEWS_PATH # @param template [String] # @param layout [Boolean] # @param locals [Hash] + # @sg-ignore # @return [String] def render template, layout: true, locals: {} + # @type [String] @render_method.call(template, layout: layout, locals: locals) end diff --git a/lib/solargraph/parser/flow_sensitive_typing.rb b/lib/solargraph/parser/flow_sensitive_typing.rb index 8fb26d498..33b295667 100644 --- a/lib/solargraph/parser/flow_sensitive_typing.rb +++ b/lib/solargraph/parser/flow_sensitive_typing.rb @@ -10,6 +10,7 @@ def initialize(locals, enclosing_breakable_pin = nil) end # @param and_node [Parser::AST::Node] + # @param true_ranges [Array] def process_and(and_node, true_ranges = []) lhs = and_node.children[0] rhs = and_node.children[1] diff --git a/lib/solargraph/source/chain/link.rb b/lib/solargraph/source/chain/link.rb index d5d63b025..716a55927 100644 --- a/lib/solargraph/source/chain/link.rb +++ b/lib/solargraph/source/chain/link.rb @@ -39,6 +39,7 @@ def resolve api_map, name_pin, locals end # debugging description of contents; not for machine use + # @return [String] def desc word end diff --git a/lib/solargraph/workspace.rb b/lib/solargraph/workspace.rb index aabadd333..ffd653d96 100644 --- a/lib/solargraph/workspace.rb +++ b/lib/solargraph/workspace.rb @@ -133,6 +133,7 @@ def rbs_collection_path @gem_rbs_collection ||= read_rbs_collection_path end + # @return [String, nil] def rbs_collection_config_path @rbs_collection_config_path ||= begin unless directory.empty? || directory == '*' From ac27324add971bf7f3ae5b22f57aa8d84813f03d Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sat, 12 Jul 2025 11:14:28 -0400 Subject: [PATCH 05/10] Linting fixes --- lib/solargraph/gem_pins.rb | 1 - lib/solargraph/pin/base.rb | 4 ++-- lib/solargraph/pin/common.rb | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/solargraph/gem_pins.rb b/lib/solargraph/gem_pins.rb index b92cbd6af..89927d41e 100644 --- a/lib/solargraph/gem_pins.rb +++ b/lib/solargraph/gem_pins.rb @@ -21,7 +21,6 @@ def self.build_yard_pins(gemspec) # @param pins [Array] def self.combine_method_pins_by_path(pins) - # bad_pins = pins.select { |pin| pin.is_a?(Pin::Method) && pin.path == 'StringIO.open' && pin.source == :rbs }; raise "wtf: #{bad_pins}" if bad_pins.length > 1 method_pins, alias_pins = pins.partition { |pin| pin.class == Pin::Method } by_path = method_pins.group_by(&:path) by_path.transform_values! do |pins| diff --git a/lib/solargraph/pin/base.rb b/lib/solargraph/pin/base.rb index 49e066b2c..15b145aee 100644 --- a/lib/solargraph/pin/base.rb +++ b/lib/solargraph/pin/base.rb @@ -13,10 +13,10 @@ class Base # @return [YARD::CodeObjects::Base] attr_reader :code_object - # @return [Solargraph::Location] + # @return [Solargraph::Location, nil] attr_reader :location - # @return [Solargraph::Location] + # @return [Solargraph::Location, nil] attr_reader :type_location # @return [String] diff --git a/lib/solargraph/pin/common.rb b/lib/solargraph/pin/common.rb index 6d9260abd..829dbe496 100644 --- a/lib/solargraph/pin/common.rb +++ b/lib/solargraph/pin/common.rb @@ -7,8 +7,6 @@ module Common attr_reader :location # @return [Pin::Closure, nil] - attr_reader :closure - def closure Solargraph.assert_or_log(:closure, "Closure not set on #{self.class} #{name.inspect} from #{source.inspect}") unless @closure @closure From 4196b1636924214efbf8998be9deb59cda511fc9 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sat, 12 Jul 2025 11:45:56 -0400 Subject: [PATCH 06/10] Linting fixes --- lib/solargraph/api_map/index.rb | 3 +++ .../parser/flow_sensitive_typing.rb | 25 ++++++++++++++++++- lib/solargraph/source/chain/link.rb | 3 ++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/solargraph/api_map/index.rb b/lib/solargraph/api_map/index.rb index 990fc7169..ea358297e 100644 --- a/lib/solargraph/api_map/index.rb +++ b/lib/solargraph/api_map/index.rb @@ -63,6 +63,7 @@ def superclass_references end # @param pins [Array] + # @return [self] def merge pins deep_clone.catalog pins end @@ -72,6 +73,7 @@ def merge pins attr_writer :pins, :pin_select_cache, :namespace_hash, :pin_class_hash, :path_pin_hash, :include_references, :extend_references, :prepend_references, :superclass_references + # @return [self] def deep_clone Index.allocate.tap do |copy| copy.pin_select_cache = {} @@ -87,6 +89,7 @@ def deep_clone end # @param new_pins [Array] + # @return [self] def catalog new_pins @pin_select_cache = {} pins.concat new_pins diff --git a/lib/solargraph/parser/flow_sensitive_typing.rb b/lib/solargraph/parser/flow_sensitive_typing.rb index 33b295667..58f149d73 100644 --- a/lib/solargraph/parser/flow_sensitive_typing.rb +++ b/lib/solargraph/parser/flow_sensitive_typing.rb @@ -4,6 +4,7 @@ class FlowSensitiveTyping include Solargraph::Parser::NodeMethods # @param locals [Array] + # @param enclosing_breakable_pin [Solargraph::Pin::Breakable, nil] def initialize(locals, enclosing_breakable_pin = nil) @locals = locals @enclosing_breakable_pin = enclosing_breakable_pin @@ -11,6 +12,8 @@ def initialize(locals, enclosing_breakable_pin = nil) # @param and_node [Parser::AST::Node] # @param true_ranges [Array] + # + # @return [void] def process_and(and_node, true_ranges = []) lhs = and_node.children[0] rhs = and_node.children[1] @@ -24,6 +27,8 @@ def process_and(and_node, true_ranges = []) end # @param if_node [Parser::AST::Node] + # + # @return [void] def process_if(if_node) # # See if we can refine a type based on the result of 'if foo.nil?' @@ -73,8 +78,11 @@ class << self # them based on the Closure and Location. # # @param pins [Array] + # @param name [String] # @param closure [Pin::Closure] # @param location [Location] + # + # @return [Array] def self.visible_pins(pins, name, closure, location) logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location})" } pins_with_name = pins.select { |p| p.name == name } @@ -108,7 +116,10 @@ def self.visible_pins(pins, name, closure, location) private # @param pin [Pin::LocalVariable] - # @param if_node [Parser::AST::Node] + # @param downcast_type_name [String] + # @param presence [Range] + # + # @return [void] def add_downcast_local(pin, downcast_type_name, presence) # @todo Create pin#update method new_pin = Solargraph::Pin::LocalVariable.new( @@ -127,6 +138,7 @@ def add_downcast_local(pin, downcast_type_name, presence) # @param facts_by_pin [Hash{Pin::LocalVariable => Array String}>}] # @param presences [Array] + # # @return [void] def process_facts(facts_by_pin, presences) # @@ -143,6 +155,7 @@ def process_facts(facts_by_pin, presences) end # @param conditional_node [Parser::AST::Node] + # @param true_ranges [Array] def process_conditional(conditional_node, true_ranges) if conditional_node.type == :send process_isa(conditional_node, true_ranges) @@ -177,12 +190,20 @@ def parse_isa(isa_node) [isa_type_name, variable_name] end + # @param variable_name [String] + # @param position [Position] + # + # @return [Solargraph::Pin::LocalVariable, nil] def find_local(variable_name, position) pins = locals.select { |pin| pin.name == variable_name && pin.presence.include?(position) } return unless pins.length == 1 pins.first end + # @param isa_node [Parser::AST::Node] + # @param true_presences [Array] + # + # @return [void] def process_isa(isa_node, true_presences) isa_type_name, variable_name = parse_isa(isa_node) return if variable_name.nil? || variable_name.empty? @@ -198,6 +219,8 @@ def process_isa(isa_node, true_presences) end # @param node [Parser::AST::Node] + # + # @return [String, nil] def type_name(node) # e.g., # s(:const, nil, :Baz) diff --git a/lib/solargraph/source/chain/link.rb b/lib/solargraph/source/chain/link.rb index 716a55927..36a8d4e86 100644 --- a/lib/solargraph/source/chain/link.rb +++ b/lib/solargraph/source/chain/link.rb @@ -17,7 +17,6 @@ def initialize word = '' @word = word end - # @sg-ignore Fix "Not enough arguments to Module#protected" protected def equality_fields [self.class, word] end @@ -75,6 +74,8 @@ def nullable? end # debugging description of contents; not for machine use + # + # @return [String] def desc word end From a439ebfd7bd234f8cc69b2baf296e3e7da1f7972 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sat, 12 Jul 2025 12:51:17 -0400 Subject: [PATCH 07/10] Restore @sg-ignore --- lib/solargraph/source/chain/link.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/solargraph/source/chain/link.rb b/lib/solargraph/source/chain/link.rb index 36a8d4e86..bcd9eb196 100644 --- a/lib/solargraph/source/chain/link.rb +++ b/lib/solargraph/source/chain/link.rb @@ -17,6 +17,13 @@ def initialize word = '' @word = word end + # @sg-ignore two problems - Declared return type + # ::Solargraph::Source::Chain::Array does not match inferred + # type ::Array(::Class<::Solargraph::Source::Chain::Link>, + # ::String) for + # Solargraph::Source::Chain::Link#equality_fields + # and + # Not enough arguments to Module#protected protected def equality_fields [self.class, word] end From a87f81d5817ea230e16ad1260769d0c20049ec21 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Mon, 14 Jul 2025 07:26:22 -0400 Subject: [PATCH 08/10] RuboCop and Solargraph fixes --- lib/solargraph/convention/data_definition.rb | 1 + .../convention/struct_definition.rb | 9 ++++---- spec/convention/struct_definition_spec.rb | 23 +++++++++---------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/lib/solargraph/convention/data_definition.rb b/lib/solargraph/convention/data_definition.rb index 0816d3c90..b65431393 100644 --- a/lib/solargraph/convention/data_definition.rb +++ b/lib/solargraph/convention/data_definition.rb @@ -88,6 +88,7 @@ def data_definition_node end # @param attribute_node [Parser::AST::Node] + # @param attribute_name [String] # @return [String, nil] def attribute_comments(attribute_node, attribute_name) data_comments = comments_for(attribute_node) diff --git a/lib/solargraph/convention/struct_definition.rb b/lib/solargraph/convention/struct_definition.rb index bc3adeada..d7766e37a 100644 --- a/lib/solargraph/convention/struct_definition.rb +++ b/lib/solargraph/convention/struct_definition.rb @@ -73,9 +73,9 @@ def process ) pins.push Pin::InstanceVariable.new(name: "@#{attribute_name}", - closure: method_pin, - location: get_node_location(attribute_node), - comments: attribute_comment(docs, false)) + closure: method_pin, + location: get_node_location(attribute_node), + comments: attribute_comment(docs, false)) end pins.push method_pin @@ -113,7 +113,7 @@ def parse_comments # We should support specific comments for an attribute, and that can be either a @return on an @param # But since we merge into the struct_comments, then we should interpret either as a param - comment = '@param ' + attr_name + comment[7..] if comment.start_with?('@return') + comment = "@param #{attr_name}#{comment[7..]}" if comment.start_with?('@return') struct_comments += "\n#{comment}" end @@ -123,6 +123,7 @@ def parse_comments # @param tag [YARD::Tags::Tag, nil] The param tag for this attribute. If nil, this method is a no-op # @param for_setter [Boolean] If true, will return a @param tag instead of a @return tag + # @return [String] The formatted comment for the attribute def attribute_comment(tag, for_setter) return "" if tag.nil? diff --git a/spec/convention/struct_definition_spec.rb b/spec/convention/struct_definition_spec.rb index a62f18d7a..ab786dcd3 100644 --- a/spec/convention/struct_definition_spec.rb +++ b/spec/convention/struct_definition_spec.rb @@ -1,6 +1,6 @@ describe Solargraph::Convention::StructDefinition do describe 'parsing docs' do - it 'should support keyword args' do + it 'supports keyword args' do source = Solargraph::SourceMap.load_string(%( # @param bar [String] # @param baz [Integer] @@ -21,7 +21,7 @@ expect(param_baz.return_type.tag).to eql('Integer') end - it 'should support positional args' do + it 'supports positional args' do source = Solargraph::SourceMap.load_string(%( # @param bar [String] # @param baz [Integer] @@ -36,8 +36,7 @@ expect(params.map(&:return_type).map(&:tag)).to eql(%w[String Integer]) end - - it 'should support positional args if keyword_init: false' do + it 'supports positional args if keyword_init: false' do source = Solargraph::SourceMap.load_string(%( # @param bar [String] # @param baz [Integer] @@ -52,7 +51,7 @@ expect(params.map(&:return_type).map(&:tag)).to eql(%w[String Integer]) end - it 'should support comments on args' do + it 'supports comments on args' do source = Solargraph::SourceMap.load_string(%( Foo = Struct.new( # @return [String] @@ -71,7 +70,7 @@ expect(params[1].documentation).to eql("Some text (also with arg name: baz)\nExtra indented text :3") end - it 'should merge struct level comments and attribute level comments' do + it 'merges struct level comments and attribute level comments' do # Note on repetitions: Imo this should stay undefined # So if there'd be a @return statement on the bar attribute, I'd not sweat it @@ -93,7 +92,7 @@ end [true, false].each do |kw_args| - it "should properly support assignment with #{kw_args ? 'keyword' : 'positional'} arg mode" do + it "supports assignment with #{kw_args ? 'keyword' : 'positional'} arg mode" do # Both positional & kwargs init mode should act the same for assignment source = Solargraph::SourceMap.load_string(%( @@ -101,17 +100,17 @@ # @param baz [Integer] Foo = Struct.new(:bar, :baz, keyword_init: #{kw_args}) ), 'test.rb') - + params_bar = source.pins.find { |p| p.path == "Foo#bar=" }.parameters - expect(params_bar.length).to eql(1) + expect(params_bar.length).to be(1) expect(params_bar.first.return_type.tag).to eql("String") expect(params_bar.first.arg?).to be(true) - + params_baz = source.pins.find { |p| p.path == "Foo#baz=" }.parameters - expect(params_baz.length).to eql(1) + expect(params_baz.length).to be(1) expect(params_baz.first.return_type.tag).to eql("Integer") expect(params_baz.first.arg?).to be(true) end end end -end \ No newline at end of file +end From 947bdfe013a3b17a87d853163f0ae865371d4d84 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 3 Aug 2025 20:42:56 -0400 Subject: [PATCH 09/10] More fixes --- lib/solargraph/convention/data_definition.rb | 2 +- lib/solargraph/pin/constant.rb | 2 ++ lib/solargraph/pin/method_alias.rb | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/solargraph/convention/data_definition.rb b/lib/solargraph/convention/data_definition.rb index b65431393..8efe27932 100644 --- a/lib/solargraph/convention/data_definition.rb +++ b/lib/solargraph/convention/data_definition.rb @@ -35,7 +35,7 @@ def process comments: comments_for(node) ) - # TODO: Support both arg and kwarg initializers for Data.define + # @todo Support both arg and kwarg initializers for Data.define # Solargraph::SourceMap::Clip#complete_keyword_parameters does not seem to currently take into account [Pin::Method#signatures] hence we only one for :kwarg pins.push initialize_method_pin diff --git a/lib/solargraph/pin/constant.rb b/lib/solargraph/pin/constant.rb index 345bbd50a..94a968e7e 100644 --- a/lib/solargraph/pin/constant.rb +++ b/lib/solargraph/pin/constant.rb @@ -5,6 +5,8 @@ module Pin class Constant < BaseVariable attr_reader :visibility + # @param visibility [::Symbol] The visibility of the constant (:public, :protected, or :private) + # @param splat [Hash] Additional options supported by superclasses def initialize visibility: :public, **splat super(**splat) @visibility = visibility diff --git a/lib/solargraph/pin/method_alias.rb b/lib/solargraph/pin/method_alias.rb index 8636169a8..28be6d8b1 100644 --- a/lib/solargraph/pin/method_alias.rb +++ b/lib/solargraph/pin/method_alias.rb @@ -13,6 +13,9 @@ class MethodAlias < Method # @return [String] attr_reader :original + # @param scope [::Symbol] + # @param original [String, nil] The name of the original method + # @param splat [Hash] Additional options supported by superclasses def initialize scope: :instance, original: nil, **splat super(**splat) @scope = scope From 6ef82c1b78e6cd50c9a87d7e4a42387c06e2efce Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Mon, 4 Aug 2025 10:46:55 -0400 Subject: [PATCH 10/10] Rubocop fix, add spec --- lib/solargraph/api_map/source_to_yard.rb | 8 ++++++-- spec/api_map/source_to_yard_spec.rb | 21 +++++++++++++++++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/solargraph/api_map/source_to_yard.rb b/lib/solargraph/api_map/source_to_yard.rb index 5e7784f01..5f64d9bad 100644 --- a/lib/solargraph/api_map/source_to_yard.rb +++ b/lib/solargraph/api_map/source_to_yard.rb @@ -49,8 +49,12 @@ def rake_yard store end store.get_extends(pin.path).each do |ref| extend_object = code_object_at(pin.path, YARD::CodeObjects::ClassObject) - extend_object.instance_mixins.push code_object_map[ref] unless extend_object.nil? or extend_object.nil? - extend_object.class_mixins.push code_object_map[ref] unless extend_object.nil? or extend_object.nil? + next unless extend_object + code_object = code_object_map[ref] + next unless code_object + extend_object.class_mixins.push code_object + # @todo add spec showing why this next line is necessary + extend_object.instance_mixins.push code_object end end store.method_pins.each do |pin| diff --git a/spec/api_map/source_to_yard_spec.rb b/spec/api_map/source_to_yard_spec.rb index 477c60c0e..78758b710 100644 --- a/spec/api_map/source_to_yard_spec.rb +++ b/spec/api_map/source_to_yard_spec.rb @@ -40,7 +40,7 @@ def self.baz expect(class_method_object.tag(:return).types).to eq(['Foo']) end - it "generates mixins" do + it "generates instance mixins" do source = Solargraph::SourceMap.load_string(%( module Foo def bar @@ -55,7 +55,24 @@ class Baz object.rake_yard Solargraph::ApiMap::Store.new(source.pins) module_object = object.code_object_at('Foo') class_object = object.code_object_at('Baz') - expect(class_object.mixins).to include(module_object) + expect(class_object.instance_mixins).to include(module_object) + end + + it "generates class mixins" do + source = Solargraph::SourceMap.load_string(%( + module Foo + def bar; end + end + class Baz + extend Foo + end + )) + object = Object.new + object.extend Solargraph::ApiMap::SourceToYard + object.rake_yard Solargraph::ApiMap::Store.new(source.pins) + module_object = object.code_object_at('Foo') + class_object = object.code_object_at('Baz') + expect(class_object.class_mixins).to include(module_object) end it "generates methods for attributes" do