rucoa 0.8.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/Gemfile.lock +8 -8
  4. data/data/definitions_ruby_3_1 +0 -0
  5. data/lib/rucoa/configuration.rb +4 -1
  6. data/lib/rucoa/definition_store.rb +268 -75
  7. data/lib/rucoa/definitions/base.rb +14 -3
  8. data/lib/rucoa/definitions/class_definition.rb +20 -4
  9. data/lib/rucoa/definitions/constant_definition.rb +31 -19
  10. data/lib/rucoa/definitions/method_definition.rb +44 -52
  11. data/lib/rucoa/definitions/method_parameter_definition.rb +4 -1
  12. data/lib/rucoa/definitions/module_definition.rb +39 -0
  13. data/lib/rucoa/handler_concerns/diagnostics_publishable.rb +14 -3
  14. data/lib/rucoa/handlers/base.rb +12 -3
  15. data/lib/rucoa/handlers/initialized_handler.rb +33 -5
  16. data/lib/rucoa/handlers/text_document_completion_handler.rb +1 -1
  17. data/lib/rucoa/handlers/text_document_definition_handler.rb +3 -99
  18. data/lib/rucoa/handlers/text_document_did_open_handler.rb +1 -4
  19. data/lib/rucoa/handlers/text_document_hover_handler.rb +21 -13
  20. data/lib/rucoa/handlers/text_document_selection_range_handler.rb +8 -2
  21. data/lib/rucoa/location.rb +37 -0
  22. data/lib/rucoa/node_concerns/body.rb +24 -0
  23. data/lib/rucoa/node_concerns/{name_full_qualifiable.rb → qualified_name.rb} +2 -2
  24. data/lib/rucoa/node_concerns.rb +2 -1
  25. data/lib/rucoa/node_inspector.rb +22 -26
  26. data/lib/rucoa/nodes/base.rb +51 -10
  27. data/lib/rucoa/nodes/begin_node.rb +8 -0
  28. data/lib/rucoa/nodes/casgn_node.rb +1 -1
  29. data/lib/rucoa/nodes/cbase_node.rb +8 -0
  30. data/lib/rucoa/nodes/class_node.rb +63 -1
  31. data/lib/rucoa/nodes/const_node.rb +64 -5
  32. data/lib/rucoa/nodes/def_node.rb +11 -9
  33. data/lib/rucoa/nodes/defs_node.rb +21 -0
  34. data/lib/rucoa/nodes/lvar_node.rb +2 -1
  35. data/lib/rucoa/nodes/module_node.rb +2 -1
  36. data/lib/rucoa/nodes/send_node.rb +14 -10
  37. data/lib/rucoa/nodes.rb +3 -1
  38. data/lib/rucoa/parse_result.rb +29 -0
  39. data/lib/rucoa/parser.rb +40 -8
  40. data/lib/rucoa/parser_builder.rb +7 -1
  41. data/lib/rucoa/position.rb +10 -1
  42. data/lib/rucoa/range.rb +11 -1
  43. data/lib/rucoa/rbs/class_definition_mapper.rb +13 -28
  44. data/lib/rucoa/rbs/constant_definition_mapper.rb +12 -6
  45. data/lib/rucoa/rbs/method_definition_mapper.rb +12 -6
  46. data/lib/rucoa/rbs/module_definition_mapper.rb +34 -6
  47. data/lib/rucoa/rubocop/autocorrector.rb +2 -2
  48. data/lib/rucoa/rubocop/investigator.rb +6 -3
  49. data/lib/rucoa/server.rb +9 -3
  50. data/lib/rucoa/source.rb +57 -27
  51. data/lib/rucoa/source_store.rb +0 -13
  52. data/lib/rucoa/unqualified_name.rb +9 -0
  53. data/lib/rucoa/version.rb +1 -1
  54. data/lib/rucoa/yard/definition_generators/attribute_reader_definition_generator.rb +60 -0
  55. data/lib/rucoa/yard/definition_generators/attribute_writer_definition_generator.rb +60 -0
  56. data/lib/rucoa/yard/definition_generators/base.rb +117 -0
  57. data/lib/rucoa/yard/definition_generators/class_definition_generator.rb +66 -0
  58. data/lib/rucoa/yard/definition_generators/constant_assignment_definition_generator.rb +29 -0
  59. data/lib/rucoa/yard/definition_generators/method_definition_generator.rb +47 -0
  60. data/lib/rucoa/yard/definition_generators/module_definition_generator.rb +62 -0
  61. data/lib/rucoa/yard/definition_generators.rb +15 -0
  62. data/lib/rucoa/yard/definitions_loader.rb +44 -65
  63. data/lib/rucoa/yard/type.rb +46 -0
  64. data/lib/rucoa/yard.rb +2 -1
  65. data/lib/rucoa.rb +4 -1
  66. metadata +18 -4
  67. data/lib/rucoa/yard/method_definition_mapper.rb +0 -215
@@ -5,7 +5,9 @@ require 'parser/current'
5
5
  module Rucoa
6
6
  class ParserBuilder < ::Parser::Builders::Default
7
7
  NODE_CLASS_BY_TYPE = {
8
+ begin: Nodes::BeginNode,
8
9
  casgn: Nodes::CasgnNode,
10
+ cbase: Nodes::CbaseNode,
9
11
  class: Nodes::ClassNode,
10
12
  const: Nodes::ConstNode,
11
13
  def: Nodes::DefNode,
@@ -27,7 +29,11 @@ module Rucoa
27
29
  end
28
30
 
29
31
  # @note Override.
30
- def n(type, children, source_map)
32
+ def n(
33
+ type,
34
+ children,
35
+ source_map
36
+ )
31
37
  self.class.node_class_for(type).new(
32
38
  type,
33
39
  children,
@@ -39,11 +39,20 @@ module Rucoa
39
39
 
40
40
  # @param column [Integer] 0-origin column number
41
41
  # @param line [Integer] 1-origin line number
42
- def initialize(column: 0, line: 1)
42
+ def initialize(
43
+ column: 0,
44
+ line: 1
45
+ )
43
46
  @column = column
44
47
  @line = line
45
48
  end
46
49
 
50
+ # @param other [Rucoa::Position]
51
+ # @return [Boolean]
52
+ def ==(other)
53
+ column == other.column && line == other.line
54
+ end
55
+
47
56
  # @param text [String]
48
57
  # @return [Integer]
49
58
  def to_index_of(text)
data/lib/rucoa/range.rb CHANGED
@@ -31,12 +31,22 @@ module Rucoa
31
31
  # @param beginning [Rucoa::Position]
32
32
  # @param ending [Ruoca::Position]
33
33
  # @param including_ending [Boolean]
34
- def initialize(beginning, ending, including_ending: true)
34
+ def initialize(
35
+ beginning,
36
+ ending,
37
+ including_ending: true
38
+ )
35
39
  @beginning = beginning
36
40
  @ending = ending
37
41
  @including_ending = including_ending
38
42
  end
39
43
 
44
+ # @param other [Rucoa::Range]
45
+ # @return [Boolean]
46
+ def ==(other)
47
+ beginning == other.beginning && ending == other.ending
48
+ end
49
+
40
50
  # @param range [Rucoa::Range]
41
51
  # @return [Boolean]
42
52
  # @example returns true when the range is contained in self
@@ -2,43 +2,28 @@
2
2
 
3
3
  module Rucoa
4
4
  module Rbs
5
- class ClassDefinitionMapper
6
- class << self
7
- # @param declaration [RBS::AST::Declarations::Class]
8
- # @return [Rucoa::Definitions::ClassDefinition]
9
- def call(declaration:)
10
- new(declaration: declaration).call
11
- end
12
- end
13
-
14
- # @param declaration [RBS::AST::Declarations::Class]
15
- def initialize(declaration:)
16
- @declaration = declaration
17
- end
18
-
5
+ class ClassDefinitionMapper < ModuleDefinitionMapper
19
6
  # @return [Rucoa::Definitions::ClassDefinition]
7
+ # @example supports `include`
8
+ # definition_store = Rucoa::DefinitionStore.new
9
+ # definition_store.bulk_add(Rucoa::DefinitionArchiver.load)
10
+ # subject = definition_store.find_definition_by_qualified_name('Array')
11
+ # expect(subject.included_module_qualified_names).to include('Enumerable')
20
12
  def call
21
13
  Definitions::ClassDefinition.new(
22
- full_qualified_name: full_qualified_name,
23
- source_path: source_path,
24
- super_class_name: super_class_name
14
+ description: description,
15
+ included_module_qualified_names: included_module_qualified_names,
16
+ location: location,
17
+ prepended_module_qualified_names: prepended_module_qualified_names,
18
+ qualified_name: qualified_name,
19
+ super_class_qualified_name: super_class_qualified_name
25
20
  )
26
21
  end
27
22
 
28
23
  private
29
24
 
30
- # @return [String]
31
- def full_qualified_name
32
- @declaration.name.to_s.delete_prefix('::')
33
- end
34
-
35
- # @return [String]
36
- def source_path
37
- @declaration.location.name
38
- end
39
-
40
25
  # @return [String, nil]
41
- def super_class_name
26
+ def super_class_qualified_name
42
27
  @declaration.super_class&.name&.to_s&.delete_prefix('::')
43
28
  end
44
29
  end
@@ -19,21 +19,27 @@ module Rucoa
19
19
  # @return [Rucoa::Definitions::ConstantDefinition]
20
20
  def call
21
21
  Definitions::ConstantDefinition.new(
22
- full_qualified_name: full_qualified_name,
23
- source_path: source_path
22
+ description: description,
23
+ location: location,
24
+ qualified_name: qualified_name
24
25
  )
25
26
  end
26
27
 
27
28
  private
28
29
 
30
+ # @return [String, nil]
31
+ def description
32
+ @declaration.comment&.string&.sub(/\A\s*<!--.*-->\s*/m, '')
33
+ end
34
+
29
35
  # @return [String]
30
- def full_qualified_name
36
+ def qualified_name
31
37
  @declaration.name.to_s.delete_prefix('::')
32
38
  end
33
39
 
34
- # @return [String]
35
- def source_path
36
- @declaration.location.name
40
+ # @return [Rucoa::Location]
41
+ def location
42
+ Location.from_rbs_location(@declaration.location)
37
43
  end
38
44
  end
39
45
  end
@@ -7,7 +7,10 @@ module Rucoa
7
7
  # @param declaration [RBS::AST::Declarations::Class, RBS::AST::Declarations::Module]
8
8
  # @param method_definition [RBS::AST::Members::MethodDefinition]
9
9
  # @return [Rucoa::Definitions::MethodDefinition]
10
- def call(declaration:, method_definition:)
10
+ def call(
11
+ declaration:,
12
+ method_definition:
13
+ )
11
14
  new(
12
15
  declaration: declaration,
13
16
  method_definition: method_definition
@@ -17,7 +20,10 @@ module Rucoa
17
20
 
18
21
  # @param declaration [RBS::AST::Declarations::Class, RBS::AST::Declarations::Module]
19
22
  # @param method_definition [RBS::AST::Members::MethodDefinition]
20
- def initialize(declaration:, method_definition:)
23
+ def initialize(
24
+ declaration:,
25
+ method_definition:
26
+ )
21
27
  @declaration = declaration
22
28
  @method_definition = method_definition
23
29
  end
@@ -27,9 +33,9 @@ module Rucoa
27
33
  Definitions::MethodDefinition.new(
28
34
  description: description,
29
35
  kind: kind,
36
+ location: location,
30
37
  method_name: method_name,
31
38
  namespace: namespace,
32
- source_path: source_path,
33
39
  types: types
34
40
  )
35
41
  end
@@ -65,9 +71,9 @@ module Rucoa
65
71
  @method_definition.kind
66
72
  end
67
73
 
68
- # @return [String]
69
- def source_path
70
- @declaration.location.name
74
+ # @return [Rucoa::Location]
75
+ def location
76
+ Location.from_rbs_location(@method_definition.location)
71
77
  end
72
78
 
73
79
  class MethodTypeMapper
@@ -19,21 +19,49 @@ module Rucoa
19
19
  # @return [Rucoa::Definitions::ModuleDefinition]
20
20
  def call
21
21
  Definitions::ModuleDefinition.new(
22
- full_qualified_name: full_qualified_name,
23
- source_path: source_path
22
+ description: description,
23
+ included_module_qualified_names: included_module_qualified_names,
24
+ location: location,
25
+ prepended_module_qualified_names: prepended_module_qualified_names,
26
+ qualified_name: qualified_name
24
27
  )
25
28
  end
26
29
 
27
30
  private
28
31
 
32
+ # @return [String, nil]
33
+ def description
34
+ @declaration.comment&.string&.sub(/\A\s*<!--.*-->\s*/m, '')
35
+ end
36
+
29
37
  # @return [String]
30
- def full_qualified_name
38
+ def qualified_name
31
39
  @declaration.name.to_s.delete_prefix('::')
32
40
  end
33
41
 
34
- # @return [String]
35
- def source_path
36
- @declaration.location.name
42
+ # @return [Rucoa::Location]
43
+ def location
44
+ Location.from_rbs_location(@declaration.location)
45
+ end
46
+
47
+ # @return [Array<String>]
48
+ def included_module_qualified_names
49
+ @declaration.members.filter_map do |member|
50
+ case member
51
+ when ::RBS::AST::Members::Include
52
+ member.name.to_s.delete_prefix('::')
53
+ end
54
+ end
55
+ end
56
+
57
+ # @return [Array<String>]
58
+ def prepended_module_qualified_names
59
+ @declaration.members.filter_map do |member|
60
+ case member
61
+ when ::RBS::AST::Members::Prepend
62
+ member.name.to_s.delete_prefix('::')
63
+ end
64
+ end
37
65
  end
38
66
  end
39
67
  end
@@ -40,10 +40,10 @@ module Rucoa
40
40
 
41
41
  # @return [String]
42
42
  def path
43
- if @source.untitled? || @source.path.nil?
43
+ if @source.untitled?
44
44
  'untitled'
45
45
  else
46
- @source.path
46
+ @source.name
47
47
  end
48
48
  end
49
49
  end
@@ -41,17 +41,20 @@ module Rucoa
41
41
  # @param file [String]
42
42
  # @param offenses [Array<RuboCop::Cop::Offense>]
43
43
  # @return [void]
44
- def file_finished(file, offenses)
44
+ def file_finished(
45
+ file,
46
+ offenses
47
+ )
45
48
  @offenses = offenses
46
49
  super
47
50
  end
48
51
 
49
52
  # @return [String]
50
53
  def path
51
- if @source.untitled? || @source.path.nil?
54
+ if @source.untitled?
52
55
  'untitled'
53
56
  else
54
- @source.path
57
+ @source.name
55
58
  end
56
59
  end
57
60
  end
data/lib/rucoa/server.rb CHANGED
@@ -59,7 +59,7 @@ module Rucoa
59
59
  @source_store = SourceStore.new
60
60
 
61
61
  @definition_store = DefinitionStore.new
62
- @definition_store.definitions += DefinitionArchiver.load
62
+ @definition_store.bulk_add(DefinitionArchiver.load)
63
63
  end
64
64
 
65
65
  # @return [void]
@@ -83,7 +83,10 @@ module Rucoa
83
83
  # @yieldparam response [Hash]
84
84
  # @param message [Hash]
85
85
  # @return [void]
86
- def write(message, &block)
86
+ def write(
87
+ message,
88
+ &block
89
+ )
87
90
  if block
88
91
  write_server_request(message, &block)
89
92
  else
@@ -139,7 +142,10 @@ module Rucoa
139
142
 
140
143
  # @param message [Hash]
141
144
  # @return [void]
142
- def write_server_request(message, &block)
145
+ def write_server_request(
146
+ message,
147
+ &block
148
+ )
143
149
  message = message.merge('id' => @server_request_id)
144
150
  debug do
145
151
  {
data/lib/rucoa/source.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'uri'
4
+
3
5
  module Rucoa
4
6
  class Source
5
7
  # @return [String]
@@ -9,8 +11,11 @@ module Rucoa
9
11
  attr_reader :uri
10
12
 
11
13
  # @param content [String]
12
- # @param uri [String, nil]
13
- def initialize(content:, uri: nil)
14
+ # @param uri [String]
15
+ def initialize(
16
+ content:,
17
+ uri:
18
+ )
14
19
  @content = content
15
20
  @uri = uri
16
21
  end
@@ -33,35 +38,49 @@ module Rucoa
33
38
  # a_kind_of(Rucoa::Definitions::MethodDefinition)
34
39
  # ]
35
40
  # )
41
+ # @example returns empty array when failed to parse
42
+ # source = Rucoa::Source.new(
43
+ # content: 'class Foo',
44
+ # uri: 'file:///path/to/foo.rb'
45
+ # )
46
+ # expect(source.definitions).to eq([])
47
+ # @example returns empty array when no node is found from content
48
+ # source = Rucoa::Source.new(
49
+ # content: '',
50
+ # uri: 'file:///path/to/foo.rb'
51
+ # )
52
+ # expect(source.definitions).to eq([])
36
53
  def definitions
37
- @definitions ||= Yard::DefinitionsLoader.load_string(
38
- content: @content,
39
- path: path
40
- )
54
+ @definitions ||=
55
+ if parse_result.failed? || root_node.nil?
56
+ []
57
+ else
58
+ Yard::DefinitionsLoader.call(
59
+ associations: parse_result.associations,
60
+ root_node: parse_result.root_node
61
+ )
62
+ end
41
63
  end
42
64
 
43
65
  # @return [String, nil]
44
- # @example returns path from given VSCode URI
66
+ # @example returns path for file URI
45
67
  # source = Rucoa::Source.new(
46
68
  # content: '',
47
69
  # uri: 'file:///path/to/foo.rb'
48
70
  # )
49
- # expect(source.path).to eq('/path/to/foo.rb')
50
- # @example returns name for untitled URI
71
+ # expect(source.name).to eq('/path/to/foo.rb')
72
+ # @example returns opaque for untitled URI
51
73
  # source = Rucoa::Source.new(
52
74
  # content: '',
53
75
  # uri: 'untitled:Untitled-1'
54
76
  # )
55
- # expect(source.path).to eq('Untitled-1')
56
- def path
57
- return unless @uri
58
-
59
- return @uri.split(':', 2).last if untitled?
60
-
61
- path = ::URI.parse(@uri).path
62
- return unless path
63
-
64
- ::CGI.unescape(path)
77
+ # expect(source.name).to eq('Untitled-1')
78
+ def name
79
+ if untitled?
80
+ uri_object.opaque
81
+ else
82
+ uri_object.path
83
+ end
65
84
  end
66
85
 
67
86
  # @param position [Rucoa::Position]
@@ -70,34 +89,45 @@ module Rucoa
70
89
  root_and_descendant_nodes.reverse.find do |node|
71
90
  node.include_position?(position)
72
91
  end
73
- rescue ::Parser::SyntaxError
74
- nil
75
92
  end
76
93
 
77
94
  # @return [Rucoa::Nodes::Base, nil]
78
95
  def root_node
79
- @root_node ||= Parser.call(@content)
80
- rescue ::Parser::SyntaxError
81
- nil
96
+ parse_result.root_node
82
97
  end
83
98
 
84
99
  # @return [Boolean]
85
- def syntax_error?
86
- root_node.nil?
100
+ def failed_to_parse?
101
+ parse_result.failed?
87
102
  end
88
103
 
89
104
  # @return [Boolean]
90
105
  def untitled?
91
- @uri&.start_with?('untitled:')
106
+ uri_object.scheme == 'untitled'
92
107
  end
93
108
 
94
109
  private
95
110
 
111
+ # @return [Rucoa::ParseResult]
112
+ def parse_result
113
+ return @parse_result if instance_variable_defined?(:@parse_result)
114
+
115
+ @parse_result = Parser.call(
116
+ text: @content,
117
+ uri: @uri
118
+ )
119
+ end
120
+
96
121
  # @return [Array<Rucoa::Nodes::Base>]
97
122
  def root_and_descendant_nodes
98
123
  return [] unless root_node
99
124
 
100
125
  [root_node, *root_node.descendants]
101
126
  end
127
+
128
+ # @return [URI]
129
+ def uri_object
130
+ @uri_object ||= ::URI.parse(@uri)
131
+ end
102
132
  end
103
133
  end
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cgi'
4
- require 'uri'
5
-
6
3
  module Rucoa
7
4
  class SourceStore
8
5
  def initialize
@@ -26,15 +23,5 @@ module Rucoa
26
23
  def each_uri(&block)
27
24
  @data.each_key(&block)
28
25
  end
29
-
30
- private
31
-
32
- # @param uri [String]
33
- # @return [String]
34
- def path_from_uri(uri)
35
- ::CGI.unescape(
36
- ::URI.parse(uri).path || 'untitled'
37
- )
38
- end
39
26
  end
40
27
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ UnqualifiedName = ::Struct.new(
5
+ :chained_name,
6
+ :module_nesting,
7
+ keyword_init: true
8
+ )
9
+ end
data/lib/rucoa/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rucoa
4
- VERSION = '0.8.0'
4
+ VERSION = '0.10.0'
5
5
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Yard
5
+ module DefinitionGenerators
6
+ class AttributeReaderDefinitionGenerator < Base
7
+ READER_METHOD_NAMES = ::Set[
8
+ 'attr_accessor',
9
+ 'attr_reader'
10
+ ].freeze
11
+
12
+ # @example returns method definition for attr_reader node
13
+ # definitions = Rucoa::Source.new(
14
+ # content: <<~RUBY,
15
+ # class Foo
16
+ # attr_reader :bar
17
+ # end
18
+ # RUBY
19
+ # uri: '/path/to/foo.rb'
20
+ # ).definitions
21
+ # expect(definitions[1]).to be_a(Rucoa::Definitions::MethodDefinition)
22
+ # @example returns method definition for attr_accessor node
23
+ # definitions = Rucoa::Source.new(
24
+ # content: <<~RUBY,
25
+ # class Foo
26
+ # attr_accessor :bar
27
+ # end
28
+ # RUBY
29
+ # uri: '/path/to/foo.rb'
30
+ # ).definitions
31
+ # expect(definitions.map(&:qualified_name)).to eq(
32
+ # %w[
33
+ # Foo
34
+ # Foo#bar
35
+ # Foo#bar=
36
+ # ]
37
+ # )
38
+ def call
39
+ return [] unless @node.is_a?(Nodes::SendNode) && READER_METHOD_NAMES.include?(@node.name)
40
+
41
+ @node.arguments.map do |argument|
42
+ Definitions::MethodDefinition.new(
43
+ description: description,
44
+ kind: :instance,
45
+ location: location,
46
+ method_name: argument.value.to_s,
47
+ namespace: @node.namespace,
48
+ types: return_types.map do |type|
49
+ Types::MethodType.new(
50
+ parameters_string: '', # TODO
51
+ return_type: type
52
+ )
53
+ end
54
+ )
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module Yard
5
+ module DefinitionGenerators
6
+ class AttributeWriterDefinitionGenerator < Base
7
+ WRITER_METHOD_NAMES = ::Set[
8
+ 'attr_accessor',
9
+ 'attr_writer'
10
+ ].freeze
11
+
12
+ # @example returns method definition for attr_writer node
13
+ # definitions = Rucoa::Source.new(
14
+ # content: <<~RUBY,
15
+ # class Foo
16
+ # attr_writer :bar
17
+ # end
18
+ # RUBY
19
+ # uri: '/path/to/foo.rb'
20
+ # ).definitions
21
+ # expect(definitions[1]).to be_a(Rucoa::Definitions::MethodDefinition)
22
+ # @example returns method definition for attr_accessor node
23
+ # definitions = Rucoa::Source.new(
24
+ # content: <<~RUBY,
25
+ # class Foo
26
+ # attr_accessor :bar
27
+ # end
28
+ # RUBY
29
+ # uri: '/path/to/foo.rb'
30
+ # ).definitions
31
+ # expect(definitions.map(&:qualified_name)).to eq(
32
+ # %w[
33
+ # Foo
34
+ # Foo#bar
35
+ # Foo#bar=
36
+ # ]
37
+ # )
38
+ def call
39
+ return [] unless @node.is_a?(Nodes::SendNode) && WRITER_METHOD_NAMES.include?(@node.name)
40
+
41
+ @node.arguments.map do |argument|
42
+ Definitions::MethodDefinition.new(
43
+ description: description,
44
+ kind: :instance,
45
+ location: location,
46
+ method_name: "#{argument.value}=",
47
+ namespace: @node.namespace,
48
+ types: return_types.map do |type|
49
+ Types::MethodType.new(
50
+ parameters_string: 'value', # TODO
51
+ return_type: type
52
+ )
53
+ end
54
+ )
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end