diff --git a/Gemfile.lock b/Gemfile.lock index 26fff2d..57dda9a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - ruby_language_server (0.9.1) + ruby_language_server (0.9.2) activerecord (~> 8.1) amatch bundler @@ -278,7 +278,7 @@ CHECKSUMS rubocop-rake (0.7.1) sha256=3797f2b6810c3e9df7376c26d5f44f3475eda59eb1adc38e6f62ecf027cbae4d rubocop-rspec (3.8.0) sha256=28440dccb3f223a9938ca1f946bd3438275b8c6c156dab909e2cb8bc424cab33 ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33 - ruby_language_server (0.9.1) + ruby_language_server (0.9.2) securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1 shellany (0.0.1) sha256=0e127a9132698766d7e752e82cdac8250b6adbd09e6c0a7fbbb6f61964fedee7 simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5 diff --git a/lib/ruby_language_server/scope_data/base.rb b/lib/ruby_language_server/scope_data/base.rb index 4d3f381..5691228 100644 --- a/lib/ruby_language_server/scope_data/base.rb +++ b/lib/ruby_language_server/scope_data/base.rb @@ -25,7 +25,10 @@ class Base < ActiveRecord::Base TYPE_VARIABLE => '^' }.freeze - attr_accessor :type # Type of this scope (module, class, block) + # Return the class_type as a symbol for easier testing + def type + class_type&.to_sym + end # bar should be closer to Bar than Far. Adding the UPPER version accomplishes this. scope :with_distance_from, lambda { |word| diff --git a/lib/ruby_language_server/scope_parser.rb b/lib/ruby_language_server/scope_parser.rb index 5ca379b..19342de 100644 --- a/lib/ruby_language_server/scope_parser.rb +++ b/lib/ruby_language_server/scope_parser.rb @@ -41,7 +41,7 @@ def visit_class_node(node) end_line = node.location.end_line column = node.location.start_column - scope = push_scope(ScopeData::Scope::TYPE_CLASS, name, line, column, end_line) + scope = push_scope(ScopeData::Scope::TYPE_CLASS, name, line, column, end_line, false) # Handle superclass if node.superclass @@ -60,7 +60,7 @@ def visit_module_node(node) end_line = node.location.end_line column = node.location.start_column - push_scope(ScopeData::Scope::TYPE_MODULE, name, line, column, end_line) + push_scope(ScopeData::Scope::TYPE_MODULE, name, line, column, end_line, false) super pop_scope end diff --git a/spec/lib/ruby_language_server/scope_parser_spec.rb b/spec/lib/ruby_language_server/scope_parser_spec.rb index f10a778..03553c6 100644 --- a/spec/lib/ruby_language_server/scope_parser_spec.rb +++ b/spec/lib/ruby_language_server/scope_parser_spec.rb @@ -167,5 +167,91 @@ def some_method assert_equal('item', scope_parser.root_scope.self_and_descendants.last.variables.first.name) end end + + describe 'sibling modules' do + before do + @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) + module Foo + module Bar + end + module Baz + end + end + RUBY + end + + it 'places sibling modules at the same level' do + foo = @parser.root_scope.children.first + assert_equal('Foo', foo.name) + + children = foo.children + assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") + + bar = children.detect { |c| c.name == 'Bar' } + baz = children.detect { |c| c.name == 'Baz' } + + refute_nil(bar, "Bar should be a child of Foo") + refute_nil(baz, "Baz should be a child of Foo") + assert_equal(0, bar.children.size, "Bar should have no children") + end + end + + describe 'sibling classes' do + before do + @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) + module Foo + class Bar + end + class Baz + end + end + RUBY + end + + it 'places sibling classes at the same level' do + foo = @parser.root_scope.children.first + assert_equal('Foo', foo.name) + + children = foo.children + assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") + + bar = children.detect { |c| c.name == 'Bar' } + baz = children.detect { |c| c.name == 'Baz' } + + refute_nil(bar, "Bar should be a child of Foo") + refute_nil(baz, "Baz should be a child of Foo") + assert_equal(0, bar.children.size, "Bar should have no children") + end + end + + describe 'mixed siblings' do + before do + @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) + module Foo + class Bar + end + module Baz + end + end + RUBY + end + + it 'places sibling class and module at the same level' do + foo = @parser.root_scope.children.first + assert_equal('Foo', foo.name) + + children = foo.children + assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") + + bar = children.detect { |c| c.name == 'Bar' } + baz = children.detect { |c| c.name == 'Baz' } + + refute_nil(bar, "Bar should be a child of Foo") + refute_nil(baz, "Baz should be a child of Foo") + assert_equal(:class, bar.type, "Bar should be a class") + assert_equal(:module, baz.type, "Baz should be a module") + assert_equal(0, bar.children.size, "Bar should have no children") + end + end end end