masamune-ast 1.2.1 → 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 +4 -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 -134
- 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 -22
- metadata +29 -27
- data/lib/masamune/abstract_syntax_tree/data_node.rb +0 -49
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: caf2d78e9516f9431e751db61028a2dd90354b2dce71eecc116a848b7b171344
|
4
|
+
data.tar.gz: c556d620be50a699a6757981ce692929298baf92cd9ebbaa86256f7277e28d9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62015efa9a2e971af08db707acccf0df1761fc4a6b89fa14ca3ee830732d02ad3c06434c14c9b153006a938217f01e80370ec1dda11fa108f954ec8b47575b5a
|
7
|
+
data.tar.gz: 125c5527076511907993aee66d47e66caee9c416c33d44f63585e31676c214cbe959f5bf35165a748199fca2c87d3fda181f0f55a51331edd45c382998796178
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [2.0.0] - 2023-10-13
|
4
|
+
|
5
|
+
- Migrate to Prism by @gazayas in #60
|
6
|
+
- Return array of Prism nodes for `Masamune::AbstractSyntaxTree` search methods.
|
7
|
+
- Refactor NodeHelper into inline extensions by @kaspth in #61
|
8
|
+
- Remove functionality to replace source code by Node name (the `type` keyword now only accepts Symbols such as `:variable` and `:method_call`).
|
9
|
+
|
3
10
|
## [1.0.0] - 2023-05-01
|
4
11
|
|
5
12
|
- Change `MasamuneAst` module to `Masamune`.
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
masamune-ast (
|
4
|
+
masamune-ast (2.0.0)
|
5
5
|
activesupport
|
6
|
+
prism (>= 0.13.0)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
@@ -18,6 +19,7 @@ GEM
|
|
18
19
|
concurrent-ruby (~> 1.0)
|
19
20
|
method_source (1.0.0)
|
20
21
|
minitest (5.18.0)
|
22
|
+
prism (0.13.0)
|
21
23
|
pry (0.14.2)
|
22
24
|
coderay (~> 1.1)
|
23
25
|
method_source (~> 1.0)
|
@@ -26,6 +28,7 @@ GEM
|
|
26
28
|
concurrent-ruby (~> 1.0)
|
27
29
|
|
28
30
|
PLATFORMS
|
31
|
+
arm64-darwin-22
|
29
32
|
x86_64-darwin-21
|
30
33
|
x86_64-linux
|
31
34
|
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Masamune
|
2
2
|
|
3
|
-
## A
|
3
|
+
## A covenience wrapper around Prism, a Ruby source code parser
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -23,25 +23,21 @@ require "masamune"
|
|
23
23
|
Isolate and replace variables, methods, or strings in your Ruby source code according to the specific tokens allotted when the code is intially parsed:
|
24
24
|
```ruby
|
25
25
|
code = <<~CODE
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def n
|
31
|
-
"n"
|
26
|
+
:hello
|
27
|
+
hello = "hello"
|
28
|
+
def hello
|
29
|
+
puts hello
|
32
30
|
end
|
33
31
|
CODE
|
34
32
|
|
35
33
|
msmn = Masamune::AbstractSyntaxTree.new(code)
|
36
|
-
msmn.replace(type: :variable,
|
34
|
+
msmn.replace(type: :variable, old_token_value: "hello", new_token_value: "greeting")
|
37
35
|
|
38
36
|
# This will produce the following code in string form.
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def n
|
44
|
-
"n"
|
37
|
+
:hello
|
38
|
+
greeting = "hello"
|
39
|
+
def hello
|
40
|
+
puts greeting
|
45
41
|
end
|
46
42
|
```
|
47
43
|
|
@@ -56,22 +52,20 @@ CODE
|
|
56
52
|
|
57
53
|
msmn = Masamune::AbstractSyntaxTree.new(code)
|
58
54
|
|
55
|
+
# Returns an array of Prism nodes
|
59
56
|
msmn.variables
|
60
|
-
#=> [{:line_number=>1, :index_on_line=>0, :token=>"java"},
|
61
|
-
#=> {:line_number=>2, :index_on_line=>0, :token=>"javascript"},
|
62
|
-
#=> {:line_number=>2, :index_on_line=>13, :token=>"java"},
|
63
|
-
#=> {:line_number=>3, :index_on_line=>5, :token=>"java"},
|
64
|
-
#=> {:line_number=>3, :index_on_line=>25, :token=>"javascript"}]
|
65
57
|
|
58
|
+
msmn.variables.first.token_value
|
59
|
+
#=> "java"
|
60
|
+
msmn.variables.first.token_location
|
61
|
+
#=> (1,0)-(1,4)
|
62
|
+
|
63
|
+
# Returns an array of Prism nodes
|
66
64
|
msmn.strings
|
67
|
-
#=> [{:line_number=>1, :index_on_line=>8, :token=>"java"},
|
68
|
-
#=> {:line_number=>2, :index_on_line=>21, :token=>"script"},
|
69
|
-
#=> {:line_number=>3, :index_on_line=>13, :token=>" is not "}]
|
70
65
|
|
71
|
-
msmn.variables(
|
72
|
-
|
73
|
-
#=>
|
74
|
-
#=> {:line_number=>3, :index_on_line=>5, :token=>"java"}]
|
66
|
+
last_java_node = msmn.variables(token_value: "java").last
|
67
|
+
last_java_node.token_location
|
68
|
+
#=> (3,5)-(3,9)
|
75
69
|
|
76
70
|
code = <<CODE
|
77
71
|
ary = [1, 2, 3]
|
@@ -87,68 +81,22 @@ CODE
|
|
87
81
|
|
88
82
|
msmn = Masamune::AbstractSyntaxTree.new(code)
|
89
83
|
|
90
|
-
msmn.
|
91
|
-
#=>
|
92
|
-
#=> {:line_number=>2, :index_on_line=>8, :token=>"times"},
|
93
|
-
#=> {:line_number=>3, :index_on_line=>2, :token=>"puts"},
|
94
|
-
#=> {:line_number=>6, :index_on_line=>4, :token=>"foo"},
|
95
|
-
#=> {:line_number=>8, :index_on_line=>0, :token=>"foo"},
|
96
|
-
#=> {:line_number=>9, :index_on_line=>0, :token=>"foo"}]
|
97
|
-
|
98
|
-
msmn.method_calls
|
99
|
-
#=> [{:line_number=>2, :index_on_line=>4, :token=>"sum"},
|
100
|
-
#=> {:line_number=>2, :index_on_line=>8, :token=>"times"},
|
101
|
-
#=> {:line_number=>3, :index_on_line=>2, :token=>"puts"},
|
102
|
-
#=> {:line_number=>8, :index_on_line=>0, :token=>"foo"},
|
103
|
-
#=> {:line_number=>9, :index_on_line=>0, :token=>"foo"}]
|
104
|
-
|
105
|
-
msmn.method_definitions
|
106
|
-
#=> [{:line_number=>6, :index_on_line=>4, :token=>"foo"}]
|
107
|
-
```
|
84
|
+
msmn.method_definitions.size
|
85
|
+
#=> 1
|
108
86
|
|
109
|
-
|
110
|
-
|
111
|
-
code = <<~CODE
|
112
|
-
"ruby"
|
113
|
-
"rails"
|
114
|
-
CODE
|
87
|
+
msmn.method_calls.size
|
88
|
+
#=> 5
|
115
89
|
|
116
|
-
msmn
|
117
|
-
|
118
|
-
#=> [#<Masamune::AbstractSyntaxTree::StringContent:0x00007ff2d987c020
|
119
|
-
#=> @ast_id=406820,
|
120
|
-
#=> @contents=[:string_content, [:@tstring_content, "ruby", [1, 1]]],
|
121
|
-
#=> @data_nodes=
|
122
|
-
#=> [#<Masamune::AbstractSyntaxTree::DataNode:0x00007ff2d9883fc8
|
123
|
-
#=> @ast_id=406820,
|
124
|
-
#=> @contents=[:@tstring_content, "ruby", [1, 1]],
|
125
|
-
#=> @data_nodes=nil,
|
126
|
-
#=> @index_on_line=1,
|
127
|
-
#=> @line_number=1,
|
128
|
-
#=> @parent=#<Masamune::AbstractSyntaxTree::StringContent:0x00007ff2d987c020 ...>,
|
129
|
-
#=> @token="ruby",
|
130
|
-
#=> @type=:@tstring_content>]>,
|
131
|
-
#=> #<Masamune::AbstractSyntaxTree::StringContent:0x00007ff2d9883190
|
132
|
-
#=> @ast_id=406820,
|
133
|
-
#=> @contents=[:string_content, [:@tstring_content, "rails", [2, 1]]],
|
134
|
-
#=> @data_nodes=
|
135
|
-
#=> [#<Masamune::AbstractSyntaxTree::DataNode:0x00007ff2d9883168
|
136
|
-
#=> @ast_id=406820,
|
137
|
-
#=> @contents=[:@tstring_content, "rails", [2, 1]],
|
138
|
-
#=> @data_nodes=nil,
|
139
|
-
#=> @index_on_line=1,
|
140
|
-
#=> @line_number=2,
|
141
|
-
#=> @parent=#<Masamune::AbstractSyntaxTree::StringContent:0x00007ff2d9883190 ...>,
|
142
|
-
#=> @token="rails",
|
143
|
-
#=> @type=:@tstring_content>]>]
|
90
|
+
msmn.all_methods.size
|
91
|
+
#=> 6
|
144
92
|
```
|
145
93
|
|
146
|
-
In some cases, it can be easier to look at the given lex nodes to analyze your source code
|
94
|
+
In some cases, it can be easier to look at the given lex nodes to analyze your source code:
|
147
95
|
```ruby
|
148
96
|
msmn.lex_nodes
|
149
|
-
=> [#<Masamune::LexNode:0x00007fd61810cac0 @ast_id=1200, @index=0, @
|
150
|
-
#<Masamune::LexNode:0x00007fd61810c930 @ast_id=1200, @index=1, @
|
151
|
-
#<Masamune::LexNode:0x00007fd61810c7c8 @ast_id=1200, @index=2, @
|
97
|
+
=> [#<Masamune::LexNode:0x00007fd61810cac0 @ast_id=1200, @index=0, @location=[1, 0], @state=CMDARG, @token="java", @type=:ident>,
|
98
|
+
#<Masamune::LexNode:0x00007fd61810c930 @ast_id=1200, @index=1, @location=[1, 4], @state=CMDARG, @token=" ", @type=:sp>,
|
99
|
+
#<Masamune::LexNode:0x00007fd61810c7c8 @ast_id=1200, @index=2, @location=[1, 5], @state=BEG, @token="=", @type=:op>,
|
152
100
|
…
|
153
101
|
]
|
154
102
|
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Prism
|
2
|
+
class Node
|
3
|
+
def comment? = false
|
4
|
+
|
5
|
+
def self.node_predicate(name, body = -> { true })
|
6
|
+
define_method(name, &body)
|
7
|
+
Node.define_method(name) { false } unless Node.respond_to?(name, false)
|
8
|
+
end
|
9
|
+
|
10
|
+
def line_number
|
11
|
+
token_location.start_line
|
12
|
+
end
|
13
|
+
|
14
|
+
# #location provides helpful information for the source code of a node as a whole, but in
|
15
|
+
# Masamune we generally want the token value itself, so we primarily get the token value's location.
|
16
|
+
def token_location
|
17
|
+
location
|
18
|
+
end
|
19
|
+
|
20
|
+
# The source code of Prism nodes can be retrieved by calling #slice.
|
21
|
+
# However, the output tends to vary from node to node, and other methods
|
22
|
+
# like `name`, `message`, etc. are available in Prism nodes which means you
|
23
|
+
# have to know exactly which method to call the get the results you want.
|
24
|
+
#
|
25
|
+
# The `token` method simplifies all of this, and just gives you the
|
26
|
+
# variable, method name, etc. in String form by just calling `token_value`.
|
27
|
+
def token_value
|
28
|
+
content
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class DefNode
|
33
|
+
node_predicate :method?
|
34
|
+
node_predicate :method_definition?
|
35
|
+
def token_location = name_loc
|
36
|
+
def token_value = name.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
class CallNode
|
40
|
+
def method? = true
|
41
|
+
node_predicate :method_call?
|
42
|
+
def token_location = message_loc
|
43
|
+
def token_value = message
|
44
|
+
end
|
45
|
+
|
46
|
+
class LocalVariableWriteNode
|
47
|
+
node_predicate :variable?
|
48
|
+
def token_location = name_loc
|
49
|
+
def token_value = name.to_s
|
50
|
+
end
|
51
|
+
|
52
|
+
class LocalVariableReadNode
|
53
|
+
def variable? = true
|
54
|
+
def token_value = name.to_s
|
55
|
+
end
|
56
|
+
|
57
|
+
class RequiredParameterNode
|
58
|
+
def variable? = true
|
59
|
+
def token_value = slice
|
60
|
+
end
|
61
|
+
|
62
|
+
class StringNode
|
63
|
+
node_predicate :string?
|
64
|
+
def token_location = content_loc
|
65
|
+
def token_value = content
|
66
|
+
end
|
67
|
+
|
68
|
+
class SymbolNode
|
69
|
+
node_predicate :symbol?
|
70
|
+
node_predicate :symbol_literal?, -> { closing_loc.nil? }
|
71
|
+
node_predicate :symbol_string?, -> { closing_loc.present? }
|
72
|
+
|
73
|
+
def token_location = value_loc
|
74
|
+
def token_value = value
|
75
|
+
end
|
76
|
+
|
77
|
+
class Comment
|
78
|
+
def comment? = true
|
79
|
+
def token_location = location
|
80
|
+
def token_value = location.slice
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Masamune
|
2
|
+
class AbstractSyntaxTree
|
3
|
+
class BlockParametersVisitors < Prism::Visitor
|
4
|
+
attr_reader :results
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@results = []
|
8
|
+
end
|
9
|
+
|
10
|
+
# Since block parameters nodes can house multiple variables in one node,
|
11
|
+
# we don't have to check for a token_value.
|
12
|
+
def visit_block_parameters_node(node)
|
13
|
+
results << node
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Masamune
|
2
|
+
class AbstractSyntaxTree
|
3
|
+
class MethodCallsVisitor < Prism::Visitor
|
4
|
+
attr_reader :token_value, :results
|
5
|
+
|
6
|
+
def initialize(token_value)
|
7
|
+
@token_value = token_value
|
8
|
+
@results = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def visit_call_node(node)
|
12
|
+
if node.method_call?
|
13
|
+
results << node if token_value.nil? || token_value == node.name
|
14
|
+
end
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Masamune
|
2
|
+
class AbstractSyntaxTree
|
3
|
+
class MethodDefinitionsVisitor < Prism::Visitor
|
4
|
+
attr_reader :token_value, :results
|
5
|
+
|
6
|
+
def initialize(token_value)
|
7
|
+
@token_value = token_value
|
8
|
+
@results = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def visit_def_node(node)
|
12
|
+
results << node if token_value.nil? || token_value == node.name.to_s
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Masamune
|
2
|
+
class AbstractSyntaxTree
|
3
|
+
class ParametersVisitor < Prism::Visitor
|
4
|
+
attr_reader :results
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@results = []
|
8
|
+
end
|
9
|
+
|
10
|
+
# Since parameters nodes can house multiple variables in one node,
|
11
|
+
# we don't have to check for a token_value.
|
12
|
+
def visit_parameters_node(node)
|
13
|
+
results << node
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Masamune
|
2
|
+
class AbstractSyntaxTree
|
3
|
+
class StringsVisitor < Prism::Visitor
|
4
|
+
attr_reader :token_value, :results
|
5
|
+
|
6
|
+
def initialize(token_value)
|
7
|
+
@token_value = token_value
|
8
|
+
@results = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def visit_string_node(node)
|
12
|
+
results << node if token_value.nil? || token_value == node.content
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Masamune
|
2
|
+
class AbstractSyntaxTree
|
3
|
+
class SymbolsVisitor < Prism::Visitor
|
4
|
+
attr_reader :token_value, :results
|
5
|
+
|
6
|
+
def initialize(token_value)
|
7
|
+
@token_value = token_value
|
8
|
+
@results = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def visit_symbol_node(node)
|
12
|
+
results << node if token_value.nil? || token_value == node.value
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Masamune
|
2
|
+
class AbstractSyntaxTree
|
3
|
+
class VariablesVisitor < Prism::Visitor
|
4
|
+
attr_reader :token_value, :results
|
5
|
+
|
6
|
+
def initialize(token_value)
|
7
|
+
@token_value = token_value
|
8
|
+
@results = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def visit_local_variable_write_node(node)
|
12
|
+
results << node if token_value.nil? || token_value == node.name.to_s
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def visit_local_variable_read_node(node)
|
17
|
+
results << node if token_value.nil? || token_value == node.name.to_s
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def visit_required_parameter_node(node)
|
22
|
+
results << node if token_value.nil? || token_value == node.name.to_s
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def visit_call_node(node)
|
27
|
+
if node.variable_call?
|
28
|
+
results << node if token_value.nil? || token_value == node.name
|
29
|
+
end
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,162 +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
16
|
end
|
23
17
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
18
|
+
def variables(token_value: nil)
|
19
|
+
visitor = VariablesVisitor.new(token_value)
|
20
|
+
@prism.value.accept(visitor)
|
21
|
+
visitor.results
|
42
22
|
end
|
43
23
|
|
44
|
-
def
|
45
|
-
|
46
|
-
@
|
47
|
-
|
24
|
+
def strings(token_value: nil)
|
25
|
+
visitor = StringsVisitor.new(token_value)
|
26
|
+
@prism.value.accept(visitor)
|
27
|
+
visitor.results
|
48
28
|
end
|
49
29
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
# TODO: Add block_params: true to the arguments.
|
54
|
-
def variables(name: nil, result_type: Hash)
|
55
|
-
results = find_nodes([VarField, VarRef, Params], token: name, result_type: result_type)
|
56
|
-
order_results(results)
|
57
|
-
end
|
58
|
-
|
59
|
-
def strings(content: nil, result_type: Hash)
|
60
|
-
results = find_nodes(StringContent, token: content, result_type: result_type)
|
61
|
-
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))
|
62
32
|
end
|
63
33
|
|
64
|
-
def method_definitions(
|
65
|
-
|
66
|
-
|
34
|
+
def method_definitions(token_value: nil)
|
35
|
+
visitor = MethodDefinitionsVisitor.new(token_value)
|
36
|
+
@prism.value.accept(visitor)
|
37
|
+
visitor.results
|
67
38
|
end
|
68
39
|
|
69
|
-
def method_calls(
|
70
|
-
|
71
|
-
|
40
|
+
def method_calls(token_value: nil)
|
41
|
+
visitor = MethodCallsVisitor.new(token_value)
|
42
|
+
@prism.value.accept(visitor)
|
43
|
+
visitor.results
|
72
44
|
end
|
73
45
|
|
74
|
-
|
75
|
-
|
46
|
+
def symbols(token_value: nil)
|
47
|
+
visitor = SymbolsVisitor.new(token_value)
|
48
|
+
@prism.value.accept(visitor)
|
49
|
+
visitor.results
|
76
50
|
end
|
77
51
|
|
78
|
-
|
79
|
-
|
80
|
-
end
|
52
|
+
def symbol_literals(token_value: nil)
|
53
|
+
result = symbols(token_value: token_value)
|
81
54
|
|
82
|
-
|
83
|
-
|
84
|
-
order_results(results)
|
55
|
+
# TODO: Describe why closing_loc has to happen.
|
56
|
+
result.select{|node| node.closing_loc.nil?}
|
85
57
|
end
|
86
58
|
|
87
|
-
def
|
88
|
-
|
89
|
-
order_results(results)
|
90
|
-
end
|
59
|
+
def string_symbols(token_value: nil)
|
60
|
+
result = symbols(token_value: token_value)
|
91
61
|
|
92
|
-
|
93
|
-
|
94
|
-
order_results(results)
|
62
|
+
# TODO: Describe why closing_loc has to happen.
|
63
|
+
result.reject{|node| node.closing_loc.nil?}
|
95
64
|
end
|
96
65
|
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
100
71
|
end
|
101
72
|
|
102
|
-
def
|
103
|
-
|
104
|
-
|
73
|
+
def parameters(token_value: nil)
|
74
|
+
visitor = ParametersVisitor.new(token_value)
|
75
|
+
@prism.value.accept(visitor)
|
76
|
+
visitor.results
|
105
77
|
end
|
106
78
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
order_results(results)
|
79
|
+
# TODO: Search by token_value if necessary.
|
80
|
+
def comments
|
81
|
+
@prism.comments
|
111
82
|
end
|
112
83
|
|
113
|
-
def
|
114
|
-
token_classes = Array(token_classes)
|
115
|
-
|
116
|
-
nodes = []
|
117
|
-
token_classes.each do |klass|
|
118
|
-
if klass == Comment
|
119
|
-
nodes = @comment_list.dup
|
120
|
-
else
|
121
|
-
nodes << @node_list.select {|node| node.class == klass}
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
# Searching for multiple classes will yield multi-dimensional arrays,
|
126
|
-
# so we ensure everything is flattened out before moving forward.
|
127
|
-
nodes.flatten!
|
128
|
-
|
129
|
-
return nodes if result_type == :nodes
|
130
|
-
|
131
|
-
if token
|
132
|
-
# TODO: This most likely shouldn't be `node.data_nodes.first`.
|
133
|
-
# There are probably more data_nodes we need to check depending on the node class.
|
134
|
-
nodes = nodes.select {|node| node.data_nodes.first.token == token}.flatten
|
135
|
-
end
|
136
|
-
|
137
|
-
final_result = []
|
138
|
-
nodes.each do |node|
|
139
|
-
# Data for symbols are housed within a nested node, so we handle those differently here.
|
140
|
-
# Read the comments for `get_symbol_data` in the symbol node classes for details.
|
141
|
-
if node.class == SymbolLiteral || node.class == DynaSymbol
|
142
|
-
final_result << node.get_symbol_data.line_data_and_token
|
143
|
-
else
|
144
|
-
node.data_nodes.each {|dn| final_result << dn.line_data_and_token} if node.data_nodes
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
# Only order the information if we're returning hashes.
|
149
|
-
# TODO: We might want to change the placement of order_results_by_position
|
150
|
-
# if the operation is being done against hashes and not data nodes.
|
151
|
-
# nodes.first.class.is_a?(Hash) ? DataNode.order_results_by_position(final_result) : final_result
|
152
|
-
final_result
|
153
|
-
end
|
154
|
-
|
155
|
-
def replace(type:, old_token:, new_token:)
|
84
|
+
def replace(type:, old_token_value:, new_token_value:)
|
156
85
|
Slasher.replace(
|
157
86
|
type: type,
|
158
|
-
|
159
|
-
|
87
|
+
old_token_value: old_token_value,
|
88
|
+
new_token_value: new_token_value,
|
160
89
|
code: @code,
|
161
90
|
ast: self
|
162
91
|
)
|
@@ -164,18 +93,12 @@ module Masamune
|
|
164
93
|
|
165
94
|
private
|
166
95
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
# i.e. - {position: [4, 7], token: "project"}
|
174
|
-
def order_results(results)
|
175
|
-
if results.first.is_a?(Hash)
|
176
|
-
DataNode.order_results_by_position(results)
|
177
|
-
else
|
178
|
-
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
|
179
102
|
end
|
180
103
|
end
|
181
104
|
end
|