lib/ruby_indexer/lib/ruby_indexer/entry.rb in ruby-lsp-0.17.4 vs lib/ruby_indexer/lib/ruby_indexer/entry.rb in ruby-lsp-0.17.5

- old
+ new

@@ -20,10 +20,12 @@ attr_reader :file_path sig { returns(RubyIndexer::Location) } attr_reader :location + alias_method :name_location, :location + sig { returns(T::Array[String]) } attr_reader :comments sig { returns(Visibility) } attr_accessor :visibility @@ -56,10 +58,20 @@ RubyIndexer::Location, ) end sig { returns(T::Boolean) } + def public? + visibility == Visibility::PUBLIC + end + + sig { returns(T::Boolean) } + def protected? + visibility == Visibility::PROTECTED + end + + sig { returns(T::Boolean) } def private? visibility == Visibility::PRIVATE end sig { returns(String) } @@ -82,35 +94,53 @@ end end class Include < ModuleOperation; end class Prepend < ModuleOperation; end - class Extend < ModuleOperation; end class Namespace < Entry extend T::Sig extend T::Helpers abstract! sig { returns(T::Array[String]) } attr_reader :nesting + # Returns the location of the constant name, excluding the parent class or the body + sig { returns(Location) } + attr_reader :name_location + sig do params( nesting: T::Array[String], file_path: String, location: T.any(Prism::Location, RubyIndexer::Location), + name_location: T.any(Prism::Location, Location), comments: T::Array[String], ).void end - def initialize(nesting, file_path, location, comments) + def initialize(nesting, file_path, location, name_location, comments) @name = T.let(nesting.join("::"), String) # The original nesting where this namespace was discovered @nesting = nesting super(@name, file_path, location, comments) + + @name_location = T.let( + if name_location.is_a?(Prism::Location) + Location.new( + name_location.start_line, + name_location.end_line, + name_location.start_column, + name_location.end_column, + ) + else + name_location + end, + RubyIndexer::Location, + ) end sig { returns(T::Array[String]) } def mixin_operation_module_names mixin_operations.map(&:module_name) @@ -144,16 +174,17 @@ sig do params( nesting: T::Array[String], file_path: String, location: T.any(Prism::Location, RubyIndexer::Location), + name_location: T.any(Prism::Location, Location), comments: T::Array[String], parent_class: T.nilable(String), ).void end - def initialize(nesting, file_path, location, comments, parent_class) - super(nesting, file_path, location, comments) + def initialize(nesting, file_path, location, name_location, comments, parent_class) # rubocop:disable Metrics/ParameterLists + super(nesting, file_path, location, name_location, comments) @parent_class = parent_class end sig { override.returns(Integer) } def ancestor_hash @@ -162,19 +193,25 @@ end class SingletonClass < Class extend T::Sig - sig { params(location: Prism::Location, comments: T::Array[String]).void } - def update_singleton_information(location, comments) + sig { params(location: Prism::Location, name_location: Prism::Location, comments: T::Array[String]).void } + def update_singleton_information(location, name_location, comments) # Create a new RubyIndexer::Location object from the Prism location @location = Location.new( location.start_line, location.end_line, location.start_column, location.end_column, ) + @name_location = Location.new( + name_location.start_line, + name_location.end_line, + name_location.start_column, + name_location.end_column, + ) @comments.concat(comments) end end class Constant < Entry @@ -264,10 +301,15 @@ abstract! sig { returns(T.nilable(Entry::Namespace)) } attr_reader :owner + sig { returns(T::Array[RubyIndexer::Entry::Parameter]) } + def parameters + T.must(signatures.first).parameters + end + sig do params( name: String, file_path: String, location: T.any(Prism::Location, RubyIndexer::Location), @@ -280,51 +322,76 @@ super(name, file_path, location, comments) @visibility = visibility @owner = owner end - sig { abstract.returns(T::Array[Parameter]) } - def parameters; end + sig { abstract.returns(T::Array[Entry::Signature]) } + def signatures; end - # Returns a string with the decorated names of the parameters of this member. E.g.: `(a, b = 1, c: 2)` sig { returns(String) } def decorated_parameters - "(#{parameters.map(&:decorated_name).join(", ")})" + first_signature = signatures.first + return "()" unless first_signature + + "(#{first_signature.format})" end end class Accessor < Member extend T::Sig - sig { override.returns(T::Array[Parameter]) } - def parameters - params = [] - params << RequiredParameter.new(name: name.delete_suffix("=").to_sym) if name.end_with?("=") - params + sig { override.returns(T::Array[Signature]) } + def signatures + @signatures ||= T.let( + begin + params = [] + params << RequiredParameter.new(name: name.delete_suffix("=").to_sym) if name.end_with?("=") + [Entry::Signature.new(params)] + end, + T.nilable(T::Array[Signature]), + ) end end class Method < Member extend T::Sig - sig { override.returns(T::Array[Parameter]) } - attr_reader :parameters + sig { override.returns(T::Array[Signature]) } + attr_reader :signatures + # Returns the location of the method name, excluding parameters or the body + sig { returns(Location) } + attr_reader :name_location + sig do params( name: String, file_path: String, location: T.any(Prism::Location, RubyIndexer::Location), + name_location: T.any(Prism::Location, Location), comments: T::Array[String], - parameters: T::Array[Parameter], + signatures: T::Array[Signature], visibility: Visibility, owner: T.nilable(Entry::Namespace), ).void end - def initialize(name, file_path, location, comments, parameters, visibility, owner) # rubocop:disable Metrics/ParameterLists + def initialize(name, file_path, location, name_location, comments, signatures, visibility, owner) # rubocop:disable Metrics/ParameterLists super(name, file_path, location, comments, visibility, owner) - @parameters = parameters + @signatures = signatures + @name_location = T.let( + if name_location.is_a?(Prism::Location) + Location.new( + name_location.start_line, + name_location.end_line, + name_location.start_column, + name_location.end_column, + ) + else + name_location + end, + RubyIndexer::Location, + ) end end # An UnresolvedAlias points to a constant alias with a right hand side that has not yet been resolved. For # example, if we find @@ -435,10 +502,13 @@ extend T::Sig sig { returns(T.any(Member, MethodAlias)) } attr_reader :target + sig { returns(T.nilable(Entry::Namespace)) } + attr_reader :owner + sig { params(target: T.any(Member, MethodAlias), unresolved_alias: UnresolvedMethodAlias).void } def initialize(target, unresolved_alias) full_comments = ["Alias for #{target.name}\n"] full_comments.concat(unresolved_alias.comments) full_comments << "\n" @@ -450,24 +520,41 @@ unresolved_alias.location, full_comments, ) @target = target + @owner = T.let(unresolved_alias.owner, T.nilable(Entry::Namespace)) end - sig { returns(T.nilable(Entry::Namespace)) } - def owner - @target.owner - end - sig { returns(T::Array[Parameter]) } def parameters @target.parameters end sig { returns(String) } def decorated_parameters @target.decorated_parameters + end + end + + # Ruby doesn't support method overloading, so a method will have only one signature. + # However RBS can represent the concept of method overloading, with different return types based on the arguments + # passed, so we need to store all the signatures. + class Signature + extend T::Sig + + sig { returns(T::Array[Parameter]) } + attr_reader :parameters + + sig { params(parameters: T::Array[Parameter]).void } + def initialize(parameters) + @parameters = parameters + end + + # Returns a string with the decorated names of the parameters of this member. E.g.: `(a, b = 1, c: 2)` + sig { returns(String) } + def format + @parameters.map(&:decorated_name).join(", ") end end end end