ruby_language_server 0.2.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 +7 -0
- data/CHANGELOG.txt +67 -0
- data/FAQ_ROADMAP.md +30 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +111 -0
- data/Guardfile +36 -0
- data/LICENSE +21 -0
- data/Makefile +35 -0
- data/README.md +55 -0
- data/Rakefile +17 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/exe/ruby_language_server +9 -0
- data/lib/ruby_language_server/code_file.rb +129 -0
- data/lib/ruby_language_server/completion.rb +87 -0
- data/lib/ruby_language_server/gem_installer.rb +24 -0
- data/lib/ruby_language_server/good_cop.rb +125 -0
- data/lib/ruby_language_server/io.rb +130 -0
- data/lib/ruby_language_server/line_context.rb +39 -0
- data/lib/ruby_language_server/location.rb +29 -0
- data/lib/ruby_language_server/logger.rb +14 -0
- data/lib/ruby_language_server/project_manager.rb +231 -0
- data/lib/ruby_language_server/scope_data/base.rb +23 -0
- data/lib/ruby_language_server/scope_data/scope.rb +104 -0
- data/lib/ruby_language_server/scope_data/variable.rb +25 -0
- data/lib/ruby_language_server/scope_parser.rb +334 -0
- data/lib/ruby_language_server/scope_parser_commands/rails_commands.rb +29 -0
- data/lib/ruby_language_server/scope_parser_commands/rake_commands.rb +31 -0
- data/lib/ruby_language_server/scope_parser_commands/readme.txt +9 -0
- data/lib/ruby_language_server/scope_parser_commands/rspec_commands.rb +26 -0
- data/lib/ruby_language_server/scope_parser_commands/ruby_commands.rb +70 -0
- data/lib/ruby_language_server/server.rb +123 -0
- data/lib/ruby_language_server/version.rb +5 -0
- data/lib/ruby_language_server.rb +14 -0
- data/ruby_language_server.gemspec +56 -0
- metadata +293 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 403609bb04e3734281518bc6a175b6e839e6b731d684dd5716f31e91bb7e1d98
|
4
|
+
data.tar.gz: b7c597616a85977982dc2ddbcb8b8c7d896a1829904fa19dfbb52951da6895b6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cfbd3c60687d08b1f9e19bc632e9d8f4ceb0f5e579e8d6b9edd7e7cf81403dac9b0c7a795fac403b550950b7c1ef615095ad94bbbefe80662390edbdd16f13b7
|
7
|
+
data.tar.gz: 784a22cdadad7ebdf6f25ce35a78e2cff90aa148dbf62c88e650ba42e7ce522df59e9758e9de166f99308e5226b9100505c73a7f9ee7c470575435072926afae
|
data/CHANGELOG.txt
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
#### 0.2.0 Mon Dec 24 18:19:55 PST 2018
|
4
|
+
|
5
|
+
* Support for rake files
|
6
|
+
* Support for rspec files
|
7
|
+
* Removed ripper tags & refactoring
|
8
|
+
* Better handling of parameter variables
|
9
|
+
* Probably better performance (not measured, but reasonably sure)
|
10
|
+
|
11
|
+
#### 0.1.1 Fri Dec 21 16:48:46 PST 2018
|
12
|
+
|
13
|
+
* Fix a few little issues that came to light while updating ide-ruby
|
14
|
+
|
15
|
+
#### 0.1.0 Fri Dec 21 15:19:00 PST 2018
|
16
|
+
|
17
|
+
* Refactor server & project_manager
|
18
|
+
* fix bugs with def self.method and class << self (https://github.com/kwerle/ide-ruby/issues/19)
|
19
|
+
* Add support for additional rubocop gems (https://github.com/kwerle/ide-ruby/issues/17)
|
20
|
+
|
21
|
+
#### 0.0.9 Thu Oct 18 17:48:35 PDT 2018
|
22
|
+
|
23
|
+
* Refactor & some RuboCop
|
24
|
+
* Fix most of https://github.com/kwerle/ide-ruby/issues/18
|
25
|
+
* * Rubocop issues: no inline support,
|
26
|
+
* * invalid snake_case warnings,
|
27
|
+
* * NOT missing "rubocop failed to load" indicator
|
28
|
+
* More work on completion stuff
|
29
|
+
|
30
|
+
#### 0.0.8 Thu Jul 19 00:01:25 PDT 2018
|
31
|
+
|
32
|
+
* Bump ruby version
|
33
|
+
* Fix the initial background thread
|
34
|
+
* Refactor
|
35
|
+
* Ignore setting text to the same
|
36
|
+
|
37
|
+
#### 0.0.7 Thu Jul 12 16:11:26 PDT 2018
|
38
|
+
|
39
|
+
* Whoops - forgot to merge changes in.
|
40
|
+
|
41
|
+
#### 0.0.6 Thu Jul 12 16:11:26 PDT 2018
|
42
|
+
|
43
|
+
* Fix RuboCop again. Sigh.
|
44
|
+
|
45
|
+
#### 0.0.5 Thu Jul 12 15:07:58 PDT 2018
|
46
|
+
|
47
|
+
* Parse all project files on startup
|
48
|
+
* Fix possible issue with RuboCop config
|
49
|
+
|
50
|
+
#### 0.0.4 Tue Mar 20 19:39:06 PDT 2018
|
51
|
+
|
52
|
+
* Provide support for .rubocop.yml. This will work once I update ide-ruby.
|
53
|
+
|
54
|
+
#### 0.0.3
|
55
|
+
|
56
|
+
* Uhh. What did I do? Looks like a bunch.
|
57
|
+
|
58
|
+
#### 0.0.2 Mon Nov 13 20:49:54 PST 2017
|
59
|
+
|
60
|
+
* Fix rails has_one(etc) so it gets the right parent
|
61
|
+
|
62
|
+
#### Sat Nov 11 07:59:25 PST 2017
|
63
|
+
|
64
|
+
* Outline working but buggy (double listing for parents)
|
65
|
+
* Go to definition working but lazy (have to visit a file before definitions 'known')
|
66
|
+
* Completions working in a very basic way - local scope context only
|
67
|
+
* Linter not working (not being called, NYI)
|
data/FAQ_ROADMAP.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Why docker?
|
2
|
+
|
3
|
+
Docker guarantees me a target environment. I don't have to wonder which version of ruby you have installed or if you can build all the gems. I may also scale this thing to multiple processes and a database and a cache server.
|
4
|
+
|
5
|
+
One requirement: docker.
|
6
|
+
|
7
|
+
# Why not [language_server-ruby](https://github.com/mtsmfm/language_server-ruby)
|
8
|
+
|
9
|
+
My goals are not as high. I just want this stuff working now. I hope some day there will be merging.
|
10
|
+
|
11
|
+
# A little light on tests?
|
12
|
+
|
13
|
+
Oh yeah. Tests are mostly for when you know where you're going. I'm doing a whole lot of this by the seat of my pants. OMG, please write tests.
|
14
|
+
|
15
|
+
# Next?
|
16
|
+
|
17
|
+
* Getting a definition just looks at the tags - but tags do not include parameters passed in a method - which seems like it should. We are functional, right?
|
18
|
+
* Guess a symbol's class.
|
19
|
+
* `def some_method(parent)` should guess that parent is a Parent.
|
20
|
+
* Be smarter about context and completions
|
21
|
+
* `class << self` is busted. Fix it.
|
22
|
+
* Fix the outline. Seriously - why isn't it working as expected?
|
23
|
+
* Symbol pairs. If I have typed 'foo.bar' a thousand times in my project, the next time I type 'foo.' the IDE had damn well ought to show me 'bar' as a completion option.
|
24
|
+
* It makes me very sad that I could not get this working using sockets. Tried and tried and failed.
|
25
|
+
|
26
|
+
# Then?
|
27
|
+
|
28
|
+
* Pay special attention to the project's Gemfile. Install all the gems (we can). Integrate with gem server?
|
29
|
+
* Full scan of installed gems?
|
30
|
+
* Integrate class based scope logic. If I'm in Foo < Bar then I should see Bar's methods at just slightly lower priority than Foo's.
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ruby_language_server (0.2.0)
|
5
|
+
amatch
|
6
|
+
bundler
|
7
|
+
etc
|
8
|
+
fuzzy_match
|
9
|
+
json
|
10
|
+
rubocop
|
11
|
+
rubocop-rspec
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: https://rubygems.org/
|
15
|
+
specs:
|
16
|
+
amatch (0.4.0)
|
17
|
+
mize
|
18
|
+
tins (~> 1.0)
|
19
|
+
ast (2.4.0)
|
20
|
+
byebug (10.0.2)
|
21
|
+
coderay (1.1.2)
|
22
|
+
etc (1.0.1)
|
23
|
+
ffi (1.9.25)
|
24
|
+
formatador (0.2.5)
|
25
|
+
fuzzy_match (2.1.0)
|
26
|
+
guard (2.15.0)
|
27
|
+
formatador (>= 0.2.4)
|
28
|
+
listen (>= 2.7, < 4.0)
|
29
|
+
lumberjack (>= 1.0.12, < 2.0)
|
30
|
+
nenv (~> 0.1)
|
31
|
+
notiffany (~> 0.0)
|
32
|
+
pry (>= 0.9.12)
|
33
|
+
shellany (~> 0.0)
|
34
|
+
thor (>= 0.18.1)
|
35
|
+
guard-compat (1.2.1)
|
36
|
+
guard-minitest (2.4.6)
|
37
|
+
guard-compat (~> 1.2)
|
38
|
+
minitest (>= 3.0)
|
39
|
+
guard-rubocop (1.3.0)
|
40
|
+
guard (~> 2.0)
|
41
|
+
rubocop (~> 0.20)
|
42
|
+
jaro_winkler (1.5.1)
|
43
|
+
json (2.1.0)
|
44
|
+
listen (3.1.5)
|
45
|
+
rb-fsevent (~> 0.9, >= 0.9.4)
|
46
|
+
rb-inotify (~> 0.9, >= 0.9.7)
|
47
|
+
ruby_dep (~> 1.2)
|
48
|
+
lumberjack (1.0.13)
|
49
|
+
method_source (0.9.2)
|
50
|
+
minitest (5.11.3)
|
51
|
+
minitest-color (0.0.2)
|
52
|
+
minitest (~> 5)
|
53
|
+
mize (0.3.5)
|
54
|
+
protocol
|
55
|
+
nenv (0.3.0)
|
56
|
+
notiffany (0.1.1)
|
57
|
+
nenv (~> 0.1)
|
58
|
+
shellany (~> 0.0)
|
59
|
+
parallel (1.12.1)
|
60
|
+
parser (2.5.3.0)
|
61
|
+
ast (~> 2.4.0)
|
62
|
+
powerpack (0.1.2)
|
63
|
+
protocol (1.0.1)
|
64
|
+
ruby_parser (~> 3.0)
|
65
|
+
pry (0.12.2)
|
66
|
+
coderay (~> 1.1.0)
|
67
|
+
method_source (~> 0.9.0)
|
68
|
+
pry-byebug (3.6.0)
|
69
|
+
byebug (~> 10.0)
|
70
|
+
pry (~> 0.10)
|
71
|
+
rainbow (3.0.0)
|
72
|
+
rake (12.3.2)
|
73
|
+
rb-fsevent (0.10.3)
|
74
|
+
rb-inotify (0.10.0)
|
75
|
+
ffi (~> 1.0)
|
76
|
+
rubocop (0.61.1)
|
77
|
+
jaro_winkler (~> 1.5.1)
|
78
|
+
parallel (~> 1.10)
|
79
|
+
parser (>= 2.5, != 2.5.1.1)
|
80
|
+
powerpack (~> 0.1)
|
81
|
+
rainbow (>= 2.2.2, < 4.0)
|
82
|
+
ruby-progressbar (~> 1.7)
|
83
|
+
unicode-display_width (~> 1.4.0)
|
84
|
+
rubocop-rspec (1.30.1)
|
85
|
+
rubocop (>= 0.60.0)
|
86
|
+
ruby-progressbar (1.10.0)
|
87
|
+
ruby_dep (1.5.0)
|
88
|
+
ruby_parser (3.12.0)
|
89
|
+
sexp_processor (~> 4.9)
|
90
|
+
sexp_processor (4.11.0)
|
91
|
+
shellany (0.0.1)
|
92
|
+
thor (0.20.3)
|
93
|
+
tins (1.20.2)
|
94
|
+
unicode-display_width (1.4.1)
|
95
|
+
|
96
|
+
PLATFORMS
|
97
|
+
ruby
|
98
|
+
|
99
|
+
DEPENDENCIES
|
100
|
+
guard
|
101
|
+
guard-minitest
|
102
|
+
guard-rubocop
|
103
|
+
minitest
|
104
|
+
minitest-color
|
105
|
+
pry
|
106
|
+
pry-byebug
|
107
|
+
rake
|
108
|
+
ruby_language_server!
|
109
|
+
|
110
|
+
BUNDLED WITH
|
111
|
+
1.17.3
|
data/Guardfile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# A sample Guardfile
|
4
|
+
# More info at https://github.com/guard/guard#readme
|
5
|
+
|
6
|
+
## Uncomment and set this to only include directories you want to watch
|
7
|
+
# directories %w(app lib config test spec features) \
|
8
|
+
# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
|
9
|
+
|
10
|
+
## Note: if you are using the `directories` clause above and you are not
|
11
|
+
## watching the project directory ('.'), then you will want to move
|
12
|
+
## the Guardfile to a watched dir and symlink it back, e.g.
|
13
|
+
#
|
14
|
+
# $ mkdir config
|
15
|
+
# $ mv Guardfile config/
|
16
|
+
# $ ln -s config/Guardfile .
|
17
|
+
#
|
18
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
19
|
+
|
20
|
+
guard :minitest, all_after_pass: true do
|
21
|
+
# with Minitest::Unit
|
22
|
+
# watch(%r{^test/(.*)\/?test_(.*)\.rb$})
|
23
|
+
# watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
|
24
|
+
# watch(%r{^test/test_helper\.rb$}) { 'test' }
|
25
|
+
|
26
|
+
# with Minitest::Spec
|
27
|
+
watch(%r{^spec/**/(.*)_spec\.rb$})
|
28
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
29
|
+
watch(%r{^spec/spec_helper\.rb$}) { 'spec' }
|
30
|
+
end
|
31
|
+
|
32
|
+
guard :rubocop, cli: ['-c', '.rubocop_ruby_language_parser.yml'] do
|
33
|
+
watch('.rubocop_ruby_language_parser.yml')
|
34
|
+
watch(/.+\.rb$/)
|
35
|
+
watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) }
|
36
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Kurt Werle
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/Makefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
PROJECT_NAME=ruby_language_server
|
2
|
+
LOCAL_LINK=-v $(PWD):/tmp/src -w /tmp/src
|
3
|
+
|
4
|
+
build:
|
5
|
+
docker build -t $(PROJECT_NAME) .
|
6
|
+
|
7
|
+
guard: build
|
8
|
+
docker run -it $(LOCAL_LINK) $(PROJECT_NAME) sh -c 'bundle && guard'
|
9
|
+
|
10
|
+
continuous_development: build
|
11
|
+
echo "You are going to want to set the ide-ruby 'Image Name' to local_ruby_language_server"
|
12
|
+
sleep 15
|
13
|
+
while (true) ; \
|
14
|
+
do \
|
15
|
+
docker build -t local_ruby_language_server . ; \
|
16
|
+
sleep 2 ; \
|
17
|
+
done
|
18
|
+
|
19
|
+
console: build
|
20
|
+
docker run -it $(LOCAL_LINK) $(PROJECT_NAME) bin/console
|
21
|
+
|
22
|
+
shell: build
|
23
|
+
docker run -it $(LOCAL_LINK) $(PROJECT_NAME) sh
|
24
|
+
|
25
|
+
# Just to make sure it works.
|
26
|
+
server: build
|
27
|
+
docker run -it $(LOCAL_LINK) $(PROJECT_NAME)
|
28
|
+
|
29
|
+
gem: build
|
30
|
+
rm -f $(PROJECT_NAME)*.gem
|
31
|
+
docker run $(LOCAL_LINK) $(PROJECT_NAME) gem build $(PROJECT_NAME)
|
32
|
+
|
33
|
+
# Requires rubygems be installed on host
|
34
|
+
gem_release: gem
|
35
|
+
gem push $(PROJECT_NAME)*.gem
|
data/README.md
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Overview
|
2
|
+
|
3
|
+
https://github.com/kwerle/ruby_language_server
|
4
|
+
|
5
|
+
The goal of this project is to provide a [language server](https://microsoft.github.io/language-server-protocol/) implementation for ruby in ruby.
|
6
|
+
|
7
|
+
# Status
|
8
|
+
|
9
|
+
Beta. It does some stuff. Pretty stable. Used day-to-day.
|
10
|
+
|
11
|
+
Help wanted.
|
12
|
+
|
13
|
+
# Features
|
14
|
+
|
15
|
+
* Definitions
|
16
|
+
* Completions
|
17
|
+
* Lint - thanks to [RuboCop](https://github.com/bbatsov/rubocop)
|
18
|
+
* Please see the [FAQ_ROADMAP.md](./FAQ_ROADMAP.md)
|
19
|
+
|
20
|
+
# Editor Integrations
|
21
|
+
|
22
|
+
* You probably want to use one of the developed integrations:
|
23
|
+
* Atom - https://github.com/kwerle/ide-ruby
|
24
|
+
* Theia - https://github.com/kwerle/theia_ruby_language_server
|
25
|
+
|
26
|
+
# Running
|
27
|
+
|
28
|
+
`ruby_language_server` will start the program and wait for activity using LSP's STDIO interface
|
29
|
+
|
30
|
+
# Development
|
31
|
+
|
32
|
+
Clone. I love git [HubFlow](https://datasift.github.io/gitflow/).
|
33
|
+
|
34
|
+
Check out the [Makefile](Makefile). You are going to want to do
|
35
|
+
`make guard` and `make continuous_development`.
|
36
|
+
|
37
|
+
* In Atom: install the ide-ruby.
|
38
|
+
* Settings > Packages > ide-ruby > Image Name > local_ruby_language_server
|
39
|
+
* CMD-ALT-CTRL-l (that's an L) will reload the window
|
40
|
+
* CMD-ALT-i will show debugging info
|
41
|
+
|
42
|
+
Write tests and guard will run them. Make changes and reload the window. Test them out.
|
43
|
+
|
44
|
+
# Similar
|
45
|
+
|
46
|
+
* [mtsmfm/language_server-ruby](https://github.com/mtsmfm/language_server-ruby)
|
47
|
+
* [castwide/solargraph](https://github.com/castwide/solargraph)
|
48
|
+
|
49
|
+
# Authors
|
50
|
+
|
51
|
+
* [Kurt Werle](kurt@CircleW.org)
|
52
|
+
|
53
|
+
# Contributors
|
54
|
+
|
55
|
+
* *Your name here!*
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rake/testtask'
|
5
|
+
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
7
|
+
t.libs << 'spec'
|
8
|
+
t.libs << 'lib'
|
9
|
+
t.test_files = FileList['spec/**/*_spec.rb']
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'Run guard'
|
13
|
+
task guard: [] do
|
14
|
+
`guard`
|
15
|
+
end
|
16
|
+
|
17
|
+
task default: :test
|
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'ruby_language_server'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'scope_data/base'
|
4
|
+
require_relative 'scope_data/scope'
|
5
|
+
require_relative 'scope_data/variable'
|
6
|
+
|
7
|
+
module RubyLanguageServer
|
8
|
+
class CodeFile
|
9
|
+
attr_reader :uri
|
10
|
+
attr_reader :text
|
11
|
+
attr_reader :lint_found
|
12
|
+
|
13
|
+
def initialize(uri, text)
|
14
|
+
RubyLanguageServer.logger.debug("CodeFile initialize #{uri}")
|
15
|
+
@uri = uri
|
16
|
+
@text = text
|
17
|
+
@refresh_root_scope = true
|
18
|
+
end
|
19
|
+
|
20
|
+
def text=(new_text)
|
21
|
+
RubyLanguageServer.logger.debug("text= for #{uri}")
|
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
|
28
|
+
end
|
29
|
+
|
30
|
+
SYMBOL_KIND = {
|
31
|
+
file: 1,
|
32
|
+
'module': 5, # 2,
|
33
|
+
namespace: 3,
|
34
|
+
package: 4,
|
35
|
+
'class': 5,
|
36
|
+
'method': 6,
|
37
|
+
'singleton method': 6,
|
38
|
+
property: 7,
|
39
|
+
field: 8,
|
40
|
+
constructor: 9,
|
41
|
+
enum: 10,
|
42
|
+
interface: 11,
|
43
|
+
function: 12,
|
44
|
+
variable: 13,
|
45
|
+
constant: 14,
|
46
|
+
string: 15,
|
47
|
+
number: 16,
|
48
|
+
boolean: 17,
|
49
|
+
array: 18
|
50
|
+
}.freeze
|
51
|
+
|
52
|
+
# Find the ancestor of this scope with a name and return that. Or nil.
|
53
|
+
def ancestor_scope_name(scope)
|
54
|
+
return_scope = scope
|
55
|
+
while (return_scope = return_scope.parent)
|
56
|
+
return return_scope.name unless return_scope.name.nil?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def tags
|
61
|
+
RubyLanguageServer.logger.debug("Asking about tags for #{uri}")
|
62
|
+
return @tags = {} if text.nil? || text == ''
|
63
|
+
|
64
|
+
tags = []
|
65
|
+
root_scope.self_and_descendants.each do |scope|
|
66
|
+
next if scope.type == ScopeData::Base::TYPE_BLOCK
|
67
|
+
|
68
|
+
name = scope.name
|
69
|
+
kind = SYMBOL_KIND[scope.type] || 7
|
70
|
+
kind = 9 if name == 'initialize' # Magical special case
|
71
|
+
scope_hash = {
|
72
|
+
name: name,
|
73
|
+
kind: kind,
|
74
|
+
location: Location.hash(uri, scope.top_line)
|
75
|
+
}
|
76
|
+
container_name = ancestor_scope_name(scope)
|
77
|
+
scope_hash[:containerName] = container_name if container_name
|
78
|
+
tags << scope_hash
|
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
|
93
|
+
end
|
94
|
+
# byebug
|
95
|
+
tags.reject! { |tag| tag[:name].nil? }
|
96
|
+
# RubyLanguageServer.logger.debug("Raw tags for #{uri}: #{tags}")
|
97
|
+
# If you don't reverse the list then atom? won't be able to find the
|
98
|
+
# container and containers will get duplicated.
|
99
|
+
@tags = tags.reverse_each do |tag|
|
100
|
+
child_tags = tags.select { |child_tag| child_tag[:containerName] == tag[:name] }
|
101
|
+
max_line = child_tags.map { |child_tag| child_tag[:location][:range][:end][:line].to_i }.max || 0
|
102
|
+
tag[:location][:range][:end][:line] = [tag[:location][:range][:end][:line], max_line].max
|
103
|
+
end
|
104
|
+
# RubyLanguageServer.logger.debug("Done with tags for #{uri}: #{@tags}")
|
105
|
+
# RubyLanguageServer.logger.debug("tags caller #{caller * ','}")
|
106
|
+
@tags
|
107
|
+
end
|
108
|
+
|
109
|
+
def diagnostics
|
110
|
+
# Maybe we should be sharing this GoodCop across instances
|
111
|
+
@good_cop ||= GoodCop.new
|
112
|
+
@good_cop.diagnostics(@text, @uri)
|
113
|
+
end
|
114
|
+
|
115
|
+
def root_scope
|
116
|
+
# RubyLanguageServer.logger.error("Asking about root_scope with #{text}")
|
117
|
+
if @refresh_root_scope
|
118
|
+
new_root_scope = ScopeParser.new(text).root_scope
|
119
|
+
@root_scope ||= new_root_scope # In case we had NONE
|
120
|
+
return @root_scope if new_root_scope.children.empty?
|
121
|
+
|
122
|
+
@root_scope = new_root_scope
|
123
|
+
@refresh_root_scope = false
|
124
|
+
@tags = nil
|
125
|
+
end
|
126
|
+
@root_scope
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyLanguageServer
|
4
|
+
module Completion
|
5
|
+
COMPLETION_ITEM_KIND = {
|
6
|
+
text: 1,
|
7
|
+
method: 2,
|
8
|
+
function: 3,
|
9
|
+
constructor: 4,
|
10
|
+
field: 5,
|
11
|
+
variable: 6,
|
12
|
+
class: 7,
|
13
|
+
interface: 8,
|
14
|
+
module: 9,
|
15
|
+
property: 10,
|
16
|
+
unit: 11,
|
17
|
+
value: 12,
|
18
|
+
enum: 13,
|
19
|
+
keyword: 14,
|
20
|
+
snippet: 15,
|
21
|
+
color: 16,
|
22
|
+
file: 17,
|
23
|
+
reference: 18
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def completion(context, context_scope, scopes)
|
28
|
+
RubyLanguageServer.logger.debug("completion(#{context}, #{context_scope.self_and_ancestors.map(&:name)}, #{scopes.map(&:name)})")
|
29
|
+
completions =
|
30
|
+
if context.length < 2
|
31
|
+
scope_completions(context.last, context_scope.self_and_ancestors)
|
32
|
+
else
|
33
|
+
scope_completions_in_target_context(context, context_scope, scopes)
|
34
|
+
end
|
35
|
+
{
|
36
|
+
isIncomplete: true,
|
37
|
+
items: completions.uniq.map do |word, hash|
|
38
|
+
{
|
39
|
+
label: word,
|
40
|
+
kind: COMPLETION_ITEM_KIND[hash[:type]]
|
41
|
+
}
|
42
|
+
end
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def scope_with_name(name, scopes)
|
47
|
+
scopes.detect { |scope| scope.name == name }
|
48
|
+
end
|
49
|
+
|
50
|
+
def scope_completions_in_target_context(context, context_scope, scopes)
|
51
|
+
working_array = context.dup
|
52
|
+
context_word = working_array[-2]
|
53
|
+
if context_word.match?(/^[A-Z]/)
|
54
|
+
scope = scope_with_name(context_word, scopes)
|
55
|
+
else
|
56
|
+
context_word = context_word.split(/_/).map(&:capitalize).join('')
|
57
|
+
scope = scope_with_name(context_word, scopes)
|
58
|
+
RubyLanguageServer.logger.debug("scope_with_name: #{scope}")
|
59
|
+
end
|
60
|
+
scope ||= context_scope
|
61
|
+
RubyLanguageServer.logger.debug("scope: #{scope}")
|
62
|
+
scope_completions(context.last, scope.self_and_ancestors)
|
63
|
+
end
|
64
|
+
|
65
|
+
def scope_completions(word, scopes)
|
66
|
+
words = {}
|
67
|
+
scopes.each_with_object(words) do |scope, words_hash|
|
68
|
+
scope.children.each do |function|
|
69
|
+
words_hash[function.name] ||= {
|
70
|
+
depth: scope.depth,
|
71
|
+
type: function.type
|
72
|
+
}
|
73
|
+
end
|
74
|
+
scope.variables.each do |variable|
|
75
|
+
words_hash[variable.name] ||= {
|
76
|
+
depth: scope.depth,
|
77
|
+
type: variable.type
|
78
|
+
}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
# words = words.sort_by{|word, hash| hash[:depth] }.to_h
|
82
|
+
good_words = FuzzyMatch.new(words.keys, threshold: 0.01).find_all(word).slice(0..10) || []
|
83
|
+
words = good_words.map { |w| [w, words[w]] }.to_h
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/inline'
|
4
|
+
|
5
|
+
module RubyLanguageServer
|
6
|
+
# Sole purpose is to install gems
|
7
|
+
module GemInstaller
|
8
|
+
class << self
|
9
|
+
def install_gems(gem_names)
|
10
|
+
gem_names&.compact!
|
11
|
+
gem_names&.reject! { |name| name.strip == '' }
|
12
|
+
return if gem_names.nil? || gem_names.empty?
|
13
|
+
|
14
|
+
RubyLanguageServer.logger.info("Trying to install gems #{gem_names}")
|
15
|
+
gemfile do
|
16
|
+
source 'https://rubygems.org'
|
17
|
+
gem_names.each do |gem_name|
|
18
|
+
gem gem_name
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|