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,83 @@
1
+ module Yoda
2
+ module Evaluation
3
+ class SignatureDiscovery
4
+ # @return [Store::Registry]
5
+ attr_reader :registry
6
+
7
+ # @return [String]
8
+ attr_reader :source
9
+
10
+ # @return [Parsing::Location]
11
+ attr_reader :location
12
+
13
+ # @param registry [Store::Registry]
14
+ # @param source [String]
15
+ # @param location [Parsing::Location]
16
+ def initialize(registry, source, location)
17
+ @registry = registry
18
+ @source = source
19
+ @location = location
20
+ end
21
+
22
+ def valid?
23
+ !!nearest_send_node
24
+ end
25
+
26
+ # @return [Parsing::NodeObjects::SendNode, nil]
27
+ def nearest_send_node
28
+ @nearest_send_node ||= send_nodes_to_current_location.reverse.find { |node| node.on_parameter?(location) }
29
+ end
30
+
31
+ # @return [Array<Parsing::NodeObjects::SendNode>]
32
+ def send_nodes_to_current_location
33
+ @send_nodes_to_current_location ||= begin
34
+ analyzer.nodes_to_current_location_from_root.map do |node|
35
+ node.type == :send ? Parsing::NodeObjects::SendNode.new(node) : nil
36
+ end.compact
37
+ end
38
+ end
39
+
40
+ # @return [String, nil]
41
+ def index_word
42
+ nearest_send_node&.selector_name
43
+ end
44
+
45
+ # @return [Model::Types::Base]
46
+ def receiver_type
47
+ @receiver_type ||= begin
48
+ if nearest_send_node
49
+ evaluator.calculate_type(nearest_send_node.receiver_node)
50
+ else
51
+ Model::Types::InstanceType.new(analyzer.namespace_object.path)
52
+ end
53
+ end
54
+ end
55
+
56
+ # @return [Array<Store::Objects::MethodObject>]
57
+ def method_candidates
58
+ return [] unless valid?
59
+ receiver_values
60
+ .map { |value| Store::Query::FindSignature.new(registry).select(value, /\A#{Regexp.escape(index_word)}/) }
61
+ .flatten
62
+ end
63
+
64
+ private
65
+
66
+ # @return [Array<Store::Values::Base>]
67
+ def receiver_values
68
+ return [] unless valid?
69
+ @receiver_values ||= evaluator.calculate_values(nearest_send_node.receiver_node)
70
+ end
71
+
72
+ # @return [SourceAnalyzer]
73
+ def analyzer
74
+ @analyzer ||= Parsing::SourceAnalyzer.from_source(source, location)
75
+ end
76
+
77
+ # @return [Evaluator]
78
+ def evaluator
79
+ @evaluator ||= Evaluator.from_ast(registry, analyzer.ast, location)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,12 @@
1
+ module Yoda
2
+ module Model
3
+ require 'yoda/model/function_signatures'
4
+ require 'yoda/model/descriptions'
5
+ require 'yoda/model/node_signature'
6
+ require 'yoda/model/path'
7
+ require 'yoda/model/scoped_path'
8
+ require 'yoda/model/types'
9
+ require 'yoda/model/values'
10
+ require 'yoda/model/completion_item'
11
+ end
12
+ end
@@ -0,0 +1,56 @@
1
+ module Yoda
2
+ module Model
3
+ class CompletionItem
4
+ # @return [Descriptions::Base]
5
+ attr_reader :description
6
+
7
+ # @return [Parsing::Range]
8
+ attr_reader :range
9
+
10
+ # @return [Symbol]
11
+ attr_reader :kind
12
+
13
+ # @return [String]
14
+ attr_reader :prefix
15
+
16
+ # @param description [Descriptions::Base]
17
+ # @param range [Parsing::Range]
18
+ # @param kind [Symbol, nil]
19
+ # @param prefix [String, nil]
20
+ def initialize(description:, range:, kind: nil, prefix: nil)
21
+ fail ArgumentError, desctiption unless description.is_a?(Descriptions::Base)
22
+ fail ArgumentError, range unless range.is_a?(Parsing::Range)
23
+ fail ArgumentError, kind if !kind.nil? && !available_kinds.include?(kind)
24
+ @description = description
25
+ @range = range
26
+ @kind = kind
27
+ @prefix = prefix || ''
28
+ end
29
+
30
+ # @return [String]
31
+ def edit_text
32
+ prefix + description.sort_text
33
+ end
34
+
35
+ # @return [Symbol]
36
+ def available_kinds
37
+ %i(method class module constant)
38
+ end
39
+
40
+ def language_server_kind
41
+ case kind
42
+ when :constant
43
+ LanguageServer::Protocol::Constant::CompletionItemKind::VALUE
44
+ when :method
45
+ LanguageServer::Protocol::Constant::CompletionItemKind::METHOD
46
+ when :class
47
+ LanguageServer::Protocol::Constant::CompletionItemKind::CLASS
48
+ when :module
49
+ LanguageServer::Protocol::Constant::CompletionItemKind::MODULE
50
+ else
51
+ nil
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,10 @@
1
+ module Yoda
2
+ module Model
3
+ module Descriptions
4
+ require 'yoda/model/descriptions/base'
5
+ require 'yoda/model/descriptions/function_description'
6
+ require 'yoda/model/descriptions/value_description'
7
+ require 'yoda/model/descriptions/word_description'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,26 @@
1
+ module Yoda
2
+ module Model
3
+ module Descriptions
4
+ # @abstract
5
+ class Base
6
+ # @abstract
7
+ # @return [String]
8
+ def title
9
+ fail NotImplementedError
10
+ end
11
+
12
+ # @abstract
13
+ # @return [String]
14
+ def sort_text
15
+ fail NotImplementedError
16
+ end
17
+
18
+ # @abstract
19
+ # @return [String]
20
+ def to_markdown
21
+ fail NotImplementedError
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,40 @@
1
+ module Yoda
2
+ module Model
3
+ module Descriptions
4
+ class FunctionDescription < Base
5
+ # @type Store::Objects::MethodObject
6
+ attr_reader :function
7
+
8
+ # @param function [FunctionSignatures::Base]
9
+ def initialize(function)
10
+ fail ArgumentError, function unless function.is_a?(FunctionSignatures::Base)
11
+ @function = function
12
+ end
13
+
14
+ def title
15
+ "#{function.namespace_path}#{function.sep}#{function.to_s}"
16
+ end
17
+
18
+ def signature
19
+ "#{function.to_s}"
20
+ end
21
+
22
+ def sort_text
23
+ function.name.to_s
24
+ end
25
+
26
+ def parameter_names
27
+ function.parameters.parameter_names
28
+ end
29
+
30
+ def to_markdown
31
+ <<~EOS
32
+ **#{title}**
33
+
34
+ #{function.document}
35
+ EOS
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,33 @@
1
+ module Yoda
2
+ module Model
3
+ module Descriptions
4
+ class ValueDescription < Base
5
+ # @return [Store::Objects::Base]
6
+ attr_reader :value
7
+
8
+ # @param value [Store::Objects::Base]
9
+ def initialize(value)
10
+ @value = value
11
+ end
12
+
13
+ # @return [String]
14
+ def title
15
+ "#{value.path}#{value.is_a?(Store::Objects::MetaClassObject) ? '.class' : ''}"
16
+ end
17
+
18
+ # @return [String]
19
+ def sort_text
20
+ value.name.to_s
21
+ end
22
+
23
+ def to_markdown
24
+ <<~EOS
25
+ **#{title}**
26
+
27
+ #{value.document}
28
+ EOS
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ module Yoda
2
+ module Model
3
+ module Descriptions
4
+ class WordDescription < Base
5
+ # @return [String]
6
+ attr_reader :word
7
+
8
+ # @param function [String]
9
+ def initialize(word)
10
+ @word = word
11
+ end
12
+
13
+ # @return [String]
14
+ def title
15
+ word
16
+ end
17
+
18
+ # @return [String]
19
+ def sort_text
20
+ word
21
+ end
22
+
23
+ # @return [String]
24
+ def to_markdown
25
+ <<~EOS
26
+ word
27
+ EOS
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,13 @@
1
+ module Yoda
2
+ module Model
3
+ module FunctionSignatures
4
+ require 'yoda/model/function_signatures/base'
5
+ require 'yoda/model/function_signatures/constructor'
6
+ require 'yoda/model/function_signatures/overload'
7
+ require 'yoda/model/function_signatures/method'
8
+ require 'yoda/model/function_signatures/parameter_list'
9
+ require 'yoda/model/function_signatures/type_builder'
10
+ require 'yoda/model/function_signatures/formatter'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,68 @@
1
+ module Yoda
2
+ module Model
3
+ module FunctionSignatures
4
+ # @abstract
5
+ class Base
6
+ # @abstract
7
+ # @return [Types::FunctionType]
8
+ def type
9
+ fail NotImplementedError
10
+ end
11
+
12
+ # @abstract
13
+ # @return [Symbol]
14
+ def visibility
15
+ fail NotImplementedError
16
+ end
17
+
18
+ # @abstract
19
+ # @return [String]
20
+ def name
21
+ fail NotImplementedError
22
+ end
23
+
24
+ # @abstract
25
+ # @return [String]
26
+ def namespace_path
27
+ fail NotImplementedError
28
+ end
29
+
30
+ # @abstract
31
+ # @return [String]
32
+ def document
33
+ fail NotImplementedError
34
+ end
35
+
36
+ # @abstract
37
+ # @return [ParameterList]
38
+ def parameters
39
+ fail NotImplementedError
40
+ end
41
+
42
+ # @abstract
43
+ # @return [Array<(String, Integer, Integer)>]
44
+ def sources
45
+ fail NotImplementedError
46
+ end
47
+
48
+ # @return [String]
49
+ def to_s
50
+ formatter.to_s
51
+ end
52
+
53
+ # @abstract
54
+ # @return [Types::Base, nil]
55
+ def parameter_type_of(param)
56
+ fail NotImplementedError
57
+ end
58
+
59
+ private
60
+
61
+ # @return [Formatter]
62
+ def formatter
63
+ @formatter ||= Formatter.new(self)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,70 @@
1
+ module Yoda
2
+ module Model
3
+ module FunctionSignatures
4
+ # Constructor provides a signature of `YourClass.new` from `initialize` method of the class.
5
+ class Constructor < Base
6
+ # @type Store::Objects::MethodObject
7
+ attr_reader :initialize_method
8
+
9
+ # @param namespace [Store::Objects::NamespaceObject]
10
+ # @param initialize_method [Store::Objects::MethodObject]
11
+ def initialize(namespace, initialize_method)
12
+ @namespace = namespace
13
+ @initialize_method = initialize_method
14
+ end
15
+
16
+ def type
17
+ type_builder.type
18
+ end
19
+
20
+ def name
21
+ 'new'
22
+ end
23
+
24
+ def visibility
25
+ :public
26
+ end
27
+
28
+ def sep
29
+ '.'
30
+ end
31
+
32
+ def namespace_path
33
+ initialize_method.namespace_path
34
+ end
35
+
36
+ # @return [String]
37
+ def document
38
+ initialize_method.document
39
+ end
40
+
41
+ # @return [Array<(String, Integer, Integer)>]
42
+ def sources
43
+ initialize_method.sources
44
+ end
45
+
46
+ # @return [ParameterList]
47
+ def parameters
48
+ @parameters ||= ParameterList.new(initialize_method.parameters)
49
+ end
50
+
51
+ # @return [(String, Integer, Integer), nil]
52
+ def primary_source
53
+ initialize_method.primary_source
54
+ end
55
+
56
+ # @return [Types::Base, nil]
57
+ def parameter_type_of(param)
58
+ type_builder.type_of(param)
59
+ end
60
+
61
+ private
62
+
63
+ # @return [TypeBuilder]
64
+ def type_builder
65
+ @type_builder ||= TypeBuilder.new(parameters, initialize_method.tag_list)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end