ruby_language_server 0.2.10 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.txt +6 -0
- data/Gemfile.lock +22 -1
- data/Makefile +4 -1
- data/README.md +1 -1
- data/exe/ruby_language_server +2 -2
- data/lib/config/initializers/active_record.rb +19 -0
- data/lib/config/initializers/sqlite.rb +3 -0
- data/lib/db/schema.rb +44 -0
- data/lib/ruby_language_server.rb +1 -12
- data/lib/ruby_language_server/application.rb +30 -0
- data/lib/ruby_language_server/code_file.rb +73 -53
- data/lib/ruby_language_server/completion.rb +9 -8
- data/lib/ruby_language_server/io.rb +7 -2
- data/lib/ruby_language_server/location.rb +2 -2
- data/lib/ruby_language_server/project_manager.rb +36 -38
- data/lib/ruby_language_server/scope_data/base.rb +13 -7
- data/lib/ruby_language_server/scope_data/scope.rb +67 -67
- data/lib/ruby_language_server/scope_data/variable.rb +32 -12
- data/lib/ruby_language_server/scope_parser.rb +19 -28
- data/lib/ruby_language_server/server.rb +6 -0
- data/lib/ruby_language_server/version.rb +1 -1
- data/ruby_language_server.gemspec +3 -0
- metadata +34 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 020e4ff18a466c0ca90d360610148699d96e9d983f173499169fe79923c0b201
|
4
|
+
data.tar.gz: abc71a6aa28296af4c53404a74500690e339a9c7b27c563b8699bfedcb0f16fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 441a9f0fad64e0fef21268bc7b4e78ad7c3d966d1b690a53af404c27ae063238c94dca7455eb8ebb1b259d8aec2e3f409cfac28b83973427866f6da3e1e1e00f
|
7
|
+
data.tar.gz: 8010f23f8fd7f24cb2a9e3883fdf86cd9c9401720a005bdef97a8537844edc44b14a311dcca19937c18076efebb454093eed11947cdc4409b37bb7be578ff16c
|
data/CHANGELOG.txt
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ruby_language_server (0.
|
4
|
+
ruby_language_server (0.3.0)
|
5
|
+
activerecord
|
5
6
|
amatch
|
6
7
|
bundler
|
7
8
|
etc
|
@@ -9,16 +10,30 @@ PATH
|
|
9
10
|
json
|
10
11
|
rubocop
|
11
12
|
rubocop-rspec
|
13
|
+
sqlite3
|
12
14
|
|
13
15
|
GEM
|
14
16
|
remote: https://rubygems.org/
|
15
17
|
specs:
|
18
|
+
activemodel (5.2.3)
|
19
|
+
activesupport (= 5.2.3)
|
20
|
+
activerecord (5.2.3)
|
21
|
+
activemodel (= 5.2.3)
|
22
|
+
activesupport (= 5.2.3)
|
23
|
+
arel (>= 9.0)
|
24
|
+
activesupport (5.2.3)
|
25
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
26
|
+
i18n (>= 0.7, < 2)
|
27
|
+
minitest (~> 5.1)
|
28
|
+
tzinfo (~> 1.1)
|
16
29
|
amatch (0.4.0)
|
17
30
|
mize
|
18
31
|
tins (~> 1.0)
|
32
|
+
arel (9.0.0)
|
19
33
|
ast (2.4.0)
|
20
34
|
byebug (11.0.1)
|
21
35
|
coderay (1.1.2)
|
36
|
+
concurrent-ruby (1.1.5)
|
22
37
|
etc (1.0.1)
|
23
38
|
ffi (1.11.1)
|
24
39
|
formatador (0.2.5)
|
@@ -39,6 +54,8 @@ GEM
|
|
39
54
|
guard-rubocop (1.3.0)
|
40
55
|
guard (~> 2.0)
|
41
56
|
rubocop (~> 0.20)
|
57
|
+
i18n (1.6.0)
|
58
|
+
concurrent-ruby (~> 1.0)
|
42
59
|
jaro_winkler (1.5.3)
|
43
60
|
json (2.2.0)
|
44
61
|
listen (3.1.5)
|
@@ -87,8 +104,12 @@ GEM
|
|
87
104
|
sexp_processor (~> 4.9)
|
88
105
|
sexp_processor (4.12.1)
|
89
106
|
shellany (0.0.1)
|
107
|
+
sqlite3 (1.4.1)
|
90
108
|
thor (0.20.3)
|
109
|
+
thread_safe (0.3.6)
|
91
110
|
tins (1.21.1)
|
111
|
+
tzinfo (1.2.5)
|
112
|
+
thread_safe (~> 0.1)
|
92
113
|
unicode-display_width (1.6.0)
|
93
114
|
|
94
115
|
PLATFORMS
|
data/Makefile
CHANGED
@@ -5,9 +5,12 @@ build:
|
|
5
5
|
docker build -t $(PROJECT_NAME) .
|
6
6
|
|
7
7
|
guard: build
|
8
|
-
|
8
|
+
echo > active_record.log
|
9
|
+
docker run -it --rm $(LOCAL_LINK) -e LOG_LEVEL=DEBUG $(PROJECT_NAME) bundle exec guard
|
10
|
+
echo > active_record.log
|
9
11
|
|
10
12
|
continuous_development: build
|
13
|
+
docker build -t local_ruby_language_server .
|
11
14
|
echo "You are going to want to set the ide-ruby 'Image Name' to local_ruby_language_server"
|
12
15
|
sleep 15
|
13
16
|
while (true) ; \
|
data/README.md
CHANGED
data/exe/ruby_language_server
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection(
|
4
|
+
adapter: 'sqlite3',
|
5
|
+
database: 'file::memory:?cache=shared',
|
6
|
+
# database: '/database',
|
7
|
+
pool: 5, # does not seem to help
|
8
|
+
checkout_timeout: 30.seconds # does not seem to help
|
9
|
+
)
|
10
|
+
|
11
|
+
if ENV['LOG_LEVEL'] == 'DEBUG'
|
12
|
+
begin
|
13
|
+
warn('Turning on active record logging')
|
14
|
+
ActiveRecord::Base.logger = Logger.new(File.open('active_record.log', 'w'))
|
15
|
+
rescue Exception => e
|
16
|
+
ActiveRecord::Base.logger = Logger.new(STDERR)
|
17
|
+
ActiveRecord::Base.logger.error(e)
|
18
|
+
end
|
19
|
+
end
|
data/lib/db/schema.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
ActiveRecord::Schema.define do
|
4
|
+
def write(*args)
|
5
|
+
RubyLanguageServer.logger.debug(args)
|
6
|
+
end
|
7
|
+
|
8
|
+
create_table :scopes, force: true do |t|
|
9
|
+
t.references :code_file
|
10
|
+
t.integer :parent_id
|
11
|
+
t.integer :top_line # first line
|
12
|
+
t.integer :bottom_line # last line
|
13
|
+
t.integer :column
|
14
|
+
t.string :name, default: ''
|
15
|
+
t.string :superclass_name
|
16
|
+
t.string :path
|
17
|
+
t.string :class_type, null: false
|
18
|
+
end
|
19
|
+
|
20
|
+
add_index :scopes, :name
|
21
|
+
add_index :scopes, :path
|
22
|
+
add_index :scopes, :code_file
|
23
|
+
|
24
|
+
create_table :variables, force: true do |t|
|
25
|
+
t.references :code_file
|
26
|
+
t.references :scope
|
27
|
+
t.integer :line
|
28
|
+
t.integer :column
|
29
|
+
t.string :name
|
30
|
+
t.string :path
|
31
|
+
t.string :variable_type
|
32
|
+
end
|
33
|
+
|
34
|
+
add_index :variables, :name
|
35
|
+
add_index :variables, :code_file
|
36
|
+
|
37
|
+
create_table :code_files, force: true do |t|
|
38
|
+
t.string :uri
|
39
|
+
t.boolean :refresh_root_scope, default: true
|
40
|
+
t.text :text
|
41
|
+
end
|
42
|
+
|
43
|
+
add_index :code_files, :uri
|
44
|
+
end
|
data/lib/ruby_language_server.rb
CHANGED
@@ -1,14 +1,3 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'ruby_language_server/
|
4
|
-
require_relative 'ruby_language_server/version'
|
5
|
-
require_relative 'ruby_language_server/gem_installer'
|
6
|
-
require_relative 'ruby_language_server/io'
|
7
|
-
require_relative 'ruby_language_server/location'
|
8
|
-
require_relative 'ruby_language_server/code_file'
|
9
|
-
require_relative 'ruby_language_server/scope_parser'
|
10
|
-
require_relative 'ruby_language_server/good_cop'
|
11
|
-
require_relative 'ruby_language_server/project_manager'
|
12
|
-
require_relative 'ruby_language_server/server'
|
13
|
-
require_relative 'ruby_language_server/line_context'
|
14
|
-
require_relative 'ruby_language_server/completion'
|
3
|
+
require_relative 'ruby_language_server/application'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_record'
|
4
|
+
|
5
|
+
require_relative 'logger' # do this first!
|
6
|
+
require_relative '../config/initializers/sqlite'
|
7
|
+
require_relative '../config/initializers/active_record'
|
8
|
+
require_relative '../db/schema'
|
9
|
+
|
10
|
+
require_relative 'version'
|
11
|
+
require_relative 'gem_installer'
|
12
|
+
require_relative 'io'
|
13
|
+
require_relative 'location'
|
14
|
+
require_relative 'code_file'
|
15
|
+
require_relative 'scope_parser'
|
16
|
+
require_relative 'good_cop'
|
17
|
+
require_relative 'project_manager'
|
18
|
+
require_relative 'server'
|
19
|
+
require_relative 'line_context'
|
20
|
+
require_relative 'completion'
|
21
|
+
|
22
|
+
module RubyLanguageServer
|
23
|
+
class Application
|
24
|
+
def start
|
25
|
+
update_mutex = Monitor.new
|
26
|
+
server = RubyLanguageServer::Server.new(update_mutex)
|
27
|
+
RubyLanguageServer::IO.new(server, update_mutex)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,32 +1,40 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_record'
|
4
|
+
|
3
5
|
require_relative 'scope_data/base'
|
4
6
|
require_relative 'scope_data/scope'
|
5
7
|
require_relative 'scope_data/variable'
|
6
8
|
|
7
9
|
module RubyLanguageServer
|
8
|
-
class CodeFile
|
9
|
-
|
10
|
-
|
10
|
+
class CodeFile < ActiveRecord::Base
|
11
|
+
has_many :scopes, class_name: 'RubyLanguageServer::ScopeData::Scope', dependent: :destroy do
|
12
|
+
def root_scope
|
13
|
+
where(class_type: RubyLanguageServer::ScopeData::Scope::TYPE_ROOT).first
|
14
|
+
end
|
15
|
+
end
|
16
|
+
has_many :variables, class_name: 'RubyLanguageServer::ScopeData::Variable', dependent: :destroy
|
17
|
+
|
11
18
|
attr_accessor :diagnostics
|
12
19
|
|
13
|
-
def
|
20
|
+
def self.build(uri, text)
|
14
21
|
RubyLanguageServer.logger.debug("CodeFile initialize #{uri}")
|
15
|
-
@uri = uri
|
16
|
-
@text = text
|
17
|
-
@refresh_root_scope = true
|
18
|
-
end
|
19
22
|
|
20
|
-
|
21
|
-
|
22
|
-
if @text == new_text
|
23
|
-
RubyLanguageServer.logger.debug('IT WAS THE SAME!!!!!!!!!!!!')
|
24
|
-
return
|
25
|
-
end
|
26
|
-
@text = new_text
|
27
|
-
@refresh_root_scope = true
|
23
|
+
new_code_file = create!(uri: uri, text: text)
|
24
|
+
new_code_file
|
28
25
|
end
|
29
26
|
|
27
|
+
# def text=(new_text)
|
28
|
+
# RubyLanguageServer.logger.debug("text= for #{uri}")
|
29
|
+
# if @text == new_text
|
30
|
+
# RubyLanguageServer.logger.debug('IT WAS THE SAME!!!!!!!!!!!!')
|
31
|
+
# return
|
32
|
+
# end
|
33
|
+
# @text = new_text
|
34
|
+
# update_attribute(:refresh_root_scope, true)
|
35
|
+
# root_scope
|
36
|
+
# end
|
37
|
+
#
|
30
38
|
SYMBOL_KIND = {
|
31
39
|
file: 1,
|
32
40
|
'module': 5, # 2,
|
@@ -53,46 +61,44 @@ module RubyLanguageServer
|
|
53
61
|
def ancestor_scope_name(scope)
|
54
62
|
return_scope = scope
|
55
63
|
while (return_scope = return_scope.parent)
|
56
|
-
return return_scope.name unless return_scope.name.nil?
|
64
|
+
return return_scope.name unless return_scope.name.nil? || return_scope.block_scope?
|
57
65
|
end
|
58
66
|
end
|
59
67
|
|
60
68
|
def tags
|
61
69
|
RubyLanguageServer.logger.debug("Asking about tags for #{uri}")
|
62
|
-
|
70
|
+
@tags ||= [{}]
|
71
|
+
return @tags if text.nil?
|
72
|
+
return @tags = [{}] if text == ''
|
73
|
+
|
74
|
+
refresh_scopes_if_needed # cause root scope to reset
|
75
|
+
return @tags if scopes.reload.count <= 1 # just the root
|
63
76
|
|
64
|
-
tags =
|
65
|
-
|
66
|
-
next if scope.
|
77
|
+
tags = scopes.reload.map do |scope|
|
78
|
+
next if scope.class_type == ScopeData::Base::TYPE_BLOCK
|
79
|
+
next if scope.root_scope?
|
67
80
|
|
68
|
-
|
69
|
-
kind =
|
70
|
-
kind = 9 if name == 'initialize' # Magical special case
|
81
|
+
kind = SYMBOL_KIND[scope.class_type.to_sym] || 7
|
82
|
+
kind = 9 if scope.name == 'initialize' # Magical special case
|
71
83
|
scope_hash = {
|
72
|
-
name: name,
|
84
|
+
name: scope.name,
|
73
85
|
kind: kind,
|
74
86
|
location: Location.hash(uri, scope.top_line)
|
75
87
|
}
|
76
88
|
container_name = ancestor_scope_name(scope)
|
77
|
-
scope_hash[:containerName] = container_name
|
78
|
-
|
79
|
-
|
80
|
-
scope.variables.each do |variable|
|
81
|
-
name = variable.name
|
82
|
-
# We only care about counstants
|
83
|
-
next unless name =~ /^[A-Z]/
|
84
|
-
|
85
|
-
variable_hash = {
|
86
|
-
name: name,
|
87
|
-
kind: SYMBOL_KIND[:constant],
|
88
|
-
location: Location.hash(uri, variable.line),
|
89
|
-
containerName: scope.name
|
90
|
-
}
|
91
|
-
tags << variable_hash
|
92
|
-
end
|
89
|
+
scope_hash[:containerName] = container_name unless container_name.blank?
|
90
|
+
scope_hash
|
93
91
|
end
|
94
|
-
|
95
|
-
|
92
|
+
tags += variables.constant_variables.reload.map do |variable|
|
93
|
+
name = variable.name
|
94
|
+
{
|
95
|
+
name: name,
|
96
|
+
kind: SYMBOL_KIND[:constant],
|
97
|
+
location: Location.hash(uri, variable.line - 1),
|
98
|
+
containerName: variable.scope.name
|
99
|
+
}
|
100
|
+
end
|
101
|
+
tags = tags.compact.reject { |tag| tag[:name].nil? || tag[:name] == RubyLanguageServer::ScopeData::Scope::TYPE_BLOCK }
|
96
102
|
# RubyLanguageServer.logger.debug("Raw tags for #{uri}: #{tags}")
|
97
103
|
# If you don't reverse the list then atom? won't be able to find the
|
98
104
|
# container and containers will get duplicated.
|
@@ -106,18 +112,32 @@ module RubyLanguageServer
|
|
106
112
|
@tags
|
107
113
|
end
|
108
114
|
|
109
|
-
def
|
110
|
-
|
111
|
-
if
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
+
def update_text(new_text)
|
116
|
+
RubyLanguageServer.logger.debug("update_text for #{uri}")
|
117
|
+
return true if new_text == text
|
118
|
+
|
119
|
+
RubyLanguageServer.logger.debug('Changed!')
|
120
|
+
update(text: new_text, refresh_root_scope: true)
|
121
|
+
end
|
122
|
+
|
123
|
+
def refresh_scopes_if_needed
|
124
|
+
return unless refresh_root_scope
|
115
125
|
|
116
|
-
|
117
|
-
|
118
|
-
|
126
|
+
RubyLanguageServer.logger.debug("Asking about root_scope for #{uri}")
|
127
|
+
RubyLanguageServer::ScopeData::Variable.where(code_file_id: self).scoping do
|
128
|
+
RubyLanguageServer::ScopeData::Scope.where(code_file_id: self).scoping do
|
129
|
+
self.class.transaction do
|
130
|
+
scopes.clear
|
131
|
+
variables.clear
|
132
|
+
new_root = ScopeParser.new(text).root_scope
|
133
|
+
RubyLanguageServer.logger.debug("new_root.children #{new_root.children.as_json}") if new_root&.children
|
134
|
+
raise ActiveRecord::Rollback if new_root.nil? || new_root.children.blank?
|
135
|
+
|
136
|
+
update_attribute(:refresh_root_scope, false)
|
137
|
+
new_root
|
138
|
+
end
|
139
|
+
end
|
119
140
|
end
|
120
|
-
@root_scope
|
121
141
|
end
|
122
142
|
|
123
143
|
# Returns the context of what is being typed in the given line
|
@@ -25,10 +25,10 @@ module RubyLanguageServer
|
|
25
25
|
|
26
26
|
class << self
|
27
27
|
def completion(context, context_scope, scopes)
|
28
|
-
RubyLanguageServer.logger.debug("completion(#{context}, #{
|
28
|
+
RubyLanguageServer.logger.debug("completion(#{context}, #{scopes.map(&:name)})")
|
29
29
|
completions =
|
30
30
|
if context.length < 2
|
31
|
-
scope_completions(context.last,
|
31
|
+
scope_completions(context.last, scopes)
|
32
32
|
else
|
33
33
|
scope_completions_in_target_context(context, context_scope, scopes)
|
34
34
|
end
|
@@ -44,12 +44,13 @@ module RubyLanguageServer
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def scope_with_name(name, scopes)
|
47
|
+
return scopes.where(name: name).first if scopes.respond_to?(:where)
|
48
|
+
|
47
49
|
scopes.detect { |scope| scope.name == name }
|
48
50
|
end
|
49
51
|
|
50
52
|
def scope_completions_in_target_context(context, context_scope, scopes)
|
51
|
-
|
52
|
-
context_word = working_array[-2]
|
53
|
+
context_word = context[-2]
|
53
54
|
if context_word.match?(/^[A-Z]/)
|
54
55
|
scope = scope_with_name(context_word, scopes)
|
55
56
|
else
|
@@ -59,22 +60,22 @@ module RubyLanguageServer
|
|
59
60
|
end
|
60
61
|
scope ||= context_scope
|
61
62
|
RubyLanguageServer.logger.debug("scope: #{scope}")
|
62
|
-
scope_completions(context.last, scope.
|
63
|
+
scope_completions(context.last, [scope] + scopes.includes(:variables))
|
63
64
|
end
|
64
65
|
|
65
66
|
def scope_completions(word, scopes)
|
66
67
|
words = {}
|
67
68
|
scopes.each_with_object(words) do |scope, words_hash|
|
68
|
-
scope.children.
|
69
|
+
scope.children.method_scopes.each do |method_scope|
|
69
70
|
words_hash[method_scope.name] ||= {
|
70
71
|
depth: scope.depth,
|
71
|
-
type: method_scope.
|
72
|
+
type: method_scope.class_type
|
72
73
|
}
|
73
74
|
end
|
74
75
|
scope.variables.each do |variable|
|
75
76
|
words_hash[variable.name] ||= {
|
76
77
|
depth: scope.depth,
|
77
|
-
type: variable.
|
78
|
+
type: variable.variable_type
|
78
79
|
}
|
79
80
|
end
|
80
81
|
end
|
@@ -4,8 +4,9 @@ require 'json'
|
|
4
4
|
|
5
5
|
module RubyLanguageServer
|
6
6
|
class IO
|
7
|
-
def initialize(server)
|
7
|
+
def initialize(server, mutex)
|
8
8
|
@server = server
|
9
|
+
@mutex = mutex
|
9
10
|
server.io = self
|
10
11
|
loop do
|
11
12
|
(id, response) = process_request(STDIN)
|
@@ -57,7 +58,11 @@ module RubyLanguageServer
|
|
57
58
|
params = request_json['params']
|
58
59
|
method_name = "on_#{method_name.gsub(/[^\w]/, '_')}"
|
59
60
|
if @server.respond_to? method_name
|
60
|
-
|
61
|
+
RubyLanguageServer.logger.debug 'Locking io'
|
62
|
+
response = @mutex.synchronize do
|
63
|
+
@server.send(method_name, params)
|
64
|
+
end
|
65
|
+
RubyLanguageServer.logger.debug 'UNLocking io'
|
61
66
|
exit(true) if response == 'EXIT'
|
62
67
|
return id, response
|
63
68
|
else
|
@@ -3,14 +3,14 @@
|
|
3
3
|
module RubyLanguageServer
|
4
4
|
# Hash factories for the language server
|
5
5
|
module Location
|
6
|
-
def self.hash(uri, start_line, start_character =
|
6
|
+
def self.hash(uri, start_line, start_character = 0, end_line = nil, end_character = nil)
|
7
7
|
{
|
8
8
|
uri: uri,
|
9
9
|
range: position_hash(start_line, start_character, end_line, end_character)
|
10
10
|
}
|
11
11
|
end
|
12
12
|
|
13
|
-
def self.position_hash(start_line, start_character =
|
13
|
+
def self.position_hash(start_line, start_character = 0, end_line = nil, end_character = nil)
|
14
14
|
end_line ||= start_line
|
15
15
|
end_character ||= start_character
|
16
16
|
{
|
@@ -49,13 +49,8 @@ module RubyLanguageServer
|
|
49
49
|
|
50
50
|
@root_uri = "file://#{path}"
|
51
51
|
# This is {uri: code_file} where content stuff is like
|
52
|
-
@uri_code_file_hash = {}
|
53
|
-
@update_mutext = Mutex.new
|
54
|
-
|
55
52
|
@additional_gems_installed = false
|
56
53
|
@additional_gem_mutex = Mutex.new
|
57
|
-
|
58
|
-
scan_all_project_files
|
59
54
|
end
|
60
55
|
|
61
56
|
def diagnostics_ready?
|
@@ -90,13 +85,14 @@ module RubyLanguageServer
|
|
90
85
|
end
|
91
86
|
|
92
87
|
def all_scopes
|
93
|
-
|
88
|
+
RubyLanguageServer::ScopeData::Scope.all
|
94
89
|
end
|
95
90
|
|
96
91
|
# Return the list of scopes [deepest, parent, ..., Object]
|
97
92
|
def scopes_at(uri, position)
|
98
|
-
|
99
|
-
|
93
|
+
code_file = code_file_for_uri(uri)
|
94
|
+
code_file.refresh_scopes_if_needed
|
95
|
+
code_file.scopes.for_line(position.line).where.not(path: nil).by_path_length
|
100
96
|
end
|
101
97
|
|
102
98
|
def completion_at(uri, position)
|
@@ -104,11 +100,12 @@ module RubyLanguageServer
|
|
104
100
|
relative_position.character = relative_position.character # To get before the . or ::
|
105
101
|
# RubyLanguageServer.logger.debug("relative_position #{relative_position}")
|
106
102
|
RubyLanguageServer.logger.debug("scopes_at(uri, position) #{scopes_at(uri, position).map(&:name)}")
|
107
|
-
|
103
|
+
position_scopes = scopes_at(uri, position) || RubyLanguageServer::ScopeData::Scope.where(id: root_scope_for(uri).id)
|
104
|
+
context_scope = position_scopes.first
|
108
105
|
context = context_at_location(uri, relative_position)
|
109
106
|
return {} if context.nil? || context == ''
|
110
107
|
|
111
|
-
RubyLanguageServer::Completion.completion(context, context_scope,
|
108
|
+
RubyLanguageServer::Completion.completion(context, context_scope, position_scopes)
|
112
109
|
end
|
113
110
|
|
114
111
|
# interface CompletionItem {
|
@@ -185,29 +182,37 @@ module RubyLanguageServer
|
|
185
182
|
# data?: any
|
186
183
|
# }
|
187
184
|
|
188
|
-
def scan_all_project_files
|
185
|
+
def scan_all_project_files(mutex)
|
189
186
|
project_ruby_files = Dir.glob("#{self.class.root_path}**/*.rb")
|
190
187
|
Thread.new do
|
188
|
+
RubyLanguageServer.logger.error('Threading up!')
|
191
189
|
project_ruby_files.each do |container_path|
|
190
|
+
# Let's not preload spec/test or vendor - yet..
|
191
|
+
next if container_path.match?(/^(.?spec|test|vendor)/)
|
192
|
+
|
192
193
|
text = File.read(container_path)
|
193
194
|
relative_path = container_path.delete_prefix(self.class.root_path)
|
194
195
|
host_uri = @root_uri + relative_path
|
195
|
-
|
196
|
+
RubyLanguageServer.logger.debug "Locking scan for #{container_path}"
|
197
|
+
mutex.synchronize do
|
198
|
+
RubyLanguageServer.logger.debug("Threading #{host_uri}")
|
199
|
+
update_document_content(host_uri, text)
|
200
|
+
code_file_for_uri(host_uri).refresh_scopes_if_needed
|
201
|
+
end
|
202
|
+
RubyLanguageServer.logger.debug "Unlocking scan for #{container_path}"
|
196
203
|
end
|
197
204
|
end
|
198
205
|
end
|
199
206
|
|
200
207
|
# returns diagnostic info (if possible)
|
201
208
|
def update_document_content(uri, text)
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
diagnostics_ready? ? updated_diagnostics_for_codefile(code_file) : []
|
210
|
-
end
|
209
|
+
RubyLanguageServer.logger.debug("update_document_content: #{uri}")
|
210
|
+
# RubyLanguageServer.logger.error("@root_path: #{@root_path}")
|
211
|
+
code_file = code_file_for_uri(uri)
|
212
|
+
return code_file.diagnostics if code_file.text == text
|
213
|
+
|
214
|
+
code_file.update_text(text)
|
215
|
+
diagnostics_ready? ? updated_diagnostics_for_codefile(code_file) : []
|
211
216
|
end
|
212
217
|
|
213
218
|
def updated_diagnostics_for_codefile(code_file)
|
@@ -224,19 +229,19 @@ module RubyLanguageServer
|
|
224
229
|
end
|
225
230
|
|
226
231
|
def word_at_location(uri, position)
|
227
|
-
context_at_location(uri, position)
|
232
|
+
context_at_location(uri, position)&.last
|
228
233
|
end
|
229
234
|
|
230
235
|
def possible_definitions(uri, position)
|
231
236
|
name = word_at_location(uri, position)
|
232
|
-
return {} if name
|
237
|
+
return {} if name.blank?
|
233
238
|
|
234
239
|
name = 'initialize' if name == 'new'
|
235
240
|
scope = scopes_at(uri, position).first
|
236
241
|
results = scope_definitions_for(name, scope, uri)
|
237
242
|
return results unless results.empty?
|
238
243
|
|
239
|
-
project_definitions_for(name
|
244
|
+
project_definitions_for(name)
|
240
245
|
end
|
241
246
|
|
242
247
|
def scope_definitions_for(name, scope, uri)
|
@@ -244,7 +249,7 @@ module RubyLanguageServer
|
|
244
249
|
return_array = []
|
245
250
|
while check_scope
|
246
251
|
scope.variables.each do |variable|
|
247
|
-
return_array << Location.hash(uri, variable.line) if variable.name == name
|
252
|
+
return_array << Location.hash(uri.delete_prefix(self.class.root_uri), variable.line - 1) if variable.name == name
|
248
253
|
end
|
249
254
|
check_scope = check_scope.parent
|
250
255
|
end
|
@@ -252,25 +257,18 @@ module RubyLanguageServer
|
|
252
257
|
return_array.uniq
|
253
258
|
end
|
254
259
|
|
255
|
-
def project_definitions_for(name
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
match_tags = tags.select { |tag| tag[:name] == name }
|
262
|
-
match_tags.each do |tag|
|
263
|
-
ary << Location.hash(uri, tag[:location][:range][:start][:line] + 1)
|
264
|
-
end
|
260
|
+
def project_definitions_for(name)
|
261
|
+
scopes = RubyLanguageServer::ScopeData::Scope.where(name: name)
|
262
|
+
variables = RubyLanguageServer::ScopeData::Variable.constant_variables.where(name: name)
|
263
|
+
(scopes + variables).map do |thing|
|
264
|
+
Location.hash(thing.code_file.uri.delete_prefix(self.class.root_uri), thing.top_line)
|
265
265
|
end
|
266
|
-
return_array
|
267
266
|
end
|
268
267
|
|
269
268
|
private
|
270
269
|
|
271
270
|
def code_file_for_uri(uri)
|
272
|
-
code_file =
|
273
|
-
code_file = @uri_code_file_hash[uri] = CodeFile.new(uri, nil) if code_file.nil?
|
271
|
+
code_file = CodeFile.find_by_uri(uri) || CodeFile.build(uri, nil)
|
274
272
|
code_file
|
275
273
|
end
|
276
274
|
|
@@ -1,14 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_record'
|
4
|
+
|
3
5
|
module RubyLanguageServer
|
4
6
|
module ScopeData
|
5
|
-
class Base
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
class Base < ActiveRecord::Base
|
8
|
+
self.abstract_class = true
|
9
|
+
|
10
|
+
TYPE_MODULE = 'module'
|
11
|
+
TYPE_CLASS = 'class'
|
12
|
+
TYPE_METHOD = 'method'
|
13
|
+
TYPE_BLOCK = 'block'
|
14
|
+
TYPE_ROOT = 'root'
|
15
|
+
TYPE_VARIABLE = 'variable'
|
16
|
+
|
17
|
+
BLOCK_NAME = 'block'
|
12
18
|
|
13
19
|
JoinHash = {
|
14
20
|
TYPE_MODULE => '::',
|
@@ -1,103 +1,103 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_record'
|
4
|
+
|
3
5
|
module RubyLanguageServer
|
4
6
|
module ScopeData
|
5
7
|
# The Scope class is basically a container with context.
|
6
8
|
# It is used to track top & bottom line, variables in this scope, constants, and children - which could be functions, classes, blocks, etc. Anything that adds scope.
|
7
9
|
class Scope < Base
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
attr_accessor :depth # how many parent scopes
|
13
|
-
attr_accessor :parent # parent scope
|
14
|
-
attr_accessor :variables # variables declared in this scope
|
15
|
-
attr_accessor :constants # constants declared in this scope
|
16
|
-
attr_accessor :children # child scopes
|
17
|
-
attr_accessor :name # method
|
18
|
-
attr_accessor :superclass_name # superclass name
|
19
|
-
|
20
|
-
def initialize(parent = nil, type = TYPE_ROOT, name = '', top_line = 1, _column = 1)
|
21
|
-
super()
|
22
|
-
@parent = parent
|
23
|
-
@type = type
|
24
|
-
@name = name
|
25
|
-
@top_line = top_line
|
26
|
-
@depth = parent.nil? ? 0 : parent.depth + 1
|
27
|
-
if type == TYPE_ROOT
|
28
|
-
@full_name = nil
|
29
|
-
else
|
30
|
-
@full_name = [parent ? parent.full_name : nil, @name].compact.join(JoinHash[type])
|
31
|
-
end
|
32
|
-
@children = []
|
33
|
-
@variables = []
|
34
|
-
@constants = []
|
35
|
-
end
|
10
|
+
has_many :variables, dependent: :destroy
|
11
|
+
belongs_to :code_file
|
12
|
+
belongs_to :parent, class_name: 'Scope', optional: true
|
13
|
+
has_many :children, class_name: 'Scope', foreign_key: :parent_id
|
36
14
|
|
37
|
-
|
38
|
-
|
39
|
-
|
15
|
+
scope :method_scopes, -> { where(class_type: TYPE_METHOD) }
|
16
|
+
scope :for_line, ->(line) { where('top_line <= ? AND bottom_line >= ?', line, line).or(where(parent_id: nil)) }
|
17
|
+
scope :by_path_length, -> { order('length(path) DESC') }
|
18
|
+
# attr_accessor :top_line # first line
|
19
|
+
# attr_accessor :bottom_line # last line
|
20
|
+
# attr_accessor :parent # parent scope
|
21
|
+
# attr_accessor :constants # constants declared in this scope
|
22
|
+
# attr_accessor :name # method
|
23
|
+
# attr_accessor :superclass_name # superclass name
|
40
24
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
25
|
+
def self.build(parent = nil, type = TYPE_ROOT, name = '', top_line = 1, column = 1)
|
26
|
+
full_name = [parent ? parent.full_name : nil, name].compact.join(JoinHash[type])
|
27
|
+
create!(
|
28
|
+
parent: parent,
|
29
|
+
top_line: top_line,
|
30
|
+
column: column,
|
31
|
+
name: name,
|
32
|
+
path: full_name,
|
33
|
+
class_type: type
|
34
|
+
)
|
51
35
|
end
|
52
36
|
|
53
37
|
def full_name
|
54
|
-
@full_name || @name
|
38
|
+
path # @full_name || @name
|
55
39
|
end
|
56
40
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
60
|
-
|
41
|
+
def depth
|
42
|
+
return 0 if path.blank?
|
43
|
+
|
44
|
+
scope_parts.count
|
61
45
|
end
|
62
46
|
|
63
47
|
# Return the deepest child scopes of this scope - and on up.
|
64
48
|
# Not done recuresively because we don't really need to.
|
65
49
|
# Normally called on a root scope.
|
66
|
-
def scopes_at(position)
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
deepest_scope = matching_scopes.max_by(&:depth)
|
74
|
-
deepest_scope.self_and_ancestors
|
75
|
-
end
|
76
|
-
|
77
|
-
def each
|
78
|
-
self_and_descendants.each { |member| yield member }
|
79
|
-
end
|
50
|
+
# def scopes_at(position)
|
51
|
+
# line = position.line
|
52
|
+
# matching_scopes = self_and_descendants.where('top_line <= ?', line).where('bottom_line >= ?', line)
|
53
|
+
# deepest_scope = matching_scopes.max_by(&:depth)
|
54
|
+
# deepest_scope&.self_and_ancestors || []
|
55
|
+
# end
|
80
56
|
|
81
57
|
# Self and all descendents flattened into array
|
82
58
|
def self_and_descendants
|
83
|
-
|
59
|
+
return Scope.all if root_scope?
|
60
|
+
|
61
|
+
Scope.where('path like ?', "#{path}%")
|
84
62
|
end
|
85
63
|
|
86
64
|
def descendants
|
87
|
-
|
65
|
+
Scope.where('path like ?', "#{path}_%")
|
88
66
|
end
|
89
67
|
|
90
68
|
# [self, parent, parent.parent...]
|
91
|
-
def self_and_ancestors
|
92
|
-
|
93
|
-
|
69
|
+
# def self_and_ancestors
|
70
|
+
# return [self] if path.blank?
|
71
|
+
# remaining_path = path.dup
|
72
|
+
# ancestor_paths = scope_parts.inject([]) do |ary, scope_part|
|
73
|
+
# ary << remaining_path
|
74
|
+
# remaining_path =
|
75
|
+
# ary
|
76
|
+
# end
|
77
|
+
# [self, parent&.self_and_ancestors].flatten.compact
|
78
|
+
# end
|
94
79
|
|
95
80
|
def set_superclass_name(partial)
|
96
81
|
if partial.start_with?('::')
|
97
|
-
|
82
|
+
self.superclass_name = partial.gsub(/^::/, '')
|
98
83
|
else
|
99
|
-
|
84
|
+
self.superclass_name = [parent ? parent.full_name : nil, partial].compact.join(JoinHash[class_type])
|
100
85
|
end
|
86
|
+
save!
|
87
|
+
end
|
88
|
+
|
89
|
+
def root_scope?
|
90
|
+
class_type == TYPE_ROOT
|
91
|
+
end
|
92
|
+
|
93
|
+
def block_scope?
|
94
|
+
class_type == TYPE_BLOCK
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def scope_parts
|
100
|
+
path&.split(/#{JoinHash.values.reject(&:blank?).uniq.join('|')}/)
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
@@ -1,24 +1,44 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_record'
|
4
|
+
|
3
5
|
module RubyLanguageServer
|
4
6
|
module ScopeData
|
5
7
|
class Variable < Base
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
belongs_to :code_file
|
9
|
+
belongs_to :scope
|
10
|
+
|
11
|
+
scope :constant_variables, -> { where("SUBSTR(name, 1, 1) between ('A') and ('Z')") }
|
12
|
+
|
13
|
+
# attr_accessor :line # line
|
14
|
+
# attr_accessor :column # column
|
15
|
+
# attr_accessor :name # name
|
16
|
+
# attr_accessor :path # Module::Class name
|
10
17
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
def self.build(scope, name, line = 1, column = 1, type = TYPE_VARIABLE)
|
19
|
+
path = [scope.full_name, name].join(JoinHash[TYPE_VARIABLE])
|
20
|
+
create!(
|
21
|
+
line: line,
|
22
|
+
column: column,
|
23
|
+
name: name,
|
24
|
+
path: path,
|
25
|
+
variable_type: type
|
26
|
+
)
|
27
|
+
# @name = name
|
28
|
+
# @line = line
|
29
|
+
# @column = column
|
30
|
+
# @full_name =
|
31
|
+
# @type = type
|
32
|
+
# raise "bogus variable #{inspect}" unless @name.instance_of? String
|
18
33
|
end
|
19
34
|
|
20
35
|
def constant?
|
21
|
-
|
36
|
+
!name&.match(/^[A-Z]/).nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
# Convenience for tags
|
40
|
+
def top_line
|
41
|
+
line
|
22
42
|
end
|
23
43
|
end
|
24
44
|
end
|
@@ -28,7 +28,7 @@ module RubyLanguageServer
|
|
28
28
|
def root_scope
|
29
29
|
return @root_scope unless @root_scope.nil?
|
30
30
|
|
31
|
-
@root_scope =
|
31
|
+
@root_scope = ScopeData::Scope.where(path: nil, class_type: ScopeData::Scope::TYPE_ROOT).first_or_create!
|
32
32
|
@current_scope = @root_scope
|
33
33
|
process(@sexp)
|
34
34
|
@root_scope
|
@@ -117,13 +117,14 @@ module RubyLanguageServer
|
|
117
117
|
# add_scope(args, rest, ScopeData::Scope::TYPE_BLOCK)
|
118
118
|
unless @current_scope == scope
|
119
119
|
scope.bottom_line = [scope&.bottom_line, @current_scope.bottom_line].compact.max
|
120
|
+
scope.save!
|
120
121
|
pop_scope
|
121
122
|
end
|
122
123
|
end
|
123
124
|
|
124
125
|
def on_do_block(args, rest)
|
125
126
|
((_, ((_, (_, (_, _name, (line, column))))))) = args
|
126
|
-
push_scope(ScopeData::Scope::TYPE_BLOCK,
|
127
|
+
push_scope(ScopeData::Scope::TYPE_BLOCK, 'block', line, column, false)
|
127
128
|
process(args)
|
128
129
|
process(rest)
|
129
130
|
pop_scope
|
@@ -268,17 +269,22 @@ module RubyLanguageServer
|
|
268
269
|
private
|
269
270
|
|
270
271
|
def add_variable(name, line, column, scope = @current_scope)
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
272
|
+
scope.variables.where(name: name).first_or_create(line: line, column: column)
|
273
|
+
if scope.top_line.blank?
|
274
|
+
scope.top_line = line
|
275
|
+
scope.save!
|
276
|
+
end
|
277
|
+
# new_variable = ScopeData::Variable.build(scope, name, line, column)
|
278
|
+
# # blocks don't declare their first line in the parser
|
279
|
+
# scope.top_line ||= line
|
280
|
+
# scope.variables << new_variable unless scope.has_variable_or_constant?(new_variable)
|
275
281
|
end
|
276
282
|
|
277
283
|
def add_ivar(name, line, column)
|
278
284
|
scope = @current_scope
|
279
285
|
unless scope == root_scope
|
280
286
|
ivar_scope_types = [ScopeData::Base::TYPE_CLASS, ScopeData::Base::TYPE_MODULE]
|
281
|
-
while !ivar_scope_types.include?(scope.
|
287
|
+
while !ivar_scope_types.include?(scope.class_type) && !scope.parent.nil?
|
282
288
|
scope = scope.parent
|
283
289
|
end
|
284
290
|
end
|
@@ -299,20 +305,9 @@ module RubyLanguageServer
|
|
299
305
|
|
300
306
|
def push_scope(type, name, top_line, column, close_siblings = true)
|
301
307
|
close_sibling_scopes(top_line) if close_siblings
|
302
|
-
|
303
|
-
# But if we're adding a class, we don't care that it's in Object.
|
304
|
-
new_scope =
|
305
|
-
if (type_is_class_or_module(type) && (@current_scope == root_scope))
|
306
|
-
ScopeData::Scope.new(nil, type, name, top_line, column)
|
307
|
-
else
|
308
|
-
ScopeData::Scope.new(@current_scope, type, name, top_line, column)
|
309
|
-
end
|
308
|
+
new_scope = ScopeData::Scope.build(@current_scope, type, name, top_line, column)
|
310
309
|
new_scope.bottom_line = @lines
|
311
|
-
|
312
|
-
root_scope.children << new_scope
|
313
|
-
else
|
314
|
-
@current_scope.children << new_scope
|
315
|
-
end
|
310
|
+
new_scope.save!
|
316
311
|
@current_scope = new_scope
|
317
312
|
end
|
318
313
|
|
@@ -320,19 +315,15 @@ module RubyLanguageServer
|
|
320
315
|
# The notion is that when you start the next scope, all the previous peers and unclosed descendents of the previous peer should be closed.
|
321
316
|
def close_sibling_scopes(line)
|
322
317
|
parent_scope = @current_scope
|
323
|
-
parent_scope&.descendants&.each
|
318
|
+
parent_scope&.descendants&.each do |scope|
|
319
|
+
scope.bottom_line = [scope.bottom_line, line - 1].compact.min
|
320
|
+
scope.save!
|
321
|
+
end
|
324
322
|
end
|
325
323
|
|
326
324
|
def pop_scope
|
327
325
|
@current_scope = @current_scope.parent || root_scope # in case we are leaving a root class/module
|
328
326
|
end
|
329
|
-
|
330
|
-
def new_root_scope
|
331
|
-
ScopeData::Scope.new.tap do |scope|
|
332
|
-
scope.type = ScopeData::Scope::TYPE_ROOT
|
333
|
-
scope.name = nil
|
334
|
-
end
|
335
|
-
end
|
336
327
|
end
|
337
328
|
|
338
329
|
# This class builds on Ripper's sexp processor to add ruby and rails magic.
|
@@ -7,11 +7,17 @@ module RubyLanguageServer
|
|
7
7
|
class Server
|
8
8
|
attr_accessor :io
|
9
9
|
|
10
|
+
def initialize(mutex)
|
11
|
+
@mutex = mutex
|
12
|
+
end
|
13
|
+
|
10
14
|
def on_initialize(params)
|
11
15
|
RubyLanguageServer.logger.info("on_initialize: #{params}")
|
16
|
+
RubyLanguageServer::CodeFile.all # Just to warm up active_record.
|
12
17
|
root_path = params['rootPath']
|
13
18
|
root_uri = params['rootUri']
|
14
19
|
@project_manager = ProjectManager.new(root_path, root_uri)
|
20
|
+
@project_manager.scan_all_project_files(@mutex)
|
15
21
|
gem_string = ENV.fetch('ADDITIONAL_GEMS') {}
|
16
22
|
gem_array = (gem_string.split(',').compact.map(&:strip).reject { |string| string == '' } if gem_string && !gem_string.empty?)
|
17
23
|
@project_manager.install_additional_gems(gem_array)
|
@@ -45,6 +45,9 @@ Gem::Specification.new do |spec|
|
|
45
45
|
spec.add_dependency 'amatch' # in c
|
46
46
|
spec.add_dependency 'fuzzy_match' # completion matching
|
47
47
|
|
48
|
+
spec.add_dependency 'activerecord'
|
49
|
+
spec.add_dependency 'sqlite3'
|
50
|
+
|
48
51
|
spec.add_development_dependency 'guard'
|
49
52
|
spec.add_development_dependency 'guard-minitest'
|
50
53
|
spec.add_development_dependency 'guard-rubocop'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_language_server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kurt Werle
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-08-
|
11
|
+
date: 2019-08-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -108,6 +108,34 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: activerecord
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: sqlite3
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
111
139
|
- !ruby/object:Gem::Dependency
|
112
140
|
name: guard
|
113
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -256,8 +284,12 @@ files:
|
|
256
284
|
- bin/console
|
257
285
|
- bin/setup
|
258
286
|
- exe/ruby_language_server
|
287
|
+
- lib/config/initializers/active_record.rb
|
288
|
+
- lib/config/initializers/sqlite.rb
|
289
|
+
- lib/db/schema.rb
|
259
290
|
- lib/resources/fallback_rubocop.yml
|
260
291
|
- lib/ruby_language_server.rb
|
292
|
+
- lib/ruby_language_server/application.rb
|
261
293
|
- lib/ruby_language_server/code_file.rb
|
262
294
|
- lib/ruby_language_server/completion.rb
|
263
295
|
- lib/ruby_language_server/gem_installer.rb
|