Skip to content

Commit

Permalink
Use T::Enum to type visibility values
Browse files Browse the repository at this point in the history
  • Loading branch information
st0012 committed May 30, 2024
1 parent 936ca5b commit 397d61c
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 33 deletions.
20 changes: 12 additions & 8 deletions lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class DeclarationListener
def initialize(index, dispatcher, parse_result, file_path)
@index = index
@file_path = file_path
@visibility_stack = T.let([[:public]], T::Array[T::Array[Symbol]])
@visibility_stack = T.let([[Entry::Visibility::PUBLIC]], T::Array[T::Array[Entry::Visibility]])
@comments_by_line = T.let(
parse_result.comments.to_h do |c|
[c.location.start_line, c]
Expand Down Expand Up @@ -52,7 +52,7 @@ def initialize(index, dispatcher, parse_result, file_path)

sig { params(node: Prism::ClassNode).void }
def on_class_node_enter(node)
@visibility_stack.push([:public])
@visibility_stack.push([Entry::Visibility::PUBLIC])
name = node.constant_path.location.slice

comments = collect_comments(node)
Expand Down Expand Up @@ -85,7 +85,7 @@ def on_class_node_leave(node)

sig { params(node: Prism::ModuleNode).void }
def on_module_node_enter(node)
@visibility_stack.push([:public])
@visibility_stack.push([Entry::Visibility::PUBLIC])
name = node.constant_path.location.slice

comments = collect_comments(node)
Expand Down Expand Up @@ -204,8 +204,12 @@ def on_call_node_enter(node)
handle_module_operation(node, :included_modules)
when :prepend
handle_module_operation(node, :prepended_modules)
when :public, :protected, :private
change_scope_visibility(message)
when :public
change_scope_visibility(Entry::Visibility::PUBLIC)
when :protected
change_scope_visibility(Entry::Visibility::PROTECTED)
when :private
change_scope_visibility(Entry::Visibility::PRIVATE)
end
end

Expand Down Expand Up @@ -281,7 +285,7 @@ def handle_private_constant(node)
# The private_constant method does not resolve the constant name. It always points to a constant that needs to
# exist in the current namespace
entries = @index[fully_qualify_name(name)]
entries&.each { |entry| entry.visibility = :private }
entries&.each { |entry| entry.visibility = Entry::Visibility::PRIVATE }
end

sig do
Expand Down Expand Up @@ -412,12 +416,12 @@ def handle_module_operation(node, operation)
collection.concat(names)
end

sig { returns(Symbol) }
sig { returns(Entry::Visibility) }
def current_visibility
T.must(@visibility_stack.last&.last)
end

sig { params(visibility: Symbol).void }
sig { params(visibility: Entry::Visibility).void }
def change_scope_visibility(visibility)
scope_visibility_stack = T.must(@visibility_stack.last)
scope_visibility_stack.push(visibility)
Expand Down
16 changes: 12 additions & 4 deletions lib/ruby_indexer/lib/ruby_indexer/entry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@

module RubyIndexer
class Entry
class Visibility < T::Enum
enums do
PUBLIC = new(:public)
PROTECTED = new(:protected)
PRIVATE = new(:private)
end
end

extend T::Sig

sig { returns(String) }
Expand All @@ -17,7 +25,7 @@ class Entry
sig { returns(T::Array[String]) }
attr_reader :comments

sig { returns(Symbol) }
sig { returns(Visibility) }
attr_accessor :visibility

sig do
Expand All @@ -32,7 +40,7 @@ def initialize(name, file_path, location, comments)
@name = name
@file_path = file_path
@comments = comments
@visibility = T.let(:public, Symbol)
@visibility = T.let(Visibility::PUBLIC, Visibility)

@location = T.let(
if location.is_a?(Prism::Location)
Expand Down Expand Up @@ -188,7 +196,7 @@ class Member < Entry
file_path: String,
location: T.any(Prism::Location, RubyIndexer::Location),
comments: T::Array[String],
visibility: Symbol,
visibility: Visibility,
owner: T.nilable(Entry::Namespace),
).void
end
Expand Down Expand Up @@ -229,7 +237,7 @@ class Method < Member
location: T.any(Prism::Location, RubyIndexer::Location),
comments: T::Array[String],
parameters_node: T.nilable(Prism::ParametersNode),
visibility: Symbol,
visibility: Visibility,
owner: T.nilable(Entry::Namespace),
).void
end
Expand Down
6 changes: 3 additions & 3 deletions lib/ruby_indexer/test/classes_and_modules_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -290,13 +290,13 @@ class D; end
RUBY

b_const = @index["A::B"].first
assert_equal(:private, b_const.visibility)
assert_equal(Entry::Visibility::PRIVATE, b_const.visibility)

c_const = @index["A::C"].first
assert_equal(:private, c_const.visibility)
assert_equal(Entry::Visibility::PRIVATE, c_const.visibility)

d_const = @index["A::D"].first
assert_equal(:public, d_const.visibility)
assert_equal(Entry::Visibility::PUBLIC, d_const.visibility)
end

def test_keeping_track_of_super_classes
Expand Down
16 changes: 8 additions & 8 deletions lib/ruby_indexer/test/constant_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,13 @@ class A
RUBY

b_const = @index["A::B"].first
assert_equal(:private, b_const.visibility)
assert_equal(Entry::Visibility::PRIVATE, b_const.visibility)

c_const = @index["A::C"].first
assert_equal(:private, c_const.visibility)
assert_equal(Entry::Visibility::PRIVATE, c_const.visibility)

d_const = @index["A::D"].first
assert_equal(:public, d_const.visibility)
assert_equal(Entry::Visibility::PUBLIC, d_const.visibility)
end

def test_marking_constants_as_private_reopening_namespaces
Expand All @@ -155,13 +155,13 @@ module B
RUBY

a_const = @index["A::B::CONST_A"].first
assert_equal(:private, a_const.visibility)
assert_equal(Entry::Visibility::PRIVATE, a_const.visibility)

b_const = @index["A::B::CONST_B"].first
assert_equal(:private, b_const.visibility)
assert_equal(Entry::Visibility::PRIVATE, b_const.visibility)

c_const = @index["A::B::CONST_C"].first
assert_equal(:private, c_const.visibility)
assert_equal(Entry::Visibility::PRIVATE, c_const.visibility)
end

def test_marking_constants_as_private_with_receiver
Expand All @@ -179,10 +179,10 @@ module B
RUBY

a_const = @index["A::B::CONST_A"].first
assert_equal(:private, a_const.visibility)
assert_equal(Entry::Visibility::PRIVATE, a_const.visibility)

b_const = @index["A::B::CONST_B"].first
assert_equal(:private, b_const.visibility)
assert_equal(Entry::Visibility::PRIVATE, b_const.visibility)
end

def test_indexing_constant_aliases
Expand Down
12 changes: 6 additions & 6 deletions lib/ruby_indexer/test/method_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ def bar; end
def baz; end
RUBY

assert_entry("foo", Entry::InstanceMethod, "/fake/path/foo.rb:0-8:1-3", visibility: :private)
assert_entry("bar", Entry::InstanceMethod, "/fake/path/foo.rb:3-0:3-12", visibility: :public)
assert_entry("baz", Entry::InstanceMethod, "/fake/path/foo.rb:7-0:7-12", visibility: :protected)
assert_entry("foo", Entry::InstanceMethod, "/fake/path/foo.rb:0-8:1-3", visibility: Entry::Visibility::PRIVATE)
assert_entry("bar", Entry::InstanceMethod, "/fake/path/foo.rb:3-0:3-12", visibility: Entry::Visibility::PUBLIC)
assert_entry("baz", Entry::InstanceMethod, "/fake/path/foo.rb:7-0:7-12", visibility: Entry::Visibility::PROTECTED)
end

def test_visibility_tracking_with_nested_class_or_modules
Expand All @@ -103,9 +103,9 @@ def baz; end
end
RUBY

assert_entry("foo", Entry::InstanceMethod, "/fake/path/foo.rb:3-2:3-14", visibility: :private)
assert_entry("bar", Entry::InstanceMethod, "/fake/path/foo.rb:6-4:6-16", visibility: :public)
assert_entry("baz", Entry::InstanceMethod, "/fake/path/foo.rb:9-2:9-14", visibility: :private)
assert_entry("foo", Entry::InstanceMethod, "/fake/path/foo.rb:3-2:3-14", visibility: Entry::Visibility::PRIVATE)
assert_entry("bar", Entry::InstanceMethod, "/fake/path/foo.rb:6-4:6-16", visibility: Entry::Visibility::PUBLIC)
assert_entry("baz", Entry::InstanceMethod, "/fake/path/foo.rb:9-2:9-14", visibility: Entry::Visibility::PRIVATE)
end

def test_method_with_parameters
Expand Down
3 changes: 2 additions & 1 deletion lib/ruby_lsp/listeners/completion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ def constant_path_completion(name, range)
# The only time we may have a private constant reference from outside of the namespace is if we're dealing
# with ConstantPath and the entry name doesn't start with the current nesting
first_entry = T.must(entries.first)
next if first_entry.visibility == :private && !first_entry.name.start_with?("#{@nesting}::")
next if first_entry.visibility == RubyIndexer::Entry::Visibility::PRIVATE &&
!first_entry.name.start_with?("#{@nesting}::")

constant_name = first_entry.name.delete_prefix("#{real_namespace}::")
full_name = aliased_namespace.empty? ? constant_name : "#{aliased_namespace}::#{constant_name}"
Expand Down
3 changes: 2 additions & 1 deletion lib/ruby_lsp/listeners/definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ def find_in_index(value)
# We should only allow jumping to the definition of private constants if the constant is defined in the same
# namespace as the reference
first_entry = T.must(entries.first)
return if first_entry.visibility == :private && first_entry.name != "#{@nesting.join("::")}::#{value}"
return if first_entry.visibility == RubyIndexer::Entry::Visibility::PRIVATE &&
first_entry.name != "#{@nesting.join("::")}::#{value}"

entries.each do |entry|
location = entry.location
Expand Down
3 changes: 2 additions & 1 deletion lib/ruby_lsp/listeners/hover.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ def generate_hover(name, location)
# We should only show hover for private constants if the constant is defined in the same namespace as the
# reference
first_entry = T.must(entries.first)
return if first_entry.visibility == :private && first_entry.name != "#{@nesting.join("::")}::#{name}"
return if first_entry.visibility == RubyIndexer::Entry::Visibility::PRIVATE &&
first_entry.name != "#{@nesting.join("::")}::#{name}"

categorized_markdown_from_index_entries(name, entries).each do |category, content|
@response_builder.push(content, category: category)
Expand Down
2 changes: 1 addition & 1 deletion lib/ruby_lsp/requests/workspace_symbol.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def perform
next if @global_state.typechecker && not_in_dependencies?(file_path)

# We should never show private symbols when searching the entire workspace
next if entry.visibility == :private
next if entry.visibility == RubyIndexer::Entry::Visibility::PRIVATE

kind = kind_for_entry(entry)
loc = entry.location
Expand Down

0 comments on commit 397d61c

Please sign in to comment.