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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +5 -1
- data/README.md +30 -82
- data/lib/masamune/abstract_syntax_tree/prism/node_extensions.rb +82 -0
- data/lib/masamune/abstract_syntax_tree/visitors/block_parameters_visitor.rb +18 -0
- data/lib/masamune/abstract_syntax_tree/visitors/method_calls_visitor.rb +19 -0
- data/lib/masamune/abstract_syntax_tree/visitors/method_definitions_visitor.rb +17 -0
- data/lib/masamune/abstract_syntax_tree/visitors/parameters_visitor.rb +18 -0
- data/lib/masamune/abstract_syntax_tree/visitors/strings_visitor.rb +17 -0
- data/lib/masamune/abstract_syntax_tree/visitors/symbols_visitor.rb +17 -0
- data/lib/masamune/abstract_syntax_tree/visitors/variables_visitor.rb +34 -0
- data/lib/masamune/abstract_syntax_tree.rb +57 -151
- data/lib/masamune/lex_node.rb +6 -6
- data/lib/masamune/slasher.rb +9 -15
- data/lib/masamune/version.rb +1 -1
- data/lib/masamune.rb +10 -23
- metadata +26 -24
- data/lib/masamune/abstract_syntax_tree/data_node.rb +0 -65
- data/lib/masamune/abstract_syntax_tree/node.rb +0 -41
- data/lib/masamune/abstract_syntax_tree/nodes/assign.rb +0 -11
- data/lib/masamune/abstract_syntax_tree/nodes/blocks/brace_block.rb +0 -13
- data/lib/masamune/abstract_syntax_tree/nodes/blocks/do_block.rb +0 -13
- data/lib/masamune/abstract_syntax_tree/nodes/call.rb +0 -17
- data/lib/masamune/abstract_syntax_tree/nodes/command.rb +0 -64
- data/lib/masamune/abstract_syntax_tree/nodes/def.rb +0 -17
- data/lib/masamune/abstract_syntax_tree/nodes/params.rb +0 -23
- data/lib/masamune/abstract_syntax_tree/nodes/program.rb +0 -16
- data/lib/masamune/abstract_syntax_tree/nodes/string_content.rb +0 -17
- data/lib/masamune/abstract_syntax_tree/nodes/support_nodes/block.rb +0 -18
- data/lib/masamune/abstract_syntax_tree/nodes/support_nodes/comment.rb +0 -25
- data/lib/masamune/abstract_syntax_tree/nodes/symbol.rb +0 -17
- data/lib/masamune/abstract_syntax_tree/nodes/symbols/dyna_symbol.rb +0 -20
- data/lib/masamune/abstract_syntax_tree/nodes/symbols/symbol_literal.rb +0 -21
- data/lib/masamune/abstract_syntax_tree/nodes/variables/block_var.rb +0 -22
- data/lib/masamune/abstract_syntax_tree/nodes/variables/var_field.rb +0 -17
- data/lib/masamune/abstract_syntax_tree/nodes/variables/var_ref.rb +0 -19
- 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, :
|
4
|
-
attr_accessor :
|
5
|
+
attr_reader :code, :prism, :ripper
|
6
|
+
attr_accessor :lex_nodes
|
5
7
|
|
6
8
|
def initialize(code)
|
7
9
|
@code = code
|
8
|
-
@
|
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
|
45
|
-
|
46
|
-
@
|
47
|
-
|
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
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
65
|
-
|
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(
|
70
|
-
|
71
|
-
|
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(
|
75
|
-
|
76
|
-
|
77
|
-
|
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
|
-
|
85
|
-
|
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
|
-
|
89
|
-
|
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
|
-
|
98
|
-
|
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(
|
103
|
-
|
104
|
-
order_results(results)
|
105
|
-
end
|
59
|
+
def string_symbols(token_value: nil)
|
60
|
+
result = symbols(token_value: token_value)
|
106
61
|
|
107
|
-
|
108
|
-
|
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
|
-
|
113
|
-
|
114
|
-
|
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
|
118
|
-
|
119
|
-
|
120
|
-
|
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
|
-
|
124
|
-
|
125
|
-
|
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:,
|
84
|
+
def replace(type:, old_token_value:, new_token_value:)
|
167
85
|
Slasher.replace(
|
168
86
|
type: type,
|
169
|
-
|
170
|
-
|
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
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
#
|
183
|
-
|
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
|
data/lib/masamune/lex_node.rb
CHANGED
@@ -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
|
-
# @
|
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 :
|
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
|
-
@
|
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(
|
28
|
+
ast.variables(token_value: @token).any?
|
29
29
|
end
|
30
30
|
|
31
31
|
def method_definition?
|
32
|
-
ast.method_definitions(
|
32
|
+
ast.method_definitions(token_value: @token).any?
|
33
33
|
end
|
34
34
|
|
35
35
|
def method_call?
|
36
|
-
ast.method_calls(
|
36
|
+
ast.method_calls(token_value: @token).any?
|
37
37
|
end
|
38
38
|
|
39
39
|
def method?
|
data/lib/masamune/slasher.rb
CHANGED
@@ -1,34 +1,28 @@
|
|
1
1
|
module Masamune
|
2
2
|
module Slasher
|
3
|
-
def self.replace(type:,
|
4
|
-
# `type`
|
5
|
-
|
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
|
-
|
14
|
-
|
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
|
-
|
21
|
-
|
22
|
-
|
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 ?
|
25
|
+
match_found ? new_token_value : lex_node.token
|
32
26
|
end
|
33
27
|
|
34
28
|
result.join
|
data/lib/masamune/version.rb
CHANGED
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:
|
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-
|
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/
|
44
|
-
- lib/masamune/abstract_syntax_tree/
|
45
|
-
- lib/masamune/abstract_syntax_tree/
|
46
|
-
- lib/masamune/abstract_syntax_tree/
|
47
|
-
- lib/masamune/abstract_syntax_tree/
|
48
|
-
- lib/masamune/abstract_syntax_tree/
|
49
|
-
- lib/masamune/abstract_syntax_tree/
|
50
|
-
- lib/masamune/abstract_syntax_tree/
|
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.
|
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.
|
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,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
|