yoda-language-server 0.4.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.
Files changed (171) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +8 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.lock +78 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +85 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/client/atom/main.js +27 -0
  13. data/client/vscode/.gitignore +4 -0
  14. data/client/vscode/.vscode/launch.json +28 -0
  15. data/client/vscode/.vscode/settings.json +9 -0
  16. data/client/vscode/.vscode/tasks.json +20 -0
  17. data/client/vscode/.vscodeignore +8 -0
  18. data/client/vscode/CHANGELOG.md +7 -0
  19. data/client/vscode/README.md +65 -0
  20. data/client/vscode/package-lock.json +2688 -0
  21. data/client/vscode/package.json +39 -0
  22. data/client/vscode/src/extension.ts +42 -0
  23. data/client/vscode/src/test/extension.test.ts +22 -0
  24. data/client/vscode/src/test/index.ts +22 -0
  25. data/client/vscode/tsconfig.json +16 -0
  26. data/client/vscode/vsc-extension-quickstart.md +33 -0
  27. data/exe/yoda +27 -0
  28. data/lib/yoda.rb +11 -0
  29. data/lib/yoda/evaluation.rb +9 -0
  30. data/lib/yoda/evaluation/code_completion.rb +65 -0
  31. data/lib/yoda/evaluation/code_completion/base_provider.rb +57 -0
  32. data/lib/yoda/evaluation/code_completion/const_provider.rb +90 -0
  33. data/lib/yoda/evaluation/code_completion/method_provider.rb +82 -0
  34. data/lib/yoda/evaluation/code_completion/variable_provider.rb +18 -0
  35. data/lib/yoda/evaluation/comment_completion.rb +70 -0
  36. data/lib/yoda/evaluation/comment_completion/base_provider.rb +64 -0
  37. data/lib/yoda/evaluation/comment_completion/param_provider.rb +18 -0
  38. data/lib/yoda/evaluation/comment_completion/tag_provider.rb +41 -0
  39. data/lib/yoda/evaluation/comment_completion/type_provider.rb +58 -0
  40. data/lib/yoda/evaluation/current_node_explain.rb +70 -0
  41. data/lib/yoda/evaluation/evaluator.rb +103 -0
  42. data/lib/yoda/evaluation/signature_discovery.rb +83 -0
  43. data/lib/yoda/model.rb +12 -0
  44. data/lib/yoda/model/completion_item.rb +56 -0
  45. data/lib/yoda/model/descriptions.rb +10 -0
  46. data/lib/yoda/model/descriptions/base.rb +26 -0
  47. data/lib/yoda/model/descriptions/function_description.rb +40 -0
  48. data/lib/yoda/model/descriptions/value_description.rb +33 -0
  49. data/lib/yoda/model/descriptions/word_description.rb +32 -0
  50. data/lib/yoda/model/function_signatures.rb +13 -0
  51. data/lib/yoda/model/function_signatures/base.rb +68 -0
  52. data/lib/yoda/model/function_signatures/constructor.rb +70 -0
  53. data/lib/yoda/model/function_signatures/formatter.rb +82 -0
  54. data/lib/yoda/model/function_signatures/method.rb +67 -0
  55. data/lib/yoda/model/function_signatures/overload.rb +79 -0
  56. data/lib/yoda/model/function_signatures/parameter_list.rb +108 -0
  57. data/lib/yoda/model/function_signatures/type_builder.rb +101 -0
  58. data/lib/yoda/model/node_signature.rb +28 -0
  59. data/lib/yoda/model/path.rb +96 -0
  60. data/lib/yoda/model/scoped_path.rb +44 -0
  61. data/lib/yoda/model/types.rb +84 -0
  62. data/lib/yoda/model/types/any_type.rb +32 -0
  63. data/lib/yoda/model/types/base.rb +37 -0
  64. data/lib/yoda/model/types/duck_type.rb +41 -0
  65. data/lib/yoda/model/types/function_type.rb +174 -0
  66. data/lib/yoda/model/types/generic_type.rb +66 -0
  67. data/lib/yoda/model/types/instance_type.rb +42 -0
  68. data/lib/yoda/model/types/module_type.rb +42 -0
  69. data/lib/yoda/model/types/sequence_type.rb +53 -0
  70. data/lib/yoda/model/types/union_type.rb +56 -0
  71. data/lib/yoda/model/types/unknown_type.rb +40 -0
  72. data/lib/yoda/model/types/value_type.rb +58 -0
  73. data/lib/yoda/model/values.rb +9 -0
  74. data/lib/yoda/model/values/base.rb +32 -0
  75. data/lib/yoda/model/values/instance_value.rb +65 -0
  76. data/lib/yoda/model/values/module_value.rb +72 -0
  77. data/lib/yoda/parsing.rb +15 -0
  78. data/lib/yoda/parsing/ast_traversable.rb +18 -0
  79. data/lib/yoda/parsing/comment_tokenizer.rb +59 -0
  80. data/lib/yoda/parsing/location.rb +101 -0
  81. data/lib/yoda/parsing/node_objects.rb +10 -0
  82. data/lib/yoda/parsing/node_objects/const_node.rb +52 -0
  83. data/lib/yoda/parsing/node_objects/method_definition.rb +46 -0
  84. data/lib/yoda/parsing/node_objects/namespace.rb +104 -0
  85. data/lib/yoda/parsing/node_objects/send_node.rb +72 -0
  86. data/lib/yoda/parsing/parser.rb +27 -0
  87. data/lib/yoda/parsing/query.rb +11 -0
  88. data/lib/yoda/parsing/query/current_comment_query.rb +80 -0
  89. data/lib/yoda/parsing/query/current_comment_token_query.rb +153 -0
  90. data/lib/yoda/parsing/query/current_commenting_node_query.rb +68 -0
  91. data/lib/yoda/parsing/query/current_location_node_query.rb +51 -0
  92. data/lib/yoda/parsing/query/current_node_comment_query.rb +40 -0
  93. data/lib/yoda/parsing/range.rb +41 -0
  94. data/lib/yoda/parsing/scopes.rb +15 -0
  95. data/lib/yoda/parsing/scopes/base.rb +78 -0
  96. data/lib/yoda/parsing/scopes/builder.rb +60 -0
  97. data/lib/yoda/parsing/scopes/class_definition.rb +47 -0
  98. data/lib/yoda/parsing/scopes/meta_class_definition.rb +44 -0
  99. data/lib/yoda/parsing/scopes/meta_method_definition.rb +70 -0
  100. data/lib/yoda/parsing/scopes/method_definition.rb +69 -0
  101. data/lib/yoda/parsing/scopes/module_definition.rb +36 -0
  102. data/lib/yoda/parsing/scopes/root.rb +25 -0
  103. data/lib/yoda/parsing/source_analyzer.rb +59 -0
  104. data/lib/yoda/parsing/source_cutter.rb +231 -0
  105. data/lib/yoda/parsing/type_parser.rb +141 -0
  106. data/lib/yoda/runner.rb +6 -0
  107. data/lib/yoda/runner/infer.rb +50 -0
  108. data/lib/yoda/runner/setup.rb +26 -0
  109. data/lib/yoda/server.rb +191 -0
  110. data/lib/yoda/server/client_info.rb +98 -0
  111. data/lib/yoda/server/completion_provider.rb +78 -0
  112. data/lib/yoda/server/definition_provider.rb +36 -0
  113. data/lib/yoda/server/deserializer.rb +27 -0
  114. data/lib/yoda/server/hover_provider.rb +38 -0
  115. data/lib/yoda/server/signature_provider.rb +46 -0
  116. data/lib/yoda/store.rb +13 -0
  117. data/lib/yoda/store/actions.rb +10 -0
  118. data/lib/yoda/store/actions/import_core_library.rb +30 -0
  119. data/lib/yoda/store/actions/import_gems.rb +91 -0
  120. data/lib/yoda/store/actions/read_file.rb +36 -0
  121. data/lib/yoda/store/actions/read_project_files.rb +29 -0
  122. data/lib/yoda/store/adapters.rb +14 -0
  123. data/lib/yoda/store/adapters/base.rb +58 -0
  124. data/lib/yoda/store/adapters/leveldb_adapter.rb +80 -0
  125. data/lib/yoda/store/adapters/lmdb_adapter.rb +113 -0
  126. data/lib/yoda/store/objects.rb +46 -0
  127. data/lib/yoda/store/objects/addressable.rb +25 -0
  128. data/lib/yoda/store/objects/base.rb +116 -0
  129. data/lib/yoda/store/objects/class_object.rb +51 -0
  130. data/lib/yoda/store/objects/merger.rb +94 -0
  131. data/lib/yoda/store/objects/meta_class_object.rb +41 -0
  132. data/lib/yoda/store/objects/method_object.rb +94 -0
  133. data/lib/yoda/store/objects/module_object.rb +11 -0
  134. data/lib/yoda/store/objects/namespace_object.rb +67 -0
  135. data/lib/yoda/store/objects/overload.rb +51 -0
  136. data/lib/yoda/store/objects/patch.rb +46 -0
  137. data/lib/yoda/store/objects/patch_set.rb +80 -0
  138. data/lib/yoda/store/objects/tag.rb +62 -0
  139. data/lib/yoda/store/objects/value_object.rb +45 -0
  140. data/lib/yoda/store/project.rb +159 -0
  141. data/lib/yoda/store/query.rb +12 -0
  142. data/lib/yoda/store/query/associators.rb +10 -0
  143. data/lib/yoda/store/query/associators/associate_ancestors.rb +103 -0
  144. data/lib/yoda/store/query/associators/associate_methods.rb +38 -0
  145. data/lib/yoda/store/query/base.rb +16 -0
  146. data/lib/yoda/store/query/find_constant.rb +150 -0
  147. data/lib/yoda/store/query/find_meta_class.rb +18 -0
  148. data/lib/yoda/store/query/find_method.rb +74 -0
  149. data/lib/yoda/store/query/find_signature.rb +43 -0
  150. data/lib/yoda/store/registry.rb +67 -0
  151. data/lib/yoda/store/yard_importer.rb +260 -0
  152. data/lib/yoda/typing.rb +10 -0
  153. data/lib/yoda/typing/context.rb +96 -0
  154. data/lib/yoda/typing/environment.rb +35 -0
  155. data/lib/yoda/typing/evaluator.rb +256 -0
  156. data/lib/yoda/typing/lexical_scope.rb +26 -0
  157. data/lib/yoda/typing/relation.rb +15 -0
  158. data/lib/yoda/typing/traces.rb +9 -0
  159. data/lib/yoda/typing/traces/base.rb +26 -0
  160. data/lib/yoda/typing/traces/normal.rb +22 -0
  161. data/lib/yoda/typing/traces/send.rb +26 -0
  162. data/lib/yoda/version.rb +3 -0
  163. data/lib/yoda/yard_extensions.rb +11 -0
  164. data/lib/yoda/yard_extensions/sig_directive.rb +40 -0
  165. data/lib/yoda/yard_extensions/type_tag.rb +10 -0
  166. data/package.json +76 -0
  167. data/scripts/benchmark.rb +6 -0
  168. data/scripts/build_core_index.sh +16 -0
  169. data/yarn.lock +13 -0
  170. data/yoda-language-server.gemspec +40 -0
  171. metadata +424 -0
@@ -0,0 +1,6 @@
1
+ module Yoda
2
+ module Runner
3
+ require 'yoda/runner/infer'
4
+ require 'yoda/runner/setup'
5
+ end
6
+ end
@@ -0,0 +1,50 @@
1
+ module Yoda
2
+ module Runner
3
+ class Infer
4
+ attr_reader :filename_with_position
5
+
6
+ # @param filename_with_position [String]
7
+ def self.run(filename_with_position)
8
+ new(filename_with_position).run
9
+ end
10
+
11
+ # @param filename_with_position [String]
12
+ def initialize(filename_with_position)
13
+ @filename_with_position = filename_with_position
14
+ end
15
+
16
+ def run
17
+ project.setup
18
+ puts create_signature_help(worker.current_node_signature)
19
+ end
20
+
21
+ private
22
+
23
+ # @param signature [Model::NodeSignature, nil]
24
+ # @return [String, nil]
25
+ def create_signature_help(signature)
26
+ return nil unless signature
27
+ signature.descriptions.map(&:title).join("\n")
28
+ end
29
+
30
+ def worker
31
+ @worker ||= Evaluation::CurrentNodeExplain.new(project.registry, File.read(filename), position)
32
+ end
33
+
34
+ def project
35
+ @project ||= Store::Project.new(Dir.pwd)
36
+ end
37
+
38
+ def filename
39
+ @filename ||= filename_with_position.split(':').first
40
+ end
41
+
42
+ def position
43
+ @position ||= begin
44
+ row, column = filename_with_position.split(':').slice(1..2)
45
+ Parsing::Location.new(row: row.to_i, column: column.to_i)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,26 @@
1
+ module Yoda
2
+ module Runner
3
+ class Setup
4
+ # @return [String]
5
+ attr_reader :dir
6
+
7
+ # @param dir [String]
8
+ def initialize(dir = nil)
9
+ @dir = dir || Dir.pwd
10
+ end
11
+
12
+ # @param dir [String]
13
+ def self.run(dir = nil)
14
+ new(dir).run
15
+ end
16
+
17
+ def run
18
+ project.rebuild_cache(progress: true)
19
+ end
20
+
21
+ def project
22
+ @project ||= Store::Project.new(dir)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,191 @@
1
+ require 'language_server-protocol'
2
+
3
+ module Yoda
4
+ class Server
5
+ require 'yoda/server/completion_provider'
6
+ require 'yoda/server/signature_provider'
7
+ require 'yoda/server/hover_provider'
8
+ require 'yoda/server/definition_provider'
9
+ require 'yoda/server/deserializer'
10
+ require 'yoda/server/client_info'
11
+
12
+ LSP = ::LanguageServer::Protocol
13
+
14
+ def self.deserialize(hash)
15
+ Deserializer.new.deserialize(hash || {})
16
+ end
17
+
18
+ # @type ::LanguageServer::Protocol::Transport::Stdio::Reader
19
+ attr_reader :reader
20
+
21
+ # @type ::LanguageServer::Protocol::Transport::Stdio::Writer
22
+ attr_reader :writer
23
+
24
+ # @type ClientInfo
25
+ attr_reader :client_info
26
+
27
+ # @type CompletionProvider
28
+ attr_reader :completion_provider
29
+
30
+ # @type HoverProvider
31
+ attr_reader :hover_provider
32
+
33
+ # @type SignatureProvider
34
+ attr_reader :signature_provider
35
+
36
+ # @type DefinitionProvider
37
+ attr_reader :definition_provider
38
+
39
+ def initialize
40
+ @reader = LSP::Transport::Stdio::Reader.new
41
+ @writer = LSP::Transport::Stdio::Writer.new
42
+ end
43
+
44
+ def run
45
+ reader.read do |request|
46
+ begin
47
+ if result = callback(request)
48
+ writer.write(id: request[:id], result: result)
49
+ end
50
+ rescue StandardError => ex
51
+ STDERR.puts ex
52
+ STDERR.puts ex.backtrace
53
+ end
54
+ end
55
+ end
56
+
57
+ def callback(request)
58
+ if method_name = resolve(request_registrations, request[:method])
59
+ send(method_name, self.class.deserialize(request[:params] || {}))
60
+ elsif method_name = resolve(notification_registrations, request[:method])
61
+ send(method_name, self.class.deserialize(request[:params] || {}))
62
+ nil
63
+ end
64
+ end
65
+
66
+ # @param hash [Hash]
67
+ # @param key [String, Symbol]
68
+ def resolve(hash, key)
69
+ key.to_s.split('/').reduce(hash) do |scope, key|
70
+ (scope || {})[key.to_sym]
71
+ end
72
+ end
73
+
74
+ def request_registrations
75
+ {
76
+ initialize: :handle_initialize,
77
+ shutdown: :handle_shutdown,
78
+ textDocument: {
79
+ completion: :handle_text_document_completion,
80
+ hover: :handle_text_document_hover,
81
+ signatureHelp: :handle_text_document_signature_help,
82
+ definition: :handle_text_document_definition,
83
+ },
84
+ }
85
+ end
86
+
87
+ def notification_registrations
88
+ {
89
+ initialized: :handle_initialized,
90
+ exit: :handle_exit,
91
+ textDocument: {
92
+ didChange: :handle_text_document_did_change,
93
+ didOpen: :handle_text_document_did_open,
94
+ didSave: :handle_text_document_did_save,
95
+ },
96
+ }
97
+ end
98
+
99
+ def handle_initialize(params)
100
+ @client_info = ClientInfo.new(params[:root_uri])
101
+ @completion_provider = CompletionProvider.new(@client_info)
102
+ @hover_provider = HoverProvider.new(@client_info)
103
+ @signature_provider = SignatureProvider.new(@client_info)
104
+ @definition_provider = DefinitionProvider.new(@client_info)
105
+ client_info.setup
106
+
107
+ LSP::Interface::InitializeResult.new(
108
+ capabilities: LSP::Interface::ServerCapabilities.new(
109
+ text_document_sync: LSP::Interface::TextDocumentSyncOptions.new(
110
+ change: LSP::Constant::TextDocumentSyncKind::FULL,
111
+ save: LSP::Interface::SaveOptions.new(
112
+ include_text: true,
113
+ ),
114
+ ),
115
+ completion_provider: LSP::Interface::CompletionOptions.new(
116
+ resolve_provider: true,
117
+ trigger_characters: ['.', '@', '[', ':', '!', '<'],
118
+ ),
119
+ hover_provider: true,
120
+ definition_provider: true,
121
+ signature_help_provider: LSP::Interface::SignatureHelpOptions.new(
122
+ trigger_characters: ['(', ','],
123
+ ),
124
+ ),
125
+ )
126
+ end
127
+
128
+ def handle_initialized(_params)
129
+ end
130
+
131
+ def handle_shutdown(_params)
132
+ end
133
+
134
+ def handle_exit(_params)
135
+ end
136
+
137
+ module TextDocument
138
+ module CompletionTrigggerKind
139
+ INVOKED = 1
140
+ TRIGGER_CHARACTER = 2
141
+ end
142
+
143
+ def handle_text_document_did_open(params)
144
+ uri = params[:text_document][:uri]
145
+ text = params[:text_document][:text]
146
+ client_info.file_store.store(uri, text)
147
+ end
148
+
149
+ def handle_text_document_did_save(params)
150
+ uri = params[:text_document][:uri]
151
+
152
+ client_info.reparse_doc(uri)
153
+ end
154
+
155
+ def handle_text_document_did_change(params)
156
+ uri = params[:text_document][:uri]
157
+ text = params[:content_changes].first[:text]
158
+ client_info.file_store.store(uri, text)
159
+ end
160
+
161
+ def handle_text_document_completion(params)
162
+ uri = params[:text_document][:uri]
163
+ position = params[:position]
164
+
165
+ completion_provider&.complete(uri, position)
166
+ end
167
+
168
+ def handle_text_document_hover(params)
169
+ uri = params[:text_document][:uri]
170
+ position = params[:position]
171
+
172
+ hover_provider&.request_hover(uri, position)
173
+ end
174
+
175
+ def handle_text_document_signature_help(params)
176
+ uri = params[:text_document][:uri]
177
+ position = params[:position]
178
+
179
+ signature_provider&.provide(uri, position)
180
+ end
181
+
182
+ def handle_text_document_definition(params)
183
+ uri = params[:text_document][:uri]
184
+ position = params[:position]
185
+
186
+ definition_provider&.provide(uri, position)
187
+ end
188
+ end
189
+ include TextDocument
190
+ end
191
+ end
@@ -0,0 +1,98 @@
1
+ require 'uri'
2
+
3
+ module Yoda
4
+ class Server
5
+ class ClientInfo
6
+ # @return [String]
7
+ attr_reader :root_uri
8
+
9
+ # @return [FileStore]
10
+ attr_reader :file_store
11
+
12
+ # @return [Store::Project]
13
+ attr_reader :project
14
+
15
+ # @param root_uri [String] an uri expression of project root path
16
+ def initialize(root_uri)
17
+ @root_uri = root_uri
18
+ @file_store = FileStore.new
19
+ @project = Store::Project.new(root_path)
20
+ end
21
+
22
+ def root_path
23
+ @root_path ||= FileStore.path_of_uri(root_uri)
24
+ end
25
+
26
+ # @return [Store::Registry]
27
+ def registry
28
+ project.registry
29
+ end
30
+
31
+ def setup
32
+ project.setup
33
+ end
34
+
35
+ # @param path [String]
36
+ def uri_of_path(path)
37
+ FileStore.uri_of_path(File.expand_path(path, root_path))
38
+ end
39
+
40
+ def reparse_doc(uri)
41
+ path = FileStore.path_of_uri(uri)
42
+ project.read_source(path)
43
+ end
44
+
45
+ class FileStore
46
+ def initialize
47
+ @cache = {}
48
+ end
49
+
50
+ # @param uri_string [String]
51
+ # @return [String, nil]
52
+ def get(uri_string)
53
+ @cache[uri_string]
54
+ end
55
+
56
+ # @param uri_string [String]
57
+ # @param text [String]
58
+ def store(uri_string, text)
59
+ return unless program_file_uri?(uri_string)
60
+ @cache[uri_string] = text
61
+ end
62
+
63
+ # @param uri_string [String]
64
+ def load(uri_string)
65
+ store(uri_string, read(uri_string))
66
+ end
67
+
68
+ # @param uri_string [String]
69
+ def read(uri_string)
70
+ path = self.class.path_of_uri(uri_string)
71
+ fail ArgumentError unless path
72
+ File.read(path)
73
+ end
74
+
75
+ # @param path [String]
76
+ def self.uri_of_path(path)
77
+ "file://#{File.expand_path(path)}"
78
+ end
79
+
80
+ # @param uri_string [String]
81
+ def self.path_of_uri(uri_string)
82
+ uri = URI.parse(uri_string)
83
+ return nil unless uri.scheme == 'file'
84
+ uri.path
85
+ rescue URI::InvalidURIError
86
+ nil
87
+ end
88
+
89
+ # @param uri_string [String]
90
+ def program_file_uri?(uri_string)
91
+ %w(.c .rb).include?(File.extname(URI.parse(uri_string).path))
92
+ rescue URI::InvalidURIError => _e
93
+ false
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,78 @@
1
+ module Yoda
2
+ class Server
3
+ class CompletionProvider
4
+ # @type ClientInfo
5
+ attr_reader :client_info
6
+
7
+ # @param client_info [ClientInfo]
8
+ def initialize(client_info)
9
+ @client_info = client_info
10
+ end
11
+
12
+ # @param uri [String]
13
+ # @param position [{Symbol => Integer}]
14
+ def complete(uri, position)
15
+ source = client_info.file_store.get(uri)
16
+ location = Parsing::Location.of_language_server_protocol_position(line: position[:line], character: position[:character])
17
+
18
+ if candidates = comment_complete(source, location)
19
+ return candidates
20
+ end
21
+ complete_from_cut_source(source, location)
22
+ end
23
+
24
+ private
25
+
26
+ # @param source [String]
27
+ # @param location [Parsing::Location]
28
+ # @return [LanguageServerProtocol::Interface::CompletionList, nil]
29
+ def comment_complete(source, location)
30
+ ast, comments = Parsing::Parser.new.parse_with_comments(source)
31
+ return nil unless Parsing::Query::CurrentCommentQuery.new(comments, location).current_comment
32
+ completion_worker = Evaluation::CommentCompletion.new(client_info.registry, ast, comments, location)
33
+ return nil unless completion_worker.available?
34
+
35
+ completion_items = completion_worker.candidates
36
+
37
+ LSP::Interface::CompletionList.new(
38
+ is_incomplete: false,
39
+ items: completion_worker.candidates.map { |completion_item| create_completion_item(completion_item) },
40
+ )
41
+ rescue ::Parser::SyntaxError
42
+ nil
43
+ end
44
+
45
+ # @param source [String]
46
+ # @param location [Parsing::Location]
47
+ # @return [LanguageServerProtocol::Interface::CompletionList, nil]
48
+ def complete_from_cut_source(source, location)
49
+ cut_source = Parsing::SourceCutter.new(source, location).error_recovered_source
50
+ method_completion_worker = Evaluation::CodeCompletion.new(client_info.registry, cut_source, location)
51
+ completion_items = method_completion_worker.candidates
52
+ return nil if completion_items.empty?
53
+
54
+ LSP::Interface::CompletionList.new(
55
+ is_incomplete: false,
56
+ items: completion_items.map { |completion_item| create_completion_item(completion_item) },
57
+ )
58
+ end
59
+
60
+ # @param completion_item [Model::CompletionItem]
61
+ # @return [LSP::Interface::CompletionItem]
62
+ def create_completion_item(completion_item)
63
+ LSP::Interface::CompletionItem.new(
64
+ label: completion_item.description.is_a?(Model::Descriptions::FunctionDescription) ? completion_item.description.signature : completion_item.description.sort_text,
65
+ kind: completion_item.language_server_kind,
66
+ detail: completion_item.description.title,
67
+ documentation: completion_item.description.to_markdown,
68
+ sort_text: completion_item.description.sort_text,
69
+ text_edit: LSP::Interface::TextEdit.new(
70
+ range: LSP::Interface::Range.new(completion_item.range.to_language_server_protocol_range),
71
+ new_text: completion_item.edit_text,
72
+ ),
73
+ data: {},
74
+ )
75
+ end
76
+ end
77
+ end
78
+ end