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,41 @@
1
+ module Yoda
2
+ module Store
3
+ module Objects
4
+ class MetaClassObject < NamespaceObject
5
+ # @param path [String]
6
+ # @return [String]
7
+ def self.address_of(path)
8
+ "#{path}%class"
9
+ end
10
+
11
+ # @param path [String]
12
+ # @param document [Document, nil]
13
+ # @param tag_list [TagList, nil]
14
+ # @param instance_method_paths [Array<String>]
15
+ # @param instance_mixin_paths [Array<String>]
16
+ def initialize(**kwargs)
17
+ super(kwargs)
18
+ end
19
+
20
+ # @return [String]
21
+ def name
22
+ @name ||= path.match(MODULE_TAIL_PATTERN) { |md| md[1] || md[2] }
23
+ end
24
+
25
+ def kind
26
+ :meta_class
27
+ end
28
+
29
+ # @return [String]
30
+ def address
31
+ MetaClassObject.address_of(path)
32
+ end
33
+
34
+ # @return [String]
35
+ def base_class_address
36
+ path
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,94 @@
1
+ module Yoda
2
+ module Store
3
+ module Objects
4
+ class MethodObject < Base
5
+ # @return [Array<(String, String)>]
6
+ attr_reader :parameters
7
+
8
+ # @return [Symbol]
9
+ attr_reader :visibility
10
+
11
+ # @return [Array<Overload>]
12
+ attr_reader :overloads
13
+
14
+ class << self
15
+ # @param path [String]
16
+ # @return [String]
17
+ def namespace_of_path(path)
18
+ path.slice(0, (path.rindex(/[#.]/) || 0))
19
+ end
20
+
21
+ # @param path [String]
22
+ # @return [String]
23
+ def name_of_path(path)
24
+ path.slice((path.rindex(/[#.]/) || -1) + 1, path.length)
25
+ end
26
+
27
+ # @param path [String]
28
+ # @return [String]
29
+ def sep_of_path(path)
30
+ path.slice(path.rindex(/[#.]/))
31
+ end
32
+
33
+ # @return [Array<Symbol>]
34
+ def attr_names
35
+ super + %i(parameters visibility overloads)
36
+ end
37
+ end
38
+
39
+ # @param path [String]
40
+ # @param document [Document, nil]
41
+ # @param tag_list [TagList, nil]
42
+ # @param visibility [Symbol]
43
+ # @param overloads [Array<Overload>]
44
+ # @param parameters [Array<(String, String)>, nil]
45
+ def initialize(parameters: [], visibility: :public, overloads: [], **kwargs)
46
+ super(kwargs)
47
+ fail ArgumentError, visibility unless %i(public private protected)
48
+ @visibility = visibility.to_sym
49
+ @parameters = parameters
50
+ @overloads = overloads
51
+ end
52
+
53
+ # @return [String]
54
+ def name
55
+ @name ||= MethodObject.name_of_path(path)
56
+ end
57
+
58
+ # @return [String]
59
+ def sep
60
+ @sep ||= MethodObject.sep_of_path(path)
61
+ end
62
+
63
+ # @return [String]
64
+ def namespace_path
65
+ @namespace_path ||= MethodObject.namespace_of_path(path)
66
+ end
67
+
68
+ def kind
69
+ :method
70
+ end
71
+
72
+ def to_h
73
+ super.merge(
74
+ parameters: parameters.to_a,
75
+ visibility: visibility,
76
+ overloads: overloads,
77
+ )
78
+ end
79
+
80
+ private
81
+
82
+ # @param another [self]
83
+ # @return [Hash]
84
+ def merge_attributes(another)
85
+ super.merge(
86
+ visibility: another.visibility,
87
+ parameters: another.parameters.to_a,
88
+ overloads: overloads + another.overloads,
89
+ )
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,11 @@
1
+ module Yoda
2
+ module Store
3
+ module Objects
4
+ class ModuleObject < NamespaceObject
5
+ def kind
6
+ :module
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,67 @@
1
+ module Yoda
2
+ module Store
3
+ module Objects
4
+ # @abstract
5
+ class NamespaceObject < Base
6
+ # @return [Array<String>]
7
+ attr_reader :instance_method_addresses
8
+
9
+ # @type Array<String>
10
+ attr_reader :mixin_addresses
11
+
12
+ # @type Array<String>
13
+ attr_reader :constant_addresses
14
+
15
+ # @return [Enumerable<NamespaceObject>]
16
+ attr_accessor :ancestors
17
+
18
+ # @return [Enumerable<MethodObject>]
19
+ attr_accessor :methods
20
+
21
+ # @return [Array<Symbol>]
22
+ def self.attr_names
23
+ super + %i(instance_method_addresses mixin_addresses constant_addresses)
24
+ end
25
+
26
+ # @param path [String]
27
+ # @param document [Document, nil]
28
+ # @param tag_list [TagList, nil]
29
+ # @param instance_method_paths [Array<String>]
30
+ # @param constant_addresses [Array<String>]
31
+ # @param mixin_addresses [Array<String>]
32
+ def initialize(instance_method_addresses: [], mixin_addresses: [], constant_addresses: [], **kwargs)
33
+ super(kwargs)
34
+ @instance_method_addresses = instance_method_addresses
35
+ @mixin_addresses = mixin_addresses
36
+ @constant_addresses = constant_addresses
37
+ @ancestors ||= []
38
+ end
39
+
40
+ # @return [String]
41
+ def name
42
+ @name ||= path.match(MODULE_TAIL_PATTERN) { |md| md[1] || md[2] }
43
+ end
44
+
45
+ def to_h
46
+ super.merge(
47
+ instance_method_addresses: instance_method_addresses,
48
+ mixin_addresses: mixin_addresses,
49
+ constant_addresses: constant_addresses,
50
+ )
51
+ end
52
+
53
+ private
54
+
55
+ # @param another [self]
56
+ # @return [Hash]
57
+ def merge_attributes(another)
58
+ super.merge(
59
+ instance_method_addresses: (instance_method_addresses + another.instance_method_addresses).uniq,
60
+ mixin_addresses: (mixin_addresses + another.mixin_addresses).uniq,
61
+ constant_addresses: (constant_addresses + another.constant_addresses).uniq,
62
+ )
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,51 @@
1
+ module Yoda
2
+ module Store
3
+ module Objects
4
+ class Overload
5
+ class << self
6
+ def json_creatable?
7
+ true
8
+ end
9
+
10
+ # @param params [Hash]
11
+ def json_create(params)
12
+ new(params.map { |k, v| [k.to_sym, v] }.select { |(k, v)| %i(name tag_list document parameters).include?(k) }.to_h)
13
+ end
14
+ end
15
+
16
+ # @return [String]
17
+ attr_reader :name
18
+
19
+ # @return [Array<(String, String)>]
20
+ attr_reader :parameters
21
+
22
+ # @return [String, nil]
23
+ attr_reader :document
24
+
25
+ # @return [Array<Tag>]
26
+ attr_reader :tag_list
27
+
28
+ # @param name [String]
29
+ # @param parameters [Array<(String, String)>]
30
+ # @param document [String]
31
+ # @param tag_list [Array<Tag>]
32
+ def initialize(name:, parameters: [], document: '', tag_list: [])
33
+ @name = name
34
+ @parameters = parameters
35
+ @document = document
36
+ @tag_list = tag_list
37
+ end
38
+
39
+ # @return [Hash]
40
+ def to_h
41
+ { name: name, parameters: parameters, document: document, tag_list: tag_list }
42
+ end
43
+
44
+ # @return [String]
45
+ def to_json(_mode = nil)
46
+ to_h.merge(json_class: self.class.name).to_json
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,46 @@
1
+ module Yoda
2
+ module Store
3
+ module Objects
4
+ class Patch
5
+ # @param id [String]
6
+ attr_reader :id
7
+
8
+ # @param registry [Hash{ Symbol => Addressable }]
9
+ attr_reader :registry
10
+
11
+ # @param id [String]
12
+ def initialize(id)
13
+ @id = id
14
+ @registry = Hash.new
15
+ end
16
+
17
+ # @param addressable [Addressable]
18
+ # @return [void]
19
+ def register(addressable)
20
+ if el = @registry[addressable.address.to_sym]
21
+ @registry[addressable.address.to_sym] = el.merge(addressable)
22
+ else
23
+ @registry[addressable.address.to_sym] = addressable
24
+ end
25
+ end
26
+
27
+ # @param address [String, Symbol]
28
+ # @return [Addressable, nil]
29
+ def find(address)
30
+ @registry[address.to_sym]
31
+ end
32
+
33
+ # @param address [String, Symbol]
34
+ # @return [true, false]
35
+ def has_key?(address)
36
+ @registry.has_key?(address.to_sym)
37
+ end
38
+
39
+ # @return [Array<Symbol>]
40
+ def keys
41
+ @registry.keys
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,80 @@
1
+ module Yoda
2
+ module Store
3
+ module Objects
4
+ # PatchSet manages patch updates and patch outdates.
5
+ # Besides, this class provides api to modify objects by using owning patches.
6
+ class PatchSet
7
+ # @return [{ Symbol => Array<Symbol> }]
8
+ attr_reader :address_index
9
+
10
+ # @return [{ Symbol => Patch }]
11
+ attr_reader :patches
12
+
13
+ def initialize
14
+ @patches = Hash.new
15
+ @address_index = Hash.new
16
+ end
17
+
18
+ # @param patch [Patch]
19
+ # @return [void]
20
+ def register(patch)
21
+ register_to_index(patch)
22
+ patches[patch.id.to_sym] = patch
23
+ end
24
+
25
+ # @param id [String, Symbol]
26
+ def delete(id)
27
+ patches.delete(id.to_sym)
28
+ end
29
+
30
+ # @param object [Addressable]
31
+ # @return [Addressable]
32
+ def patch(object)
33
+ check_outdated_index(object.address.to_sym)
34
+ objects_in_patch = (address_index[object.address.to_sym] || []).map { |patch_id| patches[patch_id].find(object.address.to_sym) }
35
+ Merger.new([object, *objects_in_patch]).merged_instance
36
+ end
37
+
38
+ # @param address [String, Symbol]
39
+ # @return [Addressable, nil]
40
+ def find(address)
41
+ check_outdated_index(address.to_sym)
42
+ if (patch_ids = address_index[address.to_sym] || []).empty?
43
+ nil
44
+ else
45
+ objects = patch_ids.map { |id| patches[id].find(address.to_sym) }
46
+ Merger.new(objects).merged_instance
47
+ end
48
+ end
49
+
50
+ # @return [Array<Symbol>]
51
+ def keys
52
+ address_index.keys
53
+ end
54
+
55
+ # @param address [String, Symbol]
56
+ # @return [true, false]
57
+ def has_key?(address)
58
+ check_outdated_index(address.to_sym)
59
+ address_index[address.to_sym] && !address_index[address.to_sym].empty?
60
+ end
61
+
62
+ private
63
+
64
+ # @param patch [Patch]
65
+ # @return [void]
66
+ def register_to_index(patch)
67
+ patch.keys.each do |key|
68
+ address_index[key.to_sym] ||= []
69
+ address_index[key.to_sym].push(patch.id.to_sym)
70
+ end
71
+ end
72
+
73
+ # @param address [Symbol]
74
+ def check_outdated_index(address)
75
+ (address_index[address] || []).select! { |patch_id| patches[patch_id].has_key?(address) }
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,62 @@
1
+ module Yoda
2
+ module Store
3
+ module Objects
4
+ class Tag
5
+ class << self
6
+ def json_creatable?
7
+ true
8
+ end
9
+
10
+ # @param params [Hash]
11
+ def json_create(params)
12
+ new(params.map { |k, v| [k.to_sym, v] }.select { |(k, v)| %i(tag_name name yard_types text lexical_scope).include?(k) }.to_h)
13
+ end
14
+ end
15
+
16
+ # @return [String]
17
+ attr_reader :tag_name
18
+
19
+ # @return [String, nil]
20
+ attr_reader :name, :text
21
+
22
+ # @return [Array<String>]
23
+ attr_reader :yard_types, :lexical_scope
24
+
25
+ # @param tag_name [String]
26
+ # @param name [String, nil]
27
+ # @param yard_types [Array<String>]
28
+ # @param text [String, nil]
29
+ # @param lexical_scope [Array<String>]
30
+ def initialize(tag_name:, name: nil, yard_types: [], text: nil, lexical_scope: [])
31
+ @tag_name = tag_name
32
+ @name = name
33
+ @yard_types = yard_types
34
+ @text = text
35
+ @lexical_scope = lexical_scope
36
+ end
37
+
38
+ # @return [Hash]
39
+ def to_h
40
+ { name: name, tag_name: tag_name, yard_types: yard_types, text: text, lexical_scope: lexical_scope }
41
+ end
42
+
43
+ def hash
44
+ ([self.class.name] + to_h.to_a).hash
45
+ end
46
+
47
+ def eql?(another)
48
+ self.class == another.class && to_h == another.to_h
49
+ end
50
+
51
+ def ==(another)
52
+ eql?(another)
53
+ end
54
+
55
+ # @return [String]
56
+ def to_json(_state = nil)
57
+ to_h.merge(json_class: self.class.name).to_json
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end