masamune-ast 1.1.3 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +36 -3
  4. data/lib/masamune/abstract_syntax_tree/nodes/blocks/brace_block.rb +13 -0
  5. data/lib/masamune/abstract_syntax_tree/nodes/blocks/do_block.rb +13 -0
  6. data/lib/masamune/abstract_syntax_tree/{program.rb → nodes/program.rb} +1 -1
  7. data/lib/masamune/abstract_syntax_tree/{do_block.rb → nodes/support_nodes/block.rb} +3 -4
  8. data/lib/masamune/abstract_syntax_tree/nodes/support_nodes/comment.rb +25 -0
  9. data/lib/masamune/abstract_syntax_tree.rb +68 -29
  10. data/lib/masamune/slasher.rb +3 -2
  11. data/lib/masamune/version.rb +1 -1
  12. data/lib/masamune.rb +18 -16
  13. metadata +19 -17
  14. data/lib/masamune/abstract_syntax_tree/brace_block.rb +0 -19
  15. /data/lib/masamune/abstract_syntax_tree/{assign.rb → nodes/assign.rb} +0 -0
  16. /data/lib/masamune/abstract_syntax_tree/{call.rb → nodes/call.rb} +0 -0
  17. /data/lib/masamune/abstract_syntax_tree/{def.rb → nodes/def.rb} +0 -0
  18. /data/lib/masamune/abstract_syntax_tree/{params.rb → nodes/params.rb} +0 -0
  19. /data/lib/masamune/abstract_syntax_tree/{string_content.rb → nodes/string_content.rb} +0 -0
  20. /data/lib/masamune/abstract_syntax_tree/{symbol.rb → nodes/symbol.rb} +0 -0
  21. /data/lib/masamune/abstract_syntax_tree/{dyna_symbol.rb → nodes/symbols/dyna_symbol.rb} +0 -0
  22. /data/lib/masamune/abstract_syntax_tree/{symbol_literal.rb → nodes/symbols/symbol_literal.rb} +0 -0
  23. /data/lib/masamune/abstract_syntax_tree/{block_var.rb → nodes/variables/block_var.rb} +0 -0
  24. /data/lib/masamune/abstract_syntax_tree/{var_field.rb → nodes/variables/var_field.rb} +0 -0
  25. /data/lib/masamune/abstract_syntax_tree/{var_ref.rb → nodes/variables/var_ref.rb} +0 -0
  26. /data/lib/masamune/abstract_syntax_tree/{vcall.rb → nodes/vcall.rb} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ccb2d3e2f9229836db093e7d6e164a30a37302610835973bcba1bf63781d4869
4
- data.tar.gz: afeba57c0b354caa8bb753c4dffdafc1aeca92b96997ec0345bd309c3c0cc33a
3
+ metadata.gz: 34d1bcf1f5fc587393f5ded22b65afb26d64217253dcea0d83ea483574988326
4
+ data.tar.gz: 21f726e99d53494fb50c08012962156245a37920425fae2ab338946d463f2721
5
5
  SHA512:
6
- metadata.gz: 63c3961e42d7ae3264eac44d6d7c6b43f572f95daa2d4c56077eace0baf2fb1a7259f6f149ce0ab0dc11a00d463f463ae246ba1a563e5a4ef83405e3d5910641
7
- data.tar.gz: c130f31c0d73a54af8775f538c928ae71d55a456b8f2d715b690ef9cf2b1de906fd808e47d3ad668630817d038d255feefd2cc309c221e5b4de5e693bc844f5c
6
+ metadata.gz: 2cca246c5770392976a5b9b9a577ac90a7363c8972bbf954f76493b13dfebbc16e3c3eeb3230238e348fa77f11accadf326fb774d11a40d03aaf172e15f9a946
7
+ data.tar.gz: 9da6db975cdd75e0a3fc57056bcb2908054a54f90da996660d4fca46e967e64aa5431a78e118b8a264ca4749f421fc7dc667626da5b6e28b7d724656d7bca241
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- masamune-ast (1.1.3)
4
+ masamune-ast (1.1.4)
5
5
  activesupport
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -33,7 +33,7 @@ code = <<~CODE
33
33
  CODE
34
34
 
35
35
  msmn = Masamune::AbstractSyntaxTree.new(code)
36
- msmn.replace(type: :variables, old_token: "n", new_token: "foo")
36
+ msmn.replace(type: :variable, old_token: "n", new_token: "foo")
37
37
 
38
38
  # This will produce the following code in string form.
39
39
  10.times do |foo|
@@ -88,9 +88,9 @@ CODE
88
88
  msmn = Masamune::AbstractSyntaxTree.new(code)
89
89
 
90
90
  msmn.all_methods
91
- #=> [{:position=>[6, 4], :token=>"foo"},
92
- #=> {:position=>[2, 4], :token=>"sum"},
91
+ #=> [{:position=>[2, 4], :token=>"sum"},
93
92
  #=> {:position=>[2, 8], :token=>"times"},
93
+ #=> {:position=>[6, 4], :token=>"foo"},
94
94
  #=> {:position=>[8, 0], :token=>"foo"},
95
95
  #=> {:position=>[9, 0], :token=>"foo"}]
96
96
 
@@ -104,6 +104,39 @@ msmn.method_definitions
104
104
  #=> [{:position=>[6, 4], :token=>"foo"}]
105
105
  ```
106
106
 
107
+ You can also return the node classes themselves and get the data from there:
108
+ ```ruby
109
+ code = <<~CODE
110
+ "ruby"
111
+ "rails"
112
+ CODE
113
+
114
+ msmn = Masamune::AbstractSyntaxTree.new(code)
115
+ msmn.strings(result_type: :nodes)
116
+ #=> [#<Masamune::AbstractSyntaxTree::StringContent:0x00007f6f7c9a6850
117
+ #=> @ast_id=1440,
118
+ #=> @contents=[:string_content, [:@tstring_content, "ruby", [1, 1]]],
119
+ #=> @data_nodes=
120
+ #=> [#<Masamune::AbstractSyntaxTree::DataNode:0x00007f6f7c9a6828
121
+ #=> @ast_id=1440,
122
+ #=> @contents=[:@tstring_content, "ruby", [1, 1]],
123
+ #=> @data_nodes=nil,
124
+ #=> @line_position=[1, 1],
125
+ #=> @token="ruby",
126
+ #=> @type=:@tstring_content>]>,
127
+ #=> #<Masamune::AbstractSyntaxTree::StringContent:0x00007f6f7c9a5630
128
+ #=> @ast_id=1440,
129
+ #=> @contents=[:string_content, [:@tstring_content, "rails", [2, 1]]],
130
+ #=> @data_nodes=
131
+ #=> [#<Masamune::AbstractSyntaxTree::DataNode:0x00007f6f7c9a5608
132
+ #=> @ast_id=1440,
133
+ #=> @contents=[:@tstring_content, "rails", [2, 1]],
134
+ #=> @data_nodes=nil,
135
+ #=> @line_position=[2, 1],
136
+ #=> @token="rails",
137
+ #=> @type=:@tstring_content>]>]
138
+ ```
139
+
107
140
  In some cases, it can be easier to look at the given lex nodes to analyze your source code since you can easily see the index and the line position it's on:
108
141
  ```ruby
109
142
  msmn.lex_nodes
@@ -0,0 +1,13 @@
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
@@ -0,0 +1,13 @@
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,4 +1,4 @@
1
- # Program represents the top layer of the AST,
1
+ # Program represents the top layer of the abstract syntax tree,
2
2
  # and the second element of the array houses the entire program.
3
3
 
4
4
  module Masamune
@@ -1,10 +1,9 @@
1
- # TODO: Add description.
1
+ # DoBlock and BraceBlock share some of
2
+ # the same logic, so we share that here.
2
3
 
3
4
  module Masamune
4
5
  class AbstractSyntaxTree
5
- class DoBlock < Node
6
- attr_accessor :ast_id
7
-
6
+ class Block < Node
8
7
  def initialize(contents, ast_id)
9
8
  super
10
9
  end
@@ -0,0 +1,25 @@
1
+ # In the abstract syntax tree created by Ripper.sexp,
2
+ # the type for comments is :void_stmt, and it doesn't have
3
+ # a data node within it either. This means that the text
4
+ # for the comment doesn't exist in the ast. It DOES exist
5
+ # in LexNode though, so we grab from them there instead.
6
+
7
+ module Masamune
8
+ class AbstractSyntaxTree
9
+ class Comment < Node
10
+ def initialize(contents, ast_id)
11
+ super
12
+
13
+ # Since this is techincally supposed to be a :void_stmt
14
+ # in this ast, we just leave this as nil.
15
+ @contents = nil
16
+ end
17
+
18
+ def extract_data_nodes
19
+ [
20
+ DataNode.new([contents.type, contents.token, contents.position], @ast_id)
21
+ ]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,6 +1,6 @@
1
1
  module Masamune
2
2
  class AbstractSyntaxTree
3
- attr_reader :code, :tree
3
+ attr_reader :code, :tree, :comment_list
4
4
  attr_accessor :node_list, :data_node_list, :lex_nodes
5
5
 
6
6
  def initialize(code)
@@ -13,7 +13,12 @@ module Masamune
13
13
 
14
14
  @node_list = []
15
15
  @data_node_list = []
16
+ @comment_list = []
16
17
  register_nodes(@tree)
18
+
19
+ # Refer to Masamune::AbstractSyntaxTree::Comment
20
+ # to see why we register these separately.
21
+ register_comments
17
22
  end
18
23
 
19
24
  def register_nodes(tree_node = self.tree)
@@ -36,30 +41,43 @@ module Masamune
36
41
  end
37
42
  end
38
43
 
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!
48
+ end
49
+
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
+
39
53
  # TODO: Add block_params: true to the arguments.
40
- def variables(name: nil)
54
+ def variables(name: nil, result_type: Hash)
41
55
  var_classes = [
42
56
  :var_field,
43
57
  :var_ref,
44
58
  :params
45
59
  ].map {|type| get_node_class(type)}
46
- find_nodes(var_classes, token: name)
60
+ results = find_nodes(var_classes, token: name, result_type: result_type)
61
+ order_results(results)
47
62
  end
48
63
 
49
- def strings(content: nil)
50
- find_nodes(get_node_class(:string_content), token: content)
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)
51
67
  end
52
68
 
53
- def method_definitions(name: nil)
54
- find_nodes(get_node_class(:def), token: name)
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)
55
72
  end
56
73
 
57
- def method_calls(name: nil)
74
+ def method_calls(name: nil, result_type: Hash)
58
75
  method_classes = [
59
76
  :vcall,
60
77
  :call
61
78
  ].map {|type| get_node_class(type)}
62
- find_nodes(method_classes, token: name)
79
+ results = find_nodes(method_classes, token: name, result_type: result_type)
80
+ order_results(results)
63
81
  end
64
82
 
65
83
  # TODO
@@ -70,49 +88,56 @@ module Masamune
70
88
  def brace_block_params
71
89
  end
72
90
 
73
- def symbols(content: nil)
74
- symbol_literals + string_symbols
91
+ def symbols(content: nil, result_type: Hash)
92
+ results = symbol_literals(content: content, result_type: result_type) + string_symbols(content: content, result_type: result_type)
93
+ order_results(results)
75
94
  end
76
95
 
77
- def symbol_literals(content: nil)
78
- find_nodes(get_node_class(:symbol_literal), token: content)
96
+ def symbol_literals(content: nil, result_type: Hash)
97
+ results = find_nodes(get_node_class(:symbol_literal), token: content, result_type: result_type)
98
+ order_results(results)
79
99
  end
80
100
 
81
- def string_symbols(content: nil)
82
- find_nodes(get_node_class(:dyna_symbol), token: content)
101
+ def string_symbols(content: nil, result_type: Hash)
102
+ results = find_nodes(get_node_class(:dyna_symbol), token: content, result_type: result_type)
103
+ order_results(results)
83
104
  end
84
105
 
85
- # @tree only shows comments as a type of `:void_stmt` and
86
- # doesn't have a data node, so we get comments from @lex_nodes.
87
- def comments(content: nil)
88
- comments = @lex_nodes.select {|node| node.type == :comment}
89
- comments.select {|comment| comment.token == content} if content
90
- comments.map {|comment| {position: comment.position, token: comment.token}}
106
+ def comments(content: nil, result_type: Hash)
107
+ results = find_nodes(get_node_class(:comment), token: content, result_type: result_type)
108
+ order_results(results)
91
109
  end
92
110
 
93
- def all_methods
94
- method_definitions + method_calls
111
+ def all_methods(name: nil, result_type: Hash)
112
+ results = method_definitions(name: name, result_type: result_type) + method_calls(name: name, result_type: result_type)
113
+ order_results(results)
95
114
  end
96
115
 
97
- def block_params
116
+ def block_params(content: nil, result_type: Hash)
98
117
  # TODO: do_block_params + brace_block_params
99
- find_nodes(get_node_class(:params))
118
+ results = find_nodes(get_node_class(:params), token: content, result_type: result_type)
119
+ order_results(results)
100
120
  end
101
121
 
102
- # TODO: Create an option to return a list of DataNode class instances.
103
- def find_nodes(token_classes, token: nil)
122
+ def find_nodes(token_classes, token: nil, result_type: Hash)
104
123
  # Ensure the classes are in an array
105
124
  token_classes = [token_classes].flatten
106
125
 
107
126
  nodes = []
108
127
  token_classes.each do |klass|
109
- nodes << @node_list.select {|node| node.class == klass}
128
+ if klass == Masamune::AbstractSyntaxTree::Comment
129
+ nodes = @comment_list.dup
130
+ else
131
+ nodes << @node_list.select {|node| node.class == klass}
132
+ end
110
133
  end
111
134
 
112
135
  # Searching for multiple classes will yield multi-dimensional arrays,
113
136
  # so we ensure everything is flattened out before moving forward.
114
137
  nodes.flatten!
115
138
 
139
+ return nodes if result_type == :nodes
140
+
116
141
  if token
117
142
  # TODO: This most likely shouldn't be `node.data_nodes.first`.
118
143
  # There are probably more data_nodes we need to check depending on the node class.
@@ -130,7 +155,10 @@ module Masamune
130
155
  end
131
156
  end
132
157
 
133
- DataNode.order_results_by_position(final_result)
158
+ # Only order the information if we're returning hashes.
159
+ # TODO: We might want to change the placement of order_results_by_position
160
+ # if the operation is being done against hashes and not data nodes.
161
+ nodes.first.class.is_a?(Hash) ? DataNode.order_results_by_position(final_result) : final_result
134
162
  end
135
163
 
136
164
  def replace(type:, old_token:, new_token:)
@@ -154,5 +182,16 @@ module Masamune
154
182
  Node
155
183
  end
156
184
  end
185
+
186
+ # We only order results when they are a Hash.
187
+ # The contents from the Hash are pulled from data nodes.
188
+ # i.e. - {position: [4, 7], token: "project"}
189
+ def order_results(results)
190
+ if results.first.is_a?(Hash)
191
+ DataNode.order_results_by_position(results)
192
+ else
193
+ results
194
+ end
195
+ end
157
196
  end
158
197
  end
@@ -3,8 +3,9 @@ module Masamune
3
3
  def self.replace(type:, old_token:, new_token:, code:, ast:)
4
4
  # `type` can either be a method from the ast like `method_definitions`,
5
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)
6
+ position_and_token_ary = if type.is_a?(Symbol)
7
+ type_to_method = type.to_s.pluralize.to_sym
8
+ ast.send(type_to_method)
8
9
  elsif type.is_a?(Array)
9
10
  type.map {|klass| ast.find_nodes(klass)}.flatten
10
11
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Masamune
4
- VERSION = "1.1.3"
4
+ VERSION = "1.1.4"
5
5
  end
data/lib/masamune.rb CHANGED
@@ -9,22 +9,24 @@ require "masamune/abstract_syntax_tree"
9
9
  require "masamune/abstract_syntax_tree/node"
10
10
  require "masamune/abstract_syntax_tree/data_node"
11
11
 
12
- # Node Types
13
- require "masamune/abstract_syntax_tree/assign"
14
- require "masamune/abstract_syntax_tree/block_var"
15
- require "masamune/abstract_syntax_tree/brace_block"
16
- require "masamune/abstract_syntax_tree/call"
17
- require "masamune/abstract_syntax_tree/def"
18
- require "masamune/abstract_syntax_tree/do_block"
19
- require "masamune/abstract_syntax_tree/dyna_symbol"
20
- require "masamune/abstract_syntax_tree/params"
21
- require "masamune/abstract_syntax_tree/program"
22
- require "masamune/abstract_syntax_tree/string_content"
23
- require "masamune/abstract_syntax_tree/symbol_literal"
24
- require "masamune/abstract_syntax_tree/symbol"
25
- require "masamune/abstract_syntax_tree/var_field"
26
- require "masamune/abstract_syntax_tree/var_ref"
27
- require "masamune/abstract_syntax_tree/vcall"
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/def"
25
+ require "masamune/abstract_syntax_tree/nodes/params"
26
+ require "masamune/abstract_syntax_tree/nodes/program"
27
+ require "masamune/abstract_syntax_tree/nodes/string_content"
28
+ require "masamune/abstract_syntax_tree/nodes/symbol"
29
+ require "masamune/abstract_syntax_tree/nodes/vcall"
28
30
 
29
31
  require "pp"
30
32
  require "pry"
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.3
4
+ version: 1.1.4
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-05 00:00:00.000000000 Z
11
+ date: 2023-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -40,23 +40,25 @@ files:
40
40
  - Rakefile
41
41
  - lib/masamune.rb
42
42
  - lib/masamune/abstract_syntax_tree.rb
43
- - lib/masamune/abstract_syntax_tree/assign.rb
44
- - lib/masamune/abstract_syntax_tree/block_var.rb
45
- - lib/masamune/abstract_syntax_tree/brace_block.rb
46
- - lib/masamune/abstract_syntax_tree/call.rb
47
43
  - lib/masamune/abstract_syntax_tree/data_node.rb
48
- - lib/masamune/abstract_syntax_tree/def.rb
49
- - lib/masamune/abstract_syntax_tree/do_block.rb
50
- - lib/masamune/abstract_syntax_tree/dyna_symbol.rb
51
44
  - lib/masamune/abstract_syntax_tree/node.rb
52
- - lib/masamune/abstract_syntax_tree/params.rb
53
- - lib/masamune/abstract_syntax_tree/program.rb
54
- - lib/masamune/abstract_syntax_tree/string_content.rb
55
- - lib/masamune/abstract_syntax_tree/symbol.rb
56
- - lib/masamune/abstract_syntax_tree/symbol_literal.rb
57
- - lib/masamune/abstract_syntax_tree/var_field.rb
58
- - lib/masamune/abstract_syntax_tree/var_ref.rb
59
- - lib/masamune/abstract_syntax_tree/vcall.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/def.rb
50
+ - lib/masamune/abstract_syntax_tree/nodes/params.rb
51
+ - lib/masamune/abstract_syntax_tree/nodes/program.rb
52
+ - lib/masamune/abstract_syntax_tree/nodes/string_content.rb
53
+ - lib/masamune/abstract_syntax_tree/nodes/support_nodes/block.rb
54
+ - lib/masamune/abstract_syntax_tree/nodes/support_nodes/comment.rb
55
+ - lib/masamune/abstract_syntax_tree/nodes/symbol.rb
56
+ - lib/masamune/abstract_syntax_tree/nodes/symbols/dyna_symbol.rb
57
+ - lib/masamune/abstract_syntax_tree/nodes/symbols/symbol_literal.rb
58
+ - lib/masamune/abstract_syntax_tree/nodes/variables/block_var.rb
59
+ - lib/masamune/abstract_syntax_tree/nodes/variables/var_field.rb
60
+ - lib/masamune/abstract_syntax_tree/nodes/variables/var_ref.rb
61
+ - lib/masamune/abstract_syntax_tree/nodes/vcall.rb
60
62
  - lib/masamune/lex_node.rb
61
63
  - lib/masamune/slasher.rb
62
64
  - lib/masamune/version.rb
@@ -1,19 +0,0 @@
1
- # TODO: Add description.
2
-
3
- module Masamune
4
- class AbstractSyntaxTree
5
- class BraceBlock < Node
6
- attr_accessor :ast_id
7
-
8
- def initialize(contents, ast_id)
9
- super
10
- end
11
-
12
- def params
13
- # This node should exist already, so we search for it in the ast object.
14
- block_var = BlockVar.new(contents[1], ast_id)
15
- ast.node_list.find {|node| node.contents == block_var.contents}
16
- end
17
- end
18
- end
19
- end