masamune-ast 1.1.0 → 1.1.1
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/Gemfile.lock +1 -1
- data/README.md +30 -0
- data/lib/masamune/abstract_syntax_tree/block_var.rb +1 -1
- data/lib/masamune/abstract_syntax_tree/brace_block.rb +1 -1
- data/lib/masamune/abstract_syntax_tree/call.rb +1 -1
- data/lib/masamune/abstract_syntax_tree/def.rb +1 -1
- data/lib/masamune/abstract_syntax_tree/do_block.rb +1 -1
- data/lib/masamune/abstract_syntax_tree/params.rb +1 -1
- data/lib/masamune/abstract_syntax_tree/string_content.rb +1 -1
- data/lib/masamune/abstract_syntax_tree/var_field.rb +1 -1
- data/lib/masamune/abstract_syntax_tree/var_ref.rb +1 -1
- data/lib/masamune/abstract_syntax_tree/vcall.rb +1 -1
- data/lib/masamune/abstract_syntax_tree.rb +25 -13
- data/lib/masamune/slasher.rb +32 -0
- data/lib/masamune/version.rb +1 -1
- data/lib/masamune.rb +1 -0
- metadata +3 -3
- data/lib/masamune/slicer.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a00f60e535cf2096a37cd6efd639aa7c132c70e58c3b422a23538128368b5c85
|
4
|
+
data.tar.gz: 5d548fc4b9d5cf25c1099a2b446542f57342694d7b414052df004dcd2cf311c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c80bcefac510bfd4103d56fd13f39a46d1e4531eceb678d620709b97fe0c941f20f1e7ffddc6058e77aab46ab093d1d4ba768b6860649c5a57197e36f89bf109
|
7
|
+
data.tar.gz: 731a46f94d655a820acdd949d7d7fa03f3fc37277858b5b5daea3c0c13444720b3b1ca829d0f304d5aecb3f390e3055168503ce6655653268cb89fcf19ab28e3
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -13,8 +13,38 @@ Or add the following to your Gemfile and run `bundle install`
|
|
13
13
|
gem "masamune-ast"
|
14
14
|
```
|
15
15
|
|
16
|
+
Then require the gem in a file like this:
|
17
|
+
```ruby
|
18
|
+
require "masamune"
|
19
|
+
```
|
20
|
+
|
16
21
|
## Usage
|
17
22
|
|
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
|
+
```ruby
|
25
|
+
code = <<~CODE
|
26
|
+
10.times do |n|
|
27
|
+
puts n
|
28
|
+
end
|
29
|
+
|
30
|
+
def n
|
31
|
+
"n"
|
32
|
+
end
|
33
|
+
CODE
|
34
|
+
|
35
|
+
msmn = Masamune::AbstractSyntaxTree.new(code)
|
36
|
+
msmn.replace(type: :variables, old_token: "n", new_token: "foo")
|
37
|
+
|
38
|
+
# This will produce the following code in string form.
|
39
|
+
10.times do |foo|
|
40
|
+
puts foo
|
41
|
+
end
|
42
|
+
|
43
|
+
def n
|
44
|
+
"n"
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
18
48
|
Pinpoint variables and methods in your source code even when other tokens have the same or similar spelling:
|
19
49
|
```ruby
|
20
50
|
code = <<CODE
|
@@ -14,7 +14,7 @@ module Masamune
|
|
14
14
|
# nice to find out and implement it document/implement it somewhere.
|
15
15
|
def extract_data_nodes
|
16
16
|
@contents[1][1].map do |content|
|
17
|
-
|
17
|
+
DataNode.new(content, @ast_id)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -11,7 +11,7 @@ module Masamune
|
|
11
11
|
|
12
12
|
def params
|
13
13
|
# This node should exist already, so we search for it in the ast object.
|
14
|
-
block_var =
|
14
|
+
block_var = BlockVar.new(contents[1], ast_id)
|
15
15
|
ast.node_list.find {|node| node.contents == block_var.contents}
|
16
16
|
end
|
17
17
|
end
|
@@ -11,7 +11,7 @@ module Masamune
|
|
11
11
|
|
12
12
|
def params
|
13
13
|
# This node should exist already, so we search for it in the ast object.
|
14
|
-
block_var =
|
14
|
+
block_var = BlockVar.new(contents[1], ast_id)
|
15
15
|
ast.node_list.find {|node| node.contents == block_var.contents}
|
16
16
|
end
|
17
17
|
end
|
@@ -1,13 +1,14 @@
|
|
1
1
|
module Masamune
|
2
2
|
class AbstractSyntaxTree
|
3
|
-
attr_reader :tree
|
3
|
+
attr_reader :code, :tree
|
4
4
|
attr_accessor :node_list, :data_node_list, :lex_nodes
|
5
5
|
|
6
6
|
def initialize(code)
|
7
|
+
@code = code
|
7
8
|
@tree = Ripper.sexp(code)
|
8
9
|
raw_lex_nodes = Ripper.lex(code)
|
9
10
|
@lex_nodes = raw_lex_nodes.map do |lex_node|
|
10
|
-
|
11
|
+
LexNode.new(raw_lex_nodes.index(lex_node), lex_node, self.__id__)
|
11
12
|
end
|
12
13
|
|
13
14
|
@node_list = []
|
@@ -21,7 +22,7 @@ module Masamune
|
|
21
22
|
msmn_node = klass.new(tree_node, self.__id__)
|
22
23
|
else
|
23
24
|
# Create a general node if the node is a single value.
|
24
|
-
msmn_node =
|
25
|
+
msmn_node = Node.new(tree_node, self.__id__)
|
25
26
|
end
|
26
27
|
|
27
28
|
# Register nodes and any data nodes housed within it.
|
@@ -83,37 +84,48 @@ module Masamune
|
|
83
84
|
# Ensure the classes are in an array
|
84
85
|
token_classes = [token_classes].flatten
|
85
86
|
|
86
|
-
|
87
|
+
nodes = []
|
87
88
|
token_classes.each do |klass|
|
88
|
-
|
89
|
+
nodes << @node_list.select {|node| node.class == klass}
|
89
90
|
end
|
90
91
|
|
91
92
|
# Searching for multiple classes will yield multi-dimensional arrays,
|
92
93
|
# so we ensure everything is flattened out before moving forward.
|
93
|
-
|
94
|
+
nodes.flatten!
|
94
95
|
|
95
96
|
if token
|
96
|
-
|
97
|
+
# TODO: This most likely shouldn't be `node.data_nodes.first`.
|
98
|
+
# There are probably more data_nodes we need to check depending on the node class.
|
99
|
+
nodes = nodes.select {|node| node.data_nodes.first.token == token}.flatten
|
97
100
|
end
|
98
101
|
|
99
102
|
final_result = []
|
100
|
-
|
101
|
-
node.data_nodes.each {|dn| final_result << dn.position_and_token}
|
103
|
+
nodes.each do |node|
|
104
|
+
node.data_nodes.each {|dn| final_result << dn.position_and_token} if node.data_nodes
|
102
105
|
end
|
103
106
|
|
104
|
-
|
107
|
+
DataNode.order_results_by_position(final_result)
|
108
|
+
end
|
109
|
+
|
110
|
+
def replace(type:, old_token:, new_token:)
|
111
|
+
Slasher.replace(
|
112
|
+
type: type,
|
113
|
+
old_token: old_token,
|
114
|
+
new_token: new_token,
|
115
|
+
code: @code,
|
116
|
+
ast: self
|
117
|
+
)
|
105
118
|
end
|
106
119
|
|
107
120
|
private
|
108
121
|
|
109
122
|
def get_node_class(type)
|
110
123
|
begin
|
111
|
-
|
112
|
-
klass = class_name.constantize
|
124
|
+
"Masamune::AbstractSyntaxTree::#{type.to_s.camelize}".constantize
|
113
125
|
rescue NameError
|
114
126
|
# For all other nodes that we haven't covered yet, we just make a general class.
|
115
127
|
# We can worry about adding the classes for other nodes as we go.
|
116
|
-
|
128
|
+
Node
|
117
129
|
end
|
118
130
|
end
|
119
131
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Masamune
|
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
|
+
position_and_token_ary = if type.is_a?(Symbol) && ast.respond_to?(type)
|
7
|
+
ast.send(type)
|
8
|
+
elsif type.is_a?(Array)
|
9
|
+
type.map {|klass| ast.find_nodes(klass)}.flatten
|
10
|
+
end
|
11
|
+
|
12
|
+
tokens_to_replace = position_and_token_ary.select do |pos_and_tok|
|
13
|
+
pos_and_tok[:token] == old_token
|
14
|
+
end
|
15
|
+
|
16
|
+
# Build from lex nodes
|
17
|
+
result = ast.lex_nodes.map do |lex_node|
|
18
|
+
match_found = false
|
19
|
+
tokens_to_replace.each do |position_and_token|
|
20
|
+
if position_and_token[:position] == lex_node.position
|
21
|
+
match_found = true
|
22
|
+
break
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
match_found ? new_token : lex_node.token
|
27
|
+
end
|
28
|
+
|
29
|
+
result.join
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/masamune/version.rb
CHANGED
data/lib/masamune.rb
CHANGED
@@ -4,6 +4,7 @@ require_relative "masamune/version"
|
|
4
4
|
require "ripper"
|
5
5
|
require "active_support/core_ext/string/inflections"
|
6
6
|
require "masamune/lex_node"
|
7
|
+
require "masamune/slasher"
|
7
8
|
require "masamune/abstract_syntax_tree"
|
8
9
|
require "masamune/abstract_syntax_tree/node"
|
9
10
|
require "masamune/abstract_syntax_tree/data_node"
|
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.1.
|
4
|
+
version: 1.1.1
|
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-
|
11
|
+
date: 2023-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -55,7 +55,7 @@ files:
|
|
55
55
|
- lib/masamune/abstract_syntax_tree/var_ref.rb
|
56
56
|
- lib/masamune/abstract_syntax_tree/vcall.rb
|
57
57
|
- lib/masamune/lex_node.rb
|
58
|
-
- lib/masamune/
|
58
|
+
- lib/masamune/slasher.rb
|
59
59
|
- lib/masamune/version.rb
|
60
60
|
- sig/masamune.rbs
|
61
61
|
homepage: https://www.github.com/gazayas/masamune-ast
|
data/lib/masamune/slicer.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
module Masamune
|
2
|
-
module Slicer
|
3
|
-
def initialize(ast)
|
4
|
-
@ast = ast
|
5
|
-
end
|
6
|
-
|
7
|
-
# TODO
|
8
|
-
|
9
|
-
# def replace(type, token)
|
10
|
-
# @ast.search(type, token)
|
11
|
-
# end
|
12
|
-
|
13
|
-
# def insert_inside_block
|
14
|
-
# end
|
15
|
-
|
16
|
-
# def append_to_block
|
17
|
-
# end
|
18
|
-
end
|
19
|
-
end
|