masamune-ast 1.2.0 → 2.0.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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/Gemfile.lock +5 -1
  4. data/README.md +30 -82
  5. data/lib/masamune/abstract_syntax_tree/prism/node_extensions.rb +82 -0
  6. data/lib/masamune/abstract_syntax_tree/visitors/block_parameters_visitor.rb +18 -0
  7. data/lib/masamune/abstract_syntax_tree/visitors/method_calls_visitor.rb +19 -0
  8. data/lib/masamune/abstract_syntax_tree/visitors/method_definitions_visitor.rb +17 -0
  9. data/lib/masamune/abstract_syntax_tree/visitors/parameters_visitor.rb +18 -0
  10. data/lib/masamune/abstract_syntax_tree/visitors/strings_visitor.rb +17 -0
  11. data/lib/masamune/abstract_syntax_tree/visitors/symbols_visitor.rb +17 -0
  12. data/lib/masamune/abstract_syntax_tree/visitors/variables_visitor.rb +34 -0
  13. data/lib/masamune/abstract_syntax_tree.rb +57 -151
  14. data/lib/masamune/lex_node.rb +6 -6
  15. data/lib/masamune/slasher.rb +9 -15
  16. data/lib/masamune/version.rb +1 -1
  17. data/lib/masamune.rb +10 -23
  18. metadata +26 -24
  19. data/lib/masamune/abstract_syntax_tree/data_node.rb +0 -65
  20. data/lib/masamune/abstract_syntax_tree/node.rb +0 -41
  21. data/lib/masamune/abstract_syntax_tree/nodes/assign.rb +0 -11
  22. data/lib/masamune/abstract_syntax_tree/nodes/blocks/brace_block.rb +0 -13
  23. data/lib/masamune/abstract_syntax_tree/nodes/blocks/do_block.rb +0 -13
  24. data/lib/masamune/abstract_syntax_tree/nodes/call.rb +0 -17
  25. data/lib/masamune/abstract_syntax_tree/nodes/command.rb +0 -64
  26. data/lib/masamune/abstract_syntax_tree/nodes/def.rb +0 -17
  27. data/lib/masamune/abstract_syntax_tree/nodes/params.rb +0 -23
  28. data/lib/masamune/abstract_syntax_tree/nodes/program.rb +0 -16
  29. data/lib/masamune/abstract_syntax_tree/nodes/string_content.rb +0 -17
  30. data/lib/masamune/abstract_syntax_tree/nodes/support_nodes/block.rb +0 -18
  31. data/lib/masamune/abstract_syntax_tree/nodes/support_nodes/comment.rb +0 -25
  32. data/lib/masamune/abstract_syntax_tree/nodes/symbol.rb +0 -17
  33. data/lib/masamune/abstract_syntax_tree/nodes/symbols/dyna_symbol.rb +0 -20
  34. data/lib/masamune/abstract_syntax_tree/nodes/symbols/symbol_literal.rb +0 -21
  35. data/lib/masamune/abstract_syntax_tree/nodes/variables/block_var.rb +0 -22
  36. data/lib/masamune/abstract_syntax_tree/nodes/variables/var_field.rb +0 -17
  37. data/lib/masamune/abstract_syntax_tree/nodes/variables/var_ref.rb +0 -19
  38. data/lib/masamune/abstract_syntax_tree/nodes/vcall.rb +0 -17
@@ -1,173 +1,91 @@
1
+ require_relative "abstract_syntax_tree/prism/node_extensions"
2
+
1
3
  module Masamune
2
4
  class AbstractSyntaxTree
3
- attr_reader :code, :tree, :comment_list
4
- attr_accessor :node_list, :data_node_list, :lex_nodes
5
+ attr_reader :code, :prism, :ripper
6
+ attr_accessor :lex_nodes
5
7
 
6
8
  def initialize(code)
7
9
  @code = code
8
- @tree = Ripper.sexp(code)
10
+ @prism = Prism.parse(code)
11
+ @ripper = Ripper.sexp(code)
9
12
  raw_lex_nodes = Ripper.lex(code)
10
13
  @lex_nodes = raw_lex_nodes.map do |lex_node|
11
14
  LexNode.new(raw_lex_nodes.index(lex_node), lex_node, self.__id__)
12
15
  end
13
-
14
- @node_list = []
15
- @data_node_list = []
16
- @comment_list = []
17
- register_nodes(@tree)
18
-
19
- # Refer to Masamune::AbstractSyntaxTree::Comment
20
- # to see why we register these separately.
21
- register_comments
22
- end
23
-
24
- def register_nodes(tree_node = self.tree)
25
- if tree_node.is_a?(Array)
26
- klass = get_node_class(tree_node.first)
27
- msmn_node = klass.new(tree_node, self.__id__)
28
- else
29
- # Create a general node if the node is a single value.
30
- msmn_node = Node.new(tree_node, self.__id__)
31
- end
32
-
33
- # Register nodes and any data nodes housed within it.
34
- # See Masamune::AbstractSyntaxTree::DataNode for more details on what a data node is.
35
- @node_list << msmn_node
36
- msmn_node.data_nodes.each { |dn| @data_node_list << dn } if msmn_node.data_nodes
37
-
38
- # Continue down the tree until base case is reached.
39
- if !msmn_node.nil? && msmn_node.contents.is_a?(Array)
40
- msmn_node.contents.each { |node| register_nodes(node) }
41
- end
42
16
  end
43
17
 
44
- def register_comments
45
- comment_lex_nodes = @lex_nodes.select {|node| node.type == :comment}.flatten
46
- @comment_list << comment_lex_nodes.map {|node| Comment.new(node, self.__id__)}
47
- @comment_list.flatten!
18
+ def variables(token_value: nil)
19
+ visitor = VariablesVisitor.new(token_value)
20
+ @prism.value.accept(visitor)
21
+ visitor.results
48
22
  end
49
23
 
50
- # TODO: A lot of these methods have the same content,
51
- # so I want to come up with a way to refactor these.
52
-
53
- # TODO: Add block_params: true to the arguments.
54
- def variables(name: nil, result_type: Hash)
55
- var_classes = [
56
- :var_field,
57
- :var_ref,
58
- :params
59
- ].map {|type| get_node_class(type)}
60
- results = find_nodes(var_classes, token: name, result_type: result_type)
61
- order_results(results)
24
+ def strings(token_value: nil)
25
+ visitor = StringsVisitor.new(token_value)
26
+ @prism.value.accept(visitor)
27
+ visitor.results
62
28
  end
63
29
 
64
- def strings(content: nil, result_type: Hash)
65
- results = find_nodes(get_node_class(:string_content), token: content, result_type: result_type)
66
- order_results(results)
30
+ def all_methods(token_value: nil)
31
+ order_nodes(method_definitions(token_value: token_value) + method_calls(token_value: token_value))
67
32
  end
68
33
 
69
- def method_definitions(name: nil, result_type: Hash)
70
- results = find_nodes(get_node_class(:def), token: name, result_type: result_type)
71
- order_results(results)
34
+ def method_definitions(token_value: nil)
35
+ visitor = MethodDefinitionsVisitor.new(token_value)
36
+ @prism.value.accept(visitor)
37
+ visitor.results
72
38
  end
73
39
 
74
- def method_calls(name: nil, result_type: Hash)
75
- method_classes = [
76
- :vcall,
77
- :call,
78
- :command
79
- ].map {|type| get_node_class(type)}
80
- results = find_nodes(method_classes, token: name, result_type: result_type)
81
- order_results(results)
40
+ def method_calls(token_value: nil)
41
+ visitor = MethodCallsVisitor.new(token_value)
42
+ @prism.value.accept(visitor)
43
+ visitor.results
82
44
  end
83
45
 
84
- # TODO
85
- def do_block_params
46
+ def symbols(token_value: nil)
47
+ visitor = SymbolsVisitor.new(token_value)
48
+ @prism.value.accept(visitor)
49
+ visitor.results
86
50
  end
87
51
 
88
- # TODO
89
- def brace_block_params
90
- end
91
-
92
- def symbols(content: nil, result_type: Hash)
93
- results = symbol_literals(content: content, result_type: result_type) + string_symbols(content: content, result_type: result_type)
94
- order_results(results)
95
- end
52
+ def symbol_literals(token_value: nil)
53
+ result = symbols(token_value: token_value)
96
54
 
97
- def symbol_literals(content: nil, result_type: Hash)
98
- results = find_nodes(get_node_class(:symbol_literal), token: content, result_type: result_type)
99
- order_results(results)
55
+ # TODO: Describe why closing_loc has to happen.
56
+ result.select{|node| node.closing_loc.nil?}
100
57
  end
101
58
 
102
- def string_symbols(content: nil, result_type: Hash)
103
- results = find_nodes(get_node_class(:dyna_symbol), token: content, result_type: result_type)
104
- order_results(results)
105
- end
59
+ def string_symbols(token_value: nil)
60
+ result = symbols(token_value: token_value)
106
61
 
107
- def comments(content: nil, result_type: Hash)
108
- results = find_nodes(get_node_class(:comment), token: content, result_type: result_type)
109
- order_results(results)
62
+ # TODO: Describe why closing_loc has to happen.
63
+ result.reject{|node| node.closing_loc.nil?}
110
64
  end
111
65
 
112
- def all_methods(name: nil, result_type: Hash)
113
- results = method_definitions(name: name, result_type: result_type) + method_calls(name: name, result_type: result_type)
114
- order_results(results)
66
+ # Retrieves all parameters within pipes (i.e. - |x, y, z|).
67
+ def block_parameters
68
+ visitor = BlockParametersVisitor.new
69
+ @prism.value.accept(visitor)
70
+ visitor.results
115
71
  end
116
72
 
117
- def block_params(content: nil, result_type: Hash)
118
- # TODO: do_block_params + brace_block_params
119
- results = find_nodes(get_node_class(:params), token: content, result_type: result_type)
120
- order_results(results)
73
+ def parameters(token_value: nil)
74
+ visitor = ParametersVisitor.new(token_value)
75
+ @prism.value.accept(visitor)
76
+ visitor.results
121
77
  end
122
78
 
123
- def find_nodes(token_classes, token: nil, result_type: Hash)
124
- # Ensure the classes are in an array
125
- token_classes = [token_classes].flatten
126
-
127
- nodes = []
128
- token_classes.each do |klass|
129
- if klass == Masamune::AbstractSyntaxTree::Comment
130
- nodes = @comment_list.dup
131
- else
132
- nodes << @node_list.select {|node| node.class == klass}
133
- end
134
- end
135
-
136
- # Searching for multiple classes will yield multi-dimensional arrays,
137
- # so we ensure everything is flattened out before moving forward.
138
- nodes.flatten!
139
-
140
- return nodes if result_type == :nodes
141
-
142
- if token
143
- # TODO: This most likely shouldn't be `node.data_nodes.first`.
144
- # There are probably more data_nodes we need to check depending on the node class.
145
- nodes = nodes.select {|node| node.data_nodes.first.token == token}.flatten
146
- end
147
-
148
- final_result = []
149
- nodes.each do |node|
150
- # Data for symbols are housed within a nested node, so we handle those differently here.
151
- # Read the comments for `get_symbol_data` in the symbol node classes for details.
152
- if node.class == Masamune::AbstractSyntaxTree::SymbolLiteral || node.class == Masamune::AbstractSyntaxTree::DynaSymbol
153
- final_result << node.get_symbol_data.line_data_and_token
154
- else
155
- node.data_nodes.each {|dn| final_result << dn.line_data_and_token} if node.data_nodes
156
- end
157
- end
158
-
159
- # Only order the information if we're returning hashes.
160
- # TODO: We might want to change the placement of order_results_by_position
161
- # if the operation is being done against hashes and not data nodes.
162
- # nodes.first.class.is_a?(Hash) ? DataNode.order_results_by_position(final_result) : final_result
163
- final_result
79
+ # TODO: Search by token_value if necessary.
80
+ def comments
81
+ @prism.comments
164
82
  end
165
83
 
166
- def replace(type:, old_token:, new_token:)
84
+ def replace(type:, old_token_value:, new_token_value:)
167
85
  Slasher.replace(
168
86
  type: type,
169
- old_token: old_token,
170
- new_token: new_token,
87
+ old_token_value: old_token_value,
88
+ new_token_value: new_token_value,
171
89
  code: @code,
172
90
  ast: self
173
91
  )
@@ -175,24 +93,12 @@ module Masamune
175
93
 
176
94
  private
177
95
 
178
- def get_node_class(type)
179
- begin
180
- "Masamune::AbstractSyntaxTree::#{type.to_s.camelize}".constantize
181
- rescue NameError
182
- # For all other nodes that we haven't covered yet, we just make a general class.
183
- # We can worry about adding the classes for other nodes as we go.
184
- Node
185
- end
186
- end
187
-
188
- # We only order results when they are a Hash.
189
- # The contents from the Hash are pulled from data nodes.
190
- # i.e. - {position: [4, 7], token: "project"}
191
- def order_results(results)
192
- if results.first.is_a?(Hash)
193
- DataNode.order_results_by_position(results)
194
- else
195
- results
96
+ # Order results according to their token location.
97
+ def order_nodes(nodes)
98
+ nodes.sort do |a, b|
99
+ by_line = a.token_location.start_line <=> b.token_location.start_line
100
+ # If we're on the same line, refer to the inner index for order.
101
+ by_line.zero? ? a.token_location.start_column <=> b.token_location.start_column : by_line
196
102
  end
197
103
  end
198
104
  end
@@ -1,17 +1,17 @@
1
1
  module Masamune
2
2
  # https://docs.ruby-lang.org/en/3.0/Ripper.html#method-c-lex
3
3
  #
4
- # @position: Line number and starting point on the line. i.e. - [4, 7].
4
+ # @location: Line number and starting point on the line. i.e. - [4, 7].
5
5
  # @type: The type of token. i.e. - :kw (is a keyword).
6
6
  # @token: The raw string which represents the actual ruby code. i.e. - "do".
7
7
  # @state: Ripper::Lexer::State. i.e. - CMDARG.
8
8
  class LexNode
9
- attr_accessor :position, :type, :token, :state, :ast_id
9
+ attr_accessor :location, :type, :token, :state, :ast_id
10
10
  attr_reader :index
11
11
 
12
12
  def initialize(index, raw_lex_node, ast_id)
13
13
  @index = index
14
- @position, @type, @token, @state = raw_lex_node
14
+ @location, @type, @token, @state = raw_lex_node
15
15
  @type = @type.to_s.gsub(/^[a-z]*_/, "").to_sym
16
16
 
17
17
  # Since the Abstract Syntax Tree can get very large,
@@ -25,15 +25,15 @@ module Masamune
25
25
 
26
26
  def variable?
27
27
  return false unless identifier?
28
- ast.variables(name: @token).any?
28
+ ast.variables(token_value: @token).any?
29
29
  end
30
30
 
31
31
  def method_definition?
32
- ast.method_definitions(name: @token).any?
32
+ ast.method_definitions(token_value: @token).any?
33
33
  end
34
34
 
35
35
  def method_call?
36
- ast.method_calls(name: @token).any?
36
+ ast.method_calls(token_value: @token).any?
37
37
  end
38
38
 
39
39
  def method?
@@ -1,34 +1,28 @@
1
1
  module Masamune
2
2
  module Slasher
3
- def self.replace(type:, old_token:, new_token:, code:, ast:)
4
- # `type` can either be a method from the ast like `method_definitions`,
5
- # or it can be a list of Masamune::AbstractSyntaxTree node classes.
6
- line_data_and_token_ary = if type.is_a?(Symbol)
3
+ def self.replace(type:, old_token_value:, new_token_value:, code:, ast:)
4
+ # `type` refers to the singluar form of a method name from the ast like `method_definitions`.
5
+ nodes = if type.is_a?(Symbol)
7
6
  type_to_method = type.to_s.pluralize.to_sym
8
7
  ast.send(type_to_method)
9
- elsif type.is_a?(Array)
10
- type.map {|klass| ast.find_nodes(klass)}.flatten
11
8
  end
12
9
 
13
- tokens_to_replace = line_data_and_token_ary.select do |line_data_and_token|
14
- line_data_and_token[:token] == old_token
10
+ nodes_of_tokens_to_replace = nodes.select do |node|
11
+ node.token_value == old_token_value
15
12
  end
16
13
 
17
14
  # Build from lex nodes
18
15
  result = ast.lex_nodes.map do |lex_node|
19
16
  match_found = false
20
- tokens_to_replace.each do |line_data_and_token|
21
- position = [
22
- line_data_and_token[:line_number],
23
- line_data_and_token[:index_on_line]
24
- ]
25
- if position == lex_node.position
17
+ nodes_of_tokens_to_replace.each do |node|
18
+ location = [node.token_location.start_line, node.token_location.start_column]
19
+ if location == lex_node.location
26
20
  match_found = true
27
21
  break
28
22
  end
29
23
  end
30
24
 
31
- match_found ? new_token : lex_node.token
25
+ match_found ? new_token_value : lex_node.token
32
26
  end
33
27
 
34
28
  result.join
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Masamune
4
- VERSION = "1.2.0"
4
+ VERSION = "2.0.0"
5
5
  end
data/lib/masamune.rb CHANGED
@@ -2,35 +2,22 @@
2
2
 
3
3
  require_relative "masamune/version"
4
4
  require "ripper"
5
+ require "prism"
5
6
  require "active_support/core_ext/string/inflections"
7
+
8
+ require "masamune/abstract_syntax_tree/visitors/block_parameters_visitor"
9
+ require "masamune/abstract_syntax_tree/visitors/method_definitions_visitor"
10
+ require "masamune/abstract_syntax_tree/visitors/method_calls_visitor"
11
+ require "masamune/abstract_syntax_tree/visitors/parameters_visitor"
12
+ require "masamune/abstract_syntax_tree/visitors/strings_visitor"
13
+ require "masamune/abstract_syntax_tree/visitors/symbols_visitor"
14
+ require "masamune/abstract_syntax_tree/visitors/variables_visitor"
15
+
6
16
  require "masamune/lex_node"
7
17
  require "masamune/slasher"
8
18
  require "masamune/abstract_syntax_tree"
9
- require "masamune/abstract_syntax_tree/node"
10
- require "masamune/abstract_syntax_tree/data_node"
11
-
12
- require "masamune/abstract_syntax_tree/nodes/support_nodes/block"
13
- require "masamune/abstract_syntax_tree/nodes/support_nodes/comment"
14
-
15
- require "masamune/abstract_syntax_tree/nodes/blocks/brace_block"
16
- require "masamune/abstract_syntax_tree/nodes/blocks/do_block"
17
- require "masamune/abstract_syntax_tree/nodes/symbols/dyna_symbol"
18
- require "masamune/abstract_syntax_tree/nodes/symbols/symbol_literal"
19
- require "masamune/abstract_syntax_tree/nodes/variables/block_var"
20
- require "masamune/abstract_syntax_tree/nodes/variables/var_field"
21
- require "masamune/abstract_syntax_tree/nodes/variables/var_ref"
22
- require "masamune/abstract_syntax_tree/nodes/assign"
23
- require "masamune/abstract_syntax_tree/nodes/call"
24
- require "masamune/abstract_syntax_tree/nodes/command"
25
- require "masamune/abstract_syntax_tree/nodes/def"
26
- require "masamune/abstract_syntax_tree/nodes/params"
27
- require "masamune/abstract_syntax_tree/nodes/program"
28
- require "masamune/abstract_syntax_tree/nodes/string_content"
29
- require "masamune/abstract_syntax_tree/nodes/symbol"
30
- require "masamune/abstract_syntax_tree/nodes/vcall"
31
19
 
32
20
  require "pp"
33
- require "pry"
34
21
 
35
22
  module Masamune
36
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: masamune-ast
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriel Zayas
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-27 00:00:00.000000000 Z
11
+ date: 2023-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: prism
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.13.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.13.0
27
41
  description: A layer of abstraction on top of Ripper for handling Abstract Syntax
28
42
  Trees in Ruby.
29
43
  email:
@@ -40,26 +54,14 @@ files:
40
54
  - Rakefile
41
55
  - lib/masamune.rb
42
56
  - lib/masamune/abstract_syntax_tree.rb
43
- - lib/masamune/abstract_syntax_tree/data_node.rb
44
- - lib/masamune/abstract_syntax_tree/node.rb
45
- - lib/masamune/abstract_syntax_tree/nodes/assign.rb
46
- - lib/masamune/abstract_syntax_tree/nodes/blocks/brace_block.rb
47
- - lib/masamune/abstract_syntax_tree/nodes/blocks/do_block.rb
48
- - lib/masamune/abstract_syntax_tree/nodes/call.rb
49
- - lib/masamune/abstract_syntax_tree/nodes/command.rb
50
- - lib/masamune/abstract_syntax_tree/nodes/def.rb
51
- - lib/masamune/abstract_syntax_tree/nodes/params.rb
52
- - lib/masamune/abstract_syntax_tree/nodes/program.rb
53
- - lib/masamune/abstract_syntax_tree/nodes/string_content.rb
54
- - lib/masamune/abstract_syntax_tree/nodes/support_nodes/block.rb
55
- - lib/masamune/abstract_syntax_tree/nodes/support_nodes/comment.rb
56
- - lib/masamune/abstract_syntax_tree/nodes/symbol.rb
57
- - lib/masamune/abstract_syntax_tree/nodes/symbols/dyna_symbol.rb
58
- - lib/masamune/abstract_syntax_tree/nodes/symbols/symbol_literal.rb
59
- - lib/masamune/abstract_syntax_tree/nodes/variables/block_var.rb
60
- - lib/masamune/abstract_syntax_tree/nodes/variables/var_field.rb
61
- - lib/masamune/abstract_syntax_tree/nodes/variables/var_ref.rb
62
- - lib/masamune/abstract_syntax_tree/nodes/vcall.rb
57
+ - lib/masamune/abstract_syntax_tree/prism/node_extensions.rb
58
+ - lib/masamune/abstract_syntax_tree/visitors/block_parameters_visitor.rb
59
+ - lib/masamune/abstract_syntax_tree/visitors/method_calls_visitor.rb
60
+ - lib/masamune/abstract_syntax_tree/visitors/method_definitions_visitor.rb
61
+ - lib/masamune/abstract_syntax_tree/visitors/parameters_visitor.rb
62
+ - lib/masamune/abstract_syntax_tree/visitors/strings_visitor.rb
63
+ - lib/masamune/abstract_syntax_tree/visitors/symbols_visitor.rb
64
+ - lib/masamune/abstract_syntax_tree/visitors/variables_visitor.rb
63
65
  - lib/masamune/lex_node.rb
64
66
  - lib/masamune/slasher.rb
65
67
  - lib/masamune/version.rb
@@ -79,14 +81,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
81
  requirements:
80
82
  - - ">="
81
83
  - !ruby/object:Gem::Version
82
- version: 2.6.0
84
+ version: 2.7.0
83
85
  required_rubygems_version: !ruby/object:Gem::Requirement
84
86
  requirements:
85
87
  - - ">="
86
88
  - !ruby/object:Gem::Version
87
89
  version: '0'
88
90
  requirements: []
89
- rubygems_version: 3.3.7
91
+ rubygems_version: 3.5.0.dev
90
92
  signing_key:
91
93
  specification_version: 4
92
94
  summary: Masamune
@@ -1,65 +0,0 @@
1
- # A data node represents an abstraction in the AST which has details about a specific type.
2
- # i.e. - [:@ident, "variable_name", [4, 7]]
3
- # These values are the `type`, `token`, and `position`, respectively.
4
- # It is simliar to what you see in `Ripper.lex(code)` and `Masamune::AbstractSyntaxTree's @lex_nodes`.
5
-
6
- # We break this down into a simpler structure, `line_data_and_token`,
7
- # which looks like this: {line_number: 4, index_on_line: 7, token: "ruby"}
8
-
9
- module Masamune
10
- class AbstractSyntaxTree
11
- class DataNode < Node
12
- attr_reader :type, :token, :line_number, :index_on_line
13
-
14
- def initialize(contents, ast_id, parent)
15
- @type, @token, line_position = contents
16
- @line_number, @index_on_line = line_position
17
- @parent = parent
18
- super(contents, ast_id)
19
- end
20
-
21
- # Results here represent the position and token of the
22
- # data we're searching in the form of a Hash like the following:
23
- # [
24
- # {line_number: 4, index_on_line: 7, token: "ruby"},
25
- # {line_number: 7, index_on_line: 7, token: "rails"}
26
- # ]
27
- # TODO: Worry about using a faster sorting algorithm later.
28
- def self.order_results_by_position(results)
29
- final_result = []
30
-
31
- line_numbers = results.map {|result| result[:line_number]}.uniq.sort
32
- line_numbers.each do |line_number|
33
- # Group data together in an array if they're on the same line.
34
- shared_line_data = results.select {|result| result[:line_number] == line_number}
35
-
36
- # Sort the positions on each line number respectively.
37
- indexes_on_line = shared_line_data.map {|data| data[:index_on_line]}.sort
38
-
39
- # Apply to the final result.
40
- indexes_on_line.each do |index_on_line|
41
- shared_line_data.each do |data|
42
- if data[:index_on_line] == index_on_line
43
- final_result << data
44
- end
45
- end
46
- end
47
- end
48
-
49
- final_result
50
- end
51
-
52
- def line_data_and_token
53
- {
54
- line_number: @line_number,
55
- index_on_line: @index_on_line,
56
- token: @token
57
- }
58
- end
59
-
60
- def position
61
- [@line_number, @index_on_line]
62
- end
63
- end
64
- end
65
- end
@@ -1,41 +0,0 @@
1
- # TODO: Add description
2
-
3
- module Masamune
4
- class AbstractSyntaxTree
5
- class Node
6
- attr_reader :ast_id, :contents, :index_stack, :data_nodes
7
-
8
- def initialize(contents, ast_id)
9
- @ast_id = ast_id
10
- @contents = contents
11
- @data_nodes = extract_data_nodes
12
- end
13
-
14
- def ast
15
- ObjectSpace._id2ref(@ast_id)
16
- end
17
-
18
- # TODO: Consider removing the :type and :typeless methods.
19
-
20
- # Ripper's abstract syntax tree nodes are either typed or typeless.
21
- # Types consist of values such as :def, :do_block, :var_ref, etc.
22
- # Typed nodes house one of these types as its first element,
23
- # whereas typeless nodes simply have arrays as top-level elements.
24
- # Example of a typed node: [:@tstring_content, "ruby", [4, 7]]
25
- def typed?
26
- @contents.is_a?(Array) && @contents.first.is_a?(Symbol)
27
- end
28
-
29
- def typeless?
30
- !typed?
31
- end
32
-
33
- # By default, we assume a node has no data nodes to extract.
34
- # Because the structure for each node is different, we handle
35
- # extraction separately for each node within its respective class.
36
- def extract_data_nodes
37
- # TODO: Might want to make this [] instead of nil.
38
- end
39
- end
40
- end
41
- end
@@ -1,11 +0,0 @@
1
- # TODO: Add description.
2
-
3
- module Masamune
4
- class AbstractSyntaxTree
5
- class Assign < Node
6
- def initialize(contents, ast_id)
7
- super
8
- end
9
- end
10
- end
11
- end
@@ -1,13 +0,0 @@
1
- # TODO: Add description.
2
-
3
- module Masamune
4
- class AbstractSyntaxTree
5
- class BraceBlock < Block
6
- attr_accessor :ast_id
7
-
8
- def initialize(contents, ast_id)
9
- super
10
- end
11
- end
12
- end
13
- end
@@ -1,13 +0,0 @@
1
- # TODO: Add description.
2
-
3
- module Masamune
4
- class AbstractSyntaxTree
5
- class DoBlock < Block
6
- attr_accessor :ast_id
7
-
8
- def initialize(contents, ast_id)
9
- super
10
- end
11
- end
12
- end
13
- end
@@ -1,17 +0,0 @@
1
- # TODO: Add description.
2
-
3
- module Masamune
4
- class AbstractSyntaxTree
5
- class Call < Node
6
- def initialize(contents, ast_id)
7
- super
8
- end
9
-
10
- def extract_data_nodes
11
- [
12
- DataNode.new(@contents.last, @ast_id, self)
13
- ]
14
- end
15
- end
16
- end
17
- end