You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

solargraph

Package Overview
Dependencies
Maintainers
1
Versions
211
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

solargraph - rubygems Package Compare versions

Comparing version
0.56.1
to
0.56.2
+104
lib/solargraph/convention/data_definition.rb
# frozen_string_literal: true
module Solargraph
module Convention
module DataDefinition
autoload :DataDefintionNode, 'solargraph/convention/data_definition/data_definition_node'
autoload :DataAssignmentNode, 'solargraph/convention/data_definition/data_assignment_node'
module NodeProcessors
class DataNode < Parser::NodeProcessor::Base
# @return [Boolean] continue processing the next processor of the same node.
def process
return true if data_definition_node.nil?
loc = get_node_location(node)
nspin = Solargraph::Pin::Namespace.new(
type: :class,
location: loc,
closure: region.closure,
name: data_definition_node.class_name,
comments: comments_for(node),
visibility: :public,
gates: region.closure.gates.freeze
)
pins.push nspin
# define initialize method
initialize_method_pin = Pin::Method.new(
name: 'initialize',
parameters: [],
scope: :instance,
location: get_node_location(node),
closure: nspin,
visibility: :private,
comments: comments_for(node)
)
# 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
data_definition_node.attributes.map do |attribute_node, attribute_name|
initialize_method_pin.parameters.push(
Pin::Parameter.new(
name: attribute_name,
decl: :kwarg,
location: get_node_location(attribute_node),
closure: initialize_method_pin
)
)
end
# define attribute readers and instance variables
data_definition_node.attributes.each do |attribute_node, attribute_name|
name = attribute_name.to_s
method_pin = Pin::Method.new(
name: name,
parameters: [],
scope: :instance,
location: get_node_location(attribute_node),
closure: nspin,
comments: attribute_comments(attribute_node, attribute_name),
visibility: :public
)
pins.push method_pin
pins.push Pin::InstanceVariable.new(name: "@#{attribute_name}",
closure: method_pin,
location: get_node_location(attribute_node),
comments: attribute_comments(attribute_node, attribute_name))
end
process_children region.update(closure: nspin, visibility: :public)
false
end
private
# @return [DataDefintionNode, nil]
def data_definition_node
@data_definition_node ||= if DataDefintionNode.match?(node)
DataDefintionNode.new(node)
elsif DataAssignmentNode.match?(node)
DataAssignmentNode.new(node)
end
end
# @param attribute_node [Parser::AST::Node]
# @return [String, nil]
def attribute_comments(attribute_node, attribute_name)
data_comments = comments_for(attribute_node)
return if data_comments.nil? || data_comments.empty?
data_comments.split("\n").find do |row|
row.include?(attribute_name)
end&.gsub('@param', '@return')&.gsub(attribute_name, '')
end
end
end
end
end
end
# frozen_string_literal: true
module Solargraph
module Convention
module DataDefinition
# A node wrapper for a Data definition via const assignment.
# @example
# MyData = Data.new(:bar, :baz) do
# def foo
# end
# end
class DataAssignmentNode < DataDefintionNode
class << self
# @example
# s(:casgn, nil, :Foo,
# s(:block,
# s(:send,
# s(:const, nil, :Data), :define,
# s(:sym, :bar),
# s(:sym, :baz)),
# s(:args),
# s(:def, :foo,
# s(:args),
# s(:send, nil, :bar))))
def match?(node)
return false unless node&.type == :casgn
return false if node.children[2].nil?
data_node = if node.children[2].type == :block
node.children[2].children[0]
else
node.children[2]
end
data_definition_node?(data_node)
end
end
def class_name
if node.children[0]
Parser::NodeMethods.unpack_name(node.children[0]) + "::#{node.children[1]}"
else
node.children[1].to_s
end
end
private
# @return [Parser::AST::Node]
def data_node
if node.children[2].type == :block
node.children[2].children[0]
else
node.children[2]
end
end
end
end
end
end
# frozen_string_literal: true
module Solargraph
module Convention
module DataDefinition
# A node wrapper for a Data definition via inheritance.
# @example
# class MyData < Data.new(:bar, :baz)
# def foo
# end
# end
class DataDefintionNode
class << self
# @example
# s(:class,
# s(:const, nil, :Foo),
# s(:send,
# s(:const, nil, :Data), :define,
# s(:sym, :bar),
# s(:sym, :baz)),
# s(:hash,
# s(:pair,
# s(:sym, :keyword_init),
# s(:true)))),
# s(:def, :foo,
# s(:args),
# s(:send, nil, :bar)))
def match?(node)
return false unless node&.type == :class
data_definition_node?(node.children[1])
end
private
# @param data_node [Parser::AST::Node]
# @return [Boolean]
def data_definition_node?(data_node)
return false unless data_node.is_a?(::Parser::AST::Node)
return false unless data_node&.type == :send
return false unless data_node.children[0]&.type == :const
return false unless data_node.children[0].children[1] == :Data
return false unless data_node.children[1] == :define
true
end
end
# @return [Parser::AST::Node]
def initialize(node)
@node = node
end
# @return [String]
def class_name
Parser::NodeMethods.unpack_name(node)
end
# @return [Array<Array(Parser::AST::Node, String)>]
def attributes
data_attribute_nodes.map do |data_def_param|
next unless data_def_param.type == :sym
[data_def_param, data_def_param.children[0].to_s]
end.compact
end
# @return [Parser::AST::Node]
def body_node
node.children[2]
end
private
# @return [Parser::AST::Node]
attr_reader :node
# @return [Parser::AST::Node]
def data_node
node.children[1]
end
# @return [Array<Parser::AST::Node>]
def data_attribute_nodes
data_node.children[2..-1]
end
end
end
end
end
+8
-0

@@ -0,1 +1,9 @@

## 0.56.2 - July 29, 2025
- Add support for Ruby Data.define (#970)
- Ensure that pin locations are always populated (#965)
- Improve struct support (#992)
- Include Rakefile, Gemfile, and gemspec files in config by default (#984)
- Use Open3 to cache gemspecs (#1000)
- Eager load node processors (#1002)
## 0.56.1 - July 13, 2025

@@ -2,0 +10,0 @@ - Library avoids blocking on pending yardoc caches (#990)

@@ -68,2 +68,6 @@ # frozen_string_literal: true

# @param type [Symbol] The type of assertion to perform.
# @param msg [String, nil] An optional message to log
# @param block [Proc] A block that returns a message to log
# @return [void]
def self.assert_or_log(type, msg = nil, &block)

@@ -83,2 +87,7 @@ raise (msg || block.call) if asserts_on?(type) && ![:combine_with_visibility].include?(type)

# Bundler.with_clean_env for earlier versions of Bundler.
#
# @generic T
# @yieldreturn [generic<T>]
# @sg-ignore dynamic call, but both functions behave the same
# @return [generic<T>]
def self.with_clean_env &block

@@ -93,1 +102,5 @@ meth = if Bundler.respond_to?(:with_original_env)

end
# Ensure that ParserGem node processors are properly loaded to avoid conflicts
# with Convention node processors
require 'solargraph/parser/parser_gem/node_processors'
+1
-0

@@ -14,2 +14,3 @@ # frozen_string_literal: true

autoload :StructDefinition, 'solargraph/convention/struct_definition'
autoload :DataDefinition, 'solargraph/convention/data_definition'

@@ -16,0 +17,0 @@ # @type [Set<Convention::Base>]

+2
-1

@@ -15,3 +15,4 @@ # frozen_string_literal: true

@yieldparam [self]
)
),
source: :gemspec
)

@@ -18,0 +19,0 @@ ]

@@ -11,4 +11,5 @@ # frozen_string_literal: true

class StructNode < Parser::NodeProcessor::Base
# @return [Boolean] continue processing the next processor of the same node.
def process
return if struct_definition_node.nil?
return true if struct_definition_node.nil?

@@ -21,3 +22,3 @@ loc = get_node_location(node)

name: struct_definition_node.class_name,
comments: comments_for(node),
docstring: docstring,
visibility: :public,

@@ -36,3 +37,3 @@ gates: region.closure.gates.freeze

visibility: :private,
comments: comments_for(node)
docstring: docstring
)

@@ -56,2 +57,4 @@

[attribute_name, "#{attribute_name}="].each do |name|
docs = docstring.tags.find { |t| t.tag_name == 'param' && t.name == attribute_name }
method_pin = Pin::Method.new(

@@ -63,13 +66,22 @@ name: name,

closure: nspin,
comments: attribute_comments(attribute_node, attribute_name),
# even assignments return the value
comments: attribute_comment(docs, false),
visibility: :public
)
if name.end_with?('=')
method_pin.parameters << Pin::Parameter.new(
name: attribute_name,
location: get_node_location(attribute_node),
closure: nspin,
comments: attribute_comment(docs, true)
)
pins.push Pin::InstanceVariable.new(name: "@#{attribute_name}",
closure: method_pin,
location: get_node_location(attribute_node),
comments: attribute_comment(docs, false))
end
pins.push method_pin
next unless name.include?('=') # setter
pins.push Pin::InstanceVariable.new(name: "@#{attribute_name}",
closure: method_pin,
location: get_node_location(attribute_node),
comments: attribute_comments(attribute_node, attribute_name))
end

@@ -79,2 +91,3 @@ end

process_children region.update(closure: nspin, visibility: :public)
false
end

@@ -86,5 +99,5 @@

def struct_definition_node
@struct_definition_node ||= if StructDefintionNode.valid?(node)
@struct_definition_node ||= if StructDefintionNode.match?(node)
StructDefintionNode.new(node)
elsif StructAssignmentNode.valid?(node)
elsif StructAssignmentNode.match?(node)
StructAssignmentNode.new(node)

@@ -94,12 +107,39 @@ end

# @param attribute_node [Parser::AST::Node]
# @return [String, nil]
def attribute_comments(attribute_node, attribute_name)
struct_comments = comments_for(attribute_node)
return if struct_comments.nil? || struct_comments.empty?
# Gets/generates the relevant docstring for this struct & it's attributes
# @return [YARD::Docstring]
def docstring
@docstring ||= parse_comments
end
struct_comments.split("\n").find do |row|
row.include?(attribute_name)
end&.gsub('@param', '@return')&.gsub(attribute_name, '')
# Parses any relevant comments for a struct int a yard docstring
# @return [YARD::Docstring]
def parse_comments
struct_comments = comments_for(node) || ''
struct_definition_node.attributes.each do |attr_node, attr_name|
comment = comments_for(attr_node)
next if comment.nil?
# 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')
struct_comments += "\n#{comment}"
end
Solargraph::Source.parse_docstring(struct_comments).to_docstring
end
# @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
def attribute_comment(tag, for_setter)
return "" if tag.nil?
suffix = "[#{tag.types&.join(',') || 'undefined'}] #{tag.text}"
if for_setter
"@param #{tag.name} #{suffix}"
else
"@return #{suffix}"
end
end
end

@@ -106,0 +146,0 @@ end

@@ -25,3 +25,3 @@ # frozen_string_literal: true

# s(:send, nil, :bar))))
def valid?(node)
def match?(node)
return false unless node&.type == :casgn

@@ -28,0 +28,0 @@ return false if node.children[2].nil?

@@ -28,3 +28,3 @@ # frozen_string_literal: true

# s(:send, nil, :bar)))
def valid?(node)
def match?(node)
return false unless node&.type == :class

@@ -31,0 +31,0 @@

@@ -5,2 +5,3 @@ # frozen_string_literal: true

require 'observer'
require 'open3'

@@ -608,12 +609,11 @@ module Solargraph

Thread.new do
cache_pid = Process.spawn(workspace.command_path, 'cache', spec.name, spec.version.to_s)
report_cache_progress spec.name, pending
Process.wait(cache_pid)
logger.info "Cached #{spec.name} #{spec.version}"
rescue Errno::EINVAL => _e
logger.info "Cached #{spec.name} #{spec.version} with EINVAL"
rescue StandardError => e
cache_errors.add spec
Solargraph.logger.warn "Error caching gemspec #{spec.name} #{spec.version}: [#{e.class}] #{e.message}"
ensure
_o, e, s = Open3.capture3(workspace.command_path, 'cache', spec.name, spec.version.to_s)
if s.success?
logger.info "Cached #{spec.name} #{spec.version}"
else
cache_errors.add spec
logger.warn "Error caching gemspec #{spec.name} #{spec.version}"
logger.warn e
end
end_cache_progress

@@ -620,0 +620,0 @@ catalog

@@ -12,6 +12,7 @@ # frozen_string_literal: true

class << self
# @type [Hash{Symbol => Class<NodeProcessor::Base>}]
# @type [Hash<Symbol, Array<Class<NodeProcessor::Base>>>]
@@processors ||= {}
# Register a processor for a node type.
# Register a processor for a node type. You can register multiple processors for the same type.
# If a node processor returns true, it will skip the next processor of the same node type.
#

@@ -22,4 +23,9 @@ # @param type [Symbol]

def register type, cls
@@processors[type] = cls
@@processors[type] ||= []
@@processors[type] << cls
end
def deregister type, cls
@@processors[type].delete(cls)
end
end

@@ -41,6 +47,12 @@

return [pins, locals] unless Parser.is_ast_node?(node)
klass = @@processors[node.type] || NodeProcessor::Base
processor = klass.new(node, region, pins, locals)
processor.process
[processor.pins, processor.locals]
node_processor_classes = @@processors[node.type] || [NodeProcessor::Base]
node_processor_classes.each do |klass|
processor = klass.new(node, region, pins, locals)
process_next = processor.process
break unless process_next
end
[pins, locals]
end

@@ -47,0 +59,0 @@ end

@@ -33,5 +33,8 @@ # frozen_string_literal: true

#
# @return [void]
# @return [Boolean] continue processing the next processor of the same node type.
# @return [void] In case there is only one processor registered for the node type, it can be void.
def process
process_children
true
end

@@ -68,3 +71,5 @@

def named_path_pin position
pins.select{|pin| pin.is_a?(Pin::Closure) && pin.path && !pin.path.empty? && pin.location.range.contain?(position)}.last
pins.select do |pin|
pin.is_a?(Pin::Closure) && pin.path && !pin.path.empty? && pin.location.range.contain?(position)
end.last
end

@@ -77,3 +82,3 @@

# @todo determine if this can return a Pin::Block
pins.select{|pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position)}.last
pins.select { |pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position) }.last
end

@@ -85,3 +90,3 @@

def closure_pin position
pins.select{|pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position)}.last
pins.select { |pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position) }.last
end

@@ -88,0 +93,0 @@ end

@@ -45,2 +45,4 @@ # frozen_string_literal: true

register :send, ParserGem::NodeProcessors::SendNode
register :class, Convention::StructDefinition::NodeProcessors::StructNode
register :class, Convention::DataDefinition::NodeProcessors::DataNode
register :class, ParserGem::NodeProcessors::NamespaceNode

@@ -53,2 +55,4 @@ register :module, ParserGem::NodeProcessors::NamespaceNode

register :gvasgn, ParserGem::NodeProcessors::GvasgnNode
register :casgn, Convention::StructDefinition::NodeProcessors::StructNode
register :casgn, Convention::DataDefinition::NodeProcessors::DataNode
register :casgn, ParserGem::NodeProcessors::CasgnNode

@@ -55,0 +59,0 @@ register :masgn, ParserGem::NodeProcessors::MasgnNode

@@ -11,13 +11,2 @@ # frozen_string_literal: true

def process
if Convention::StructDefinition::StructAssignmentNode.valid?(node)
process_struct_assignment
else
process_constant_assignment
end
end
private
# @return [void]
def process_constant_assignment
pins.push Solargraph::Pin::Constant.new(

@@ -34,13 +23,4 @@ location: get_node_location(node),

# @todo Move this out of [CasgnNode] once [Solargraph::Parser::NodeProcessor] supports
# multiple processors.
def process_struct_assignment
processor_klass = Convention::StructDefinition::NodeProcessors::StructNode
processor = processor_klass.new(node, region, pins, locals)
processor.process
private
@pins = processor.pins
@locals = processor.locals
end
# @return [String]

@@ -47,0 +27,0 @@ def const_name

@@ -10,2 +10,3 @@ # frozen_string_literal: true

# @return [void]
def process

@@ -44,3 +45,5 @@ # Example:

if pin.nil?
Solargraph.logger.debug { "Could not find local for masgn= value in location #{location.inspect} in #{lhs_arr} - masgn = #{masgn}, lhs.type = #{lhs.type}" }
Solargraph.logger.debug do
"Could not find local for masgn= value in location #{location.inspect} in #{lhs_arr} - masgn = #{masgn}, lhs.type = #{lhs.type}"
end
next

@@ -47,0 +50,0 @@ end

@@ -14,13 +14,2 @@ # frozen_string_literal: true

if Convention::StructDefinition::StructDefintionNode.valid?(node)
process_struct_definition
else
process_namespace(superclass_name)
end
end
private
# @param superclass_name [String, nil]
def process_namespace(superclass_name)
loc = get_node_location(node)

@@ -48,13 +37,2 @@ nspin = Solargraph::Pin::Namespace.new(

end
# @todo Move this out of [NamespaceNode] once [Solargraph::Parser::NodeProcessor] supports
# multiple processors.
def process_struct_definition
processor_klass = Convention::StructDefinition::NodeProcessors::StructNode
processor = processor_klass.new(node, region, pins, locals)
processor.process
@pins = processor.pins
@locals = processor.locals
end
end

@@ -61,0 +39,0 @@ end

@@ -10,2 +10,3 @@ # frozen_string_literal: true

class OpasgnNode < Parser::NodeProcessor::Base
# @return [void]
def process

@@ -12,0 +13,0 @@ # Parser::CurrentRuby.parse("a += 2")

@@ -8,2 +8,3 @@ # frozen_string_literal: true

class OrasgnNode < Parser::NodeProcessor::Base
# @return [void]
def process

@@ -10,0 +11,0 @@ new_node = node.updated(node.children[0].type, node.children[0].children + [node.children[1]])

@@ -10,2 +10,3 @@ # frozen_string_literal: true

# @return [void]
def process

@@ -12,0 +13,0 @@ if node.children[1] # Exception local variable name

@@ -8,2 +8,3 @@ # frozen_string_literal: true

class SymNode < Parser::NodeProcessor::Base
# @return [void]
def process

@@ -10,0 +11,0 @@ pins.push Solargraph::Pin::Symbol.new(

@@ -54,4 +54,12 @@ # frozen_string_literal: true

assert_source_provided
assert_location_provided
end
# @return [void]
def assert_location_provided
return unless best_location.nil? && %i[yardoc source rbs].include?(source)
Solargraph.assert_or_log(:best_location, "Neither location nor type_location provided - #{path} #{source} #{self.class}")
end
# @param other [self]

@@ -294,2 +302,5 @@ # @param attrs [Hash{Symbol => Object}]

# @param other [self]
# @param attr [::Symbol]
# @return [undefined]
def choose_pin_attr(other, attr)

@@ -309,2 +320,3 @@ # @type [Pin::Base, nil]

# @return [void]
def assert_source_provided

@@ -554,2 +566,3 @@ Solargraph.assert_or_log(:source, "source not provided - #{@path} #{@source} #{self.class}") if source.nil?

# @return [String]
def desc

@@ -564,2 +577,3 @@ "[#{inner_desc}]"

# @return [String]
def all_location_text

@@ -577,2 +591,3 @@ if location.nil? && type_location.nil?

# @return [void]
def reset_generated!

@@ -579,0 +594,0 @@ end

@@ -202,5 +202,7 @@ # frozen_string_literal: true

yield_return_type = ComplexType.try_parse(*yieldreturn_tags.flat_map(&:types))
block = Signature.new(generics: generics, parameters: yield_parameters, return_type: yield_return_type, source: source, closure: self)
block = Signature.new(generics: generics, parameters: yield_parameters, return_type: yield_return_type, source: source,
closure: self, location: location, type_location: type_location)
end
signature = Signature.new(generics: generics, parameters: parameters, return_type: return_type, block: block, closure: self, source: source)
signature = Signature.new(generics: generics, parameters: parameters, return_type: return_type, block: block, closure: self, source: source,
location: location, type_location: type_location)
block.closure = signature if block

@@ -207,0 +209,0 @@ signature

@@ -25,2 +25,3 @@ # frozen_string_literal: true

# @param loader [RBS::EnvironmentLoader]
def initialize(loader:)

@@ -32,2 +33,3 @@ @loader = loader

# @return [RBS::EnvironmentLoader]
attr_reader :loader

@@ -111,3 +113,3 @@

def convert_members_to_pins decl, closure
context = Context.new
context = Conversions::Context.new
decl.members.each { |m| context = convert_member_to_pin(m, closure, context) }

@@ -119,3 +121,3 @@ end

# @param context [Context]
# @return [void]
# @return [Context]
def convert_member_to_pin member, closure, context

@@ -302,2 +304,3 @@ case member

comments: decl.comment&.string,
type_location: location_decl_to_pin_location(decl.location),
source: :rbs

@@ -324,2 +327,3 @@ )

# allow that to be extended via .solargraph.yml
# @type [Hash{Array(String, Symbol, String) => Symbol}
VISIBILITY_OVERRIDE = {

@@ -349,2 +353,9 @@ ["Rails::Engine", :instance, "run_tasks_blocks"] => :protected,

# @param decl [RBS::AST::Members::MethodDefinition, RBS::AST::Members::AttrReader, RBS::AST::Members::AttrAccessor]
# @param closure [Pin::Namespace]
# @param context [Context]
# @param scope [Symbol] :instance or :class
# @param name [String] The name of the method
# @sg-ignore
# @return [Symbol]
def calculate_method_visibility(decl, context, closure, scope, name)

@@ -424,2 +435,3 @@ override_key = [closure.path, scope, name]

decl.overloads.map do |overload|
type_location = location_decl_to_pin_location(overload.method_type.location)
generics = overload.method_type.type_params.map(&:name).map(&:to_s)

@@ -429,7 +441,7 @@ signature_parameters, signature_return_type = parts_of_function(overload.method_type, pin)

block_parameters, block_return_type = parts_of_function(overload.method_type.block, pin)
Pin::Signature.new(generics: generics, parameters: block_parameters, return_type: block_return_type,
closure: pin, source: :rbs)
Pin::Signature.new(generics: generics, parameters: block_parameters, return_type: block_return_type, source: :rbs,
type_location: type_location, closure: pin)
end
Pin::Signature.new(generics: generics, parameters: signature_parameters, return_type: signature_return_type, block: block,
closure: pin, source: :rbs)
Pin::Signature.new(generics: generics, parameters: signature_parameters, return_type: signature_return_type, block: block, source: :rbs,
type_location: type_location, closure: pin)
end

@@ -453,3 +465,9 @@ end

def parts_of_function type, pin
return [[Solargraph::Pin::Parameter.new(decl: :restarg, name: 'arg', closure: pin, source: :rbs)], ComplexType.try_parse(method_type_to_tag(type)).force_rooted] if defined?(RBS::Types::UntypedFunction) && type.type.is_a?(RBS::Types::UntypedFunction)
type_location = pin.type_location
if defined?(RBS::Types::UntypedFunction) && type.type.is_a?(RBS::Types::UntypedFunction)
return [
[Solargraph::Pin::Parameter.new(decl: :restarg, name: 'arg', closure: pin, source: :rbs, type_location: type_location)],
ComplexType.try_parse(method_type_to_tag(type)).force_rooted
]
end

@@ -460,3 +478,3 @@ parameters = []

name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin, return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted, source: :rbs)
parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin, return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted, source: :rbs, type_location: type_location)
end

@@ -467,2 +485,3 @@ type.type.optional_positionals.each do |param|

return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted,
type_location: type_location,
source: :rbs)

@@ -472,7 +491,7 @@ end

name = type.type.rest_positionals.name ? type.type.rest_positionals.name.to_s : "arg_#{arg_num += 1}"
parameters.push Solargraph::Pin::Parameter.new(decl: :restarg, name: name, closure: pin, source: :rbs)
parameters.push Solargraph::Pin::Parameter.new(decl: :restarg, name: name, closure: pin, source: :rbs, type_location: type_location)
end
type.type.trailing_positionals.each do |param|
name = param.name ? param.name.to_s : "arg_#{arg_num += 1}"
parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin, source: :rbs)
parameters.push Solargraph::Pin::Parameter.new(decl: :arg, name: name, closure: pin, source: :rbs, type_location: type_location)
end

@@ -483,3 +502,3 @@ type.type.required_keywords.each do |orig, param|

return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted,
source: :rbs)
source: :rbs, type_location: type_location)
end

@@ -490,2 +509,3 @@ type.type.optional_keywords.each do |orig, param|

return_type: ComplexType.try_parse(other_type_to_tag(param.type)).force_rooted,
type_location: type_location,
source: :rbs)

@@ -496,3 +516,3 @@ end

parameters.push Solargraph::Pin::Parameter.new(decl: :kwrestarg, name: type.type.rest_keywords.name.to_s, closure: pin,
source: :rbs)
source: :rbs, type_location: type_location)
end

@@ -507,2 +527,3 @@

# @param closure [Pin::Namespace]
# @param context [Context]
# @return [void]

@@ -531,2 +552,3 @@ def attr_reader_to_pin(decl, closure, context)

# @param closure [Pin::Namespace]
# @param context [Context]
# @return [void]

@@ -537,5 +559,6 @@ def attr_writer_to_pin(decl, closure, context)

visibility = calculate_method_visibility(decl, context, closure, final_scope, name)
type_location = location_decl_to_pin_location(decl.location)
pin = Solargraph::Pin::Method.new(
name: name,
type_location: location_decl_to_pin_location(decl.location),
type_location: type_location,
closure: closure,

@@ -554,3 +577,4 @@ parameters: [],

source: :rbs,
closure: pin
closure: pin,
type_location: type_location
)

@@ -564,2 +588,3 @@ rooted_tag = ComplexType.parse(other_type_to_tag(decl.type)).force_rooted.rooted_tags

# @param closure [Pin::Namespace]
# @param context [Context]
# @return [void]

@@ -596,2 +621,3 @@ def attr_accessor_to_pin(decl, closure, context)

comments: decl.comment&.string,
type_location: location_decl_to_pin_location(decl.location),
source: :rbs

@@ -613,2 +639,3 @@ )

comments: decl.comment&.string,
type_location: location_decl_to_pin_location(decl.location),
source: :rbs

@@ -615,0 +642,0 @@ )

# frozen_string_literal: true
module Solargraph
VERSION = '0.56.1'
VERSION = '0.56.2'
end

@@ -154,3 +154,3 @@ # frozen_string_literal: true

{
'include' => ['**/*.rb'],
'include' => ['Rakefile', 'Gemfile', '*.gemspec', '**/*.rb'],
'exclude' => ['spec/**/*', 'test/**/*', 'vendor/**/*', '.bundle/**/*'],

@@ -157,0 +157,0 @@ 'require' => [],

@@ -10,8 +10,36 @@ module Solargraph

def object_location code_object, spec
return nil if spec.nil? || code_object.nil? || code_object.file.nil? || code_object.line.nil?
if spec.nil? || code_object.nil? || code_object.file.nil? || code_object.line.nil?
if code_object.namespace.is_a?(YARD::CodeObjects::NamespaceObject)
# If the code object is a namespace, use the namespace's location
return object_location(code_object.namespace, spec)
end
return Solargraph::Location.new(__FILE__, Solargraph::Range.from_to(__LINE__ - 1, 0, __LINE__ - 1, 0))
end
file = File.join(spec.full_gem_path, code_object.file)
Solargraph::Location.new(file, Solargraph::Range.from_to(code_object.line - 1, 0, code_object.line - 1, 0))
end
# @param code_object [YARD::CodeObjects::Base]
# @param spec [Gem::Specification, nil]
# @return [Solargraph::Pin::Namespace]
def create_closure_namespace_for(code_object, spec)
code_object_for_location = code_object
# code_object.namespace is sometimes a YARD proxy object pointing to a method path ("Object#new")
code_object_for_location = code_object.namespace if code_object.namespace.is_a?(YARD::CodeObjects::NamespaceObject)
namespace_location = object_location(code_object_for_location, spec)
ns_name = code_object.namespace.to_s
if ns_name.empty?
Solargraph::Pin::ROOT_PIN
else
Solargraph::Pin::Namespace.new(
name: ns_name,
closure: Pin::ROOT_PIN,
gates: [code_object.namespace.to_s],
source: :yardoc,
location: namespace_location
)
end
end
end
end
end

@@ -10,8 +10,8 @@ # frozen_string_literal: true

# @param code_object [YARD::CodeObjects::Base]
# @param closure [Pin::Closure, nil]
# @param spec [Gem::Specification, nil]
# @return [Pin::Constant]
def self.make code_object, closure = nil, spec = nil
closure ||= Solargraph::Pin::Namespace.new(
name: code_object.namespace.to_s,
gates: [code_object.namespace.to_s],
source: :yardoc,
)
closure ||= create_closure_namespace_for(code_object, spec)
Pin::Constant.new(

@@ -18,0 +18,0 @@ location: object_location(code_object, spec),

@@ -22,8 +22,3 @@ # frozen_string_literal: true

def self.make code_object, name = nil, scope = nil, visibility = nil, closure = nil, spec = nil
closure ||= Solargraph::Pin::Namespace.new(
name: code_object.namespace.to_s,
gates: [code_object.namespace.to_s],
type: code_object.namespace.is_a?(YARD::CodeObjects::ClassObject) ? :class : :module,
source: :yardoc,
)
closure ||= create_closure_namespace_for(code_object, spec)
location = object_location(code_object, spec)

@@ -30,0 +25,0 @@ name ||= code_object.name.to_s

@@ -10,11 +10,11 @@ # frozen_string_literal: true

# @param code_object [YARD::CodeObjects::NamespaceObject]
# @param spec [Gem::Specification, nil]
# @param closure [Pin::Closure, nil]
# @return [Pin::Namespace]
def self.make code_object, spec, closure = nil
closure ||= Solargraph::Pin::Namespace.new(
name: code_object.namespace.to_s,
closure: Pin::ROOT_PIN,
gates: [code_object.namespace.to_s],
source: :yardoc,
)
closure ||= create_closure_namespace_for(code_object, spec)
location = object_location(code_object, spec)
Pin::Namespace.new(
location: object_location(code_object, spec),
location: location,
name: code_object.name.to_s,

@@ -21,0 +21,0 @@ comments: code_object.docstring ? code_object.docstring.all.to_s : '',