masamune-ast 1.1.5 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cde8e5ad304fc141ebf9a19a2b14ca11bdb5a582f37946e7190888a142cbf800
4
- data.tar.gz: 79cfd7151f94c22f78efd3fcfda3be6321b68a76ea5d5175b73ecd96b2ae2331
3
+ metadata.gz: f599b770d8e12444bbb2c2bb6aad28d8d0b9673e99708d9d713af4186f96fb4f
4
+ data.tar.gz: 723f6ab17c2152f9ab92e6da6f0130bc1ab1aa1fd0174ee00a1d9bb7206df182
5
5
  SHA512:
6
- metadata.gz: 071e318a82a6c9df04ca33746f2f1e97ff2a49362e054621d7ff490bf727574bcd55648c6fcdd63ec6f49c5962eea009fbdce1acd6bc98d0f5d9bc35f3336d9e
7
- data.tar.gz: 7bfd78af1aa7e621f343ef77521a2895921b449f944487518746b201ff3d925fe9e22645b17d7bd8fd83fcaf89463870f339bb2fa0a654c9bc9c9cf194bb2183
6
+ metadata.gz: 622cfe88710212e12d4045fe39837dd9767b56b64abb62872f544b37d6ac286f85dfb9324ef709bb32ab4219e280eff7f4fc6a966ddb379b79b5a5b3b9c06dc3
7
+ data.tar.gz: 7db8c29128764c9c36f79a98156c68d4bc008a183ceeed351405a6377606721e33523b267362b0cf1f3a19119db3e1606d494869ec28f340680a8812a4e3868b
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- masamune-ast (1.1.5)
4
+ masamune-ast (1.2.1)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -26,6 +26,7 @@ GEM
26
26
  concurrent-ruby (~> 1.0)
27
27
 
28
28
  PLATFORMS
29
+ x86_64-darwin-21
29
30
  x86_64-linux
30
31
 
31
32
  DEPENDENCIES
data/README.md CHANGED
@@ -57,21 +57,21 @@ CODE
57
57
  msmn = Masamune::AbstractSyntaxTree.new(code)
58
58
 
59
59
  msmn.variables
60
- #=> [{:position=>[1, 0], :token=>"java"},
61
- #=> {:position=>[2, 0], :token=>"javascript"},
62
- #=> {:position=>[2, 13], :token=>"java"},
63
- #=> {:position=>[3, 5], :token=>"java"},
64
- #=> {:position=>[3, 25], :token=>"javascript"}]
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
65
 
66
66
  msmn.strings
67
- #=> [{:position=>[1, 8], :token=>"java"},
68
- #=> {:position=>[2, 21], :token=>"script"},
69
- #=> {:position=>[3, 13], :token=>" is not "}]
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
70
 
71
71
  msmn.variables(name: "java")
72
- #=> [{position: [1, 0], token: "java"},
73
- #=> {position: [2, 13], token: "java"},
74
- #=> {position: [3, 5], token: "java"}]
72
+ #=> [{:line_number=>1, :index_on_line=>0, :token=>"java"},
73
+ #=> {:line_number=>2, :index_on_line=>13, :token=>"java"},
74
+ #=> {:line_number=>3, :index_on_line=>5, :token=>"java"}]
75
75
 
76
76
  code = <<CODE
77
77
  ary = [1, 2, 3]
@@ -88,22 +88,22 @@ CODE
88
88
  msmn = Masamune::AbstractSyntaxTree.new(code)
89
89
 
90
90
  msmn.all_methods
91
- #=> [{:position=>[2, 4], :token=>"sum"},
92
- #=> {:position=>[2, 8], :token=>"times"},
93
- #=> {:position=>[3, 2], :token=>"puts"},
94
- #=> {:position=>[6, 4], :token=>"foo"},
95
- #=> {:position=>[8, 0], :token=>"foo"},
96
- #=> {:position=>[9, 0], :token=>"foo"}]
91
+ #=> [{:line_number=>2, :index_on_line=>4, :token=>"sum"},
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
97
 
98
98
  msmn.method_calls
99
- #=> [{:position=>[2, 4], :token=>"sum"},
100
- #=> {:position=>[2, 8], :token=>"times"},
101
- #=> {:position=>[3, 2], :token=>"puts"},
102
- #=> {:position=>[8, 0], :token=>"foo"},
103
- #=> {:position=>[9, 0], :token=>"foo"}]
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
104
 
105
105
  msmn.method_definitions
106
- #=> [{:position=>[6, 4], :token=>"foo"}]
106
+ #=> [{:line_number=>6, :index_on_line=>4, :token=>"foo"}]
107
107
  ```
108
108
 
109
109
  You can also return the node classes themselves and get the data from there:
@@ -115,28 +115,32 @@ CODE
115
115
 
116
116
  msmn = Masamune::AbstractSyntaxTree.new(code)
117
117
  msmn.strings(result_type: :nodes)
118
- #=> [#<Masamune::AbstractSyntaxTree::StringContent:0x00007f6f7c9a6850
119
- #=> @ast_id=1440,
120
- #=> @contents=[:string_content, [:@tstring_content, "ruby", [1, 1]]],
121
- #=> @data_nodes=
122
- #=> [#<Masamune::AbstractSyntaxTree::DataNode:0x00007f6f7c9a6828
123
- #=> @ast_id=1440,
124
- #=> @contents=[:@tstring_content, "ruby", [1, 1]],
125
- #=> @data_nodes=nil,
126
- #=> @line_position=[1, 1],
127
- #=> @token="ruby",
128
- #=> @type=:@tstring_content>]>,
129
- #=> #<Masamune::AbstractSyntaxTree::StringContent:0x00007f6f7c9a5630
130
- #=> @ast_id=1440,
131
- #=> @contents=[:string_content, [:@tstring_content, "rails", [2, 1]]],
132
- #=> @data_nodes=
133
- #=> [#<Masamune::AbstractSyntaxTree::DataNode:0x00007f6f7c9a5608
134
- #=> @ast_id=1440,
135
- #=> @contents=[:@tstring_content, "rails", [2, 1]],
136
- #=> @data_nodes=nil,
137
- #=> @line_position=[2, 1],
138
- #=> @token="rails",
139
- #=> @type=:@tstring_content>]>]
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>]>]
140
144
  ```
141
145
 
142
146
  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:
@@ -3,16 +3,17 @@
3
3
  # These values are the `type`, `token`, and `position`, respectively.
4
4
  # It is simliar to what you see in `Ripper.lex(code)` and `Masamune::AbstractSyntaxTree's @lex_nodes`.
5
5
 
6
- # We break this down into a simpler structure, `position_and_token`,
7
- # which looks like this: {position: [4, 7], token: "ruby"}
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
8
 
9
9
  module Masamune
10
10
  class AbstractSyntaxTree
11
11
  class DataNode < Node
12
- attr_reader :type, :token, :line_position
12
+ attr_reader :type, :token, :line_number, :index_on_line
13
13
 
14
14
  def initialize(contents, ast_id, parent)
15
- @type, @token, @line_position = contents
15
+ @type, @token, line_position = contents
16
+ @line_number, @index_on_line = line_position
16
17
  @parent = parent
17
18
  super(contents, ast_id)
18
19
  end
@@ -20,43 +21,28 @@ module Masamune
20
21
  # Results here represent the position and token of the
21
22
  # data we're searching in the form of a Hash like the following:
22
23
  # [
23
- # {position: [4, 7], token: "ruby"},
24
- # {position: [7, 7], token: "rails"}
24
+ # {line_number: 4, index_on_line: 7, token: "ruby"},
25
+ # {line_number: 7, index_on_line: 7, token: "rails"}
25
26
  # ]
26
27
  # TODO: Worry about using a faster sorting algorithm later.
27
- def self.order_results_by_position(position_and_token_ary)
28
- # Extract the line numbers first, i.e - 4 from [4, 7]
29
- line_numbers = position_and_token_ary.map do |position_and_token|
30
- position_and_token[:position].first
31
- end.uniq.sort
32
-
33
- final_result = []
34
- line_numbers.each do |line_number|
35
- # Group data together in an array if they're on the same line.
36
- shared_line_data = position_and_token_ary.select do |position_and_token|
37
- position_and_token[:position].first == line_number
38
- end
39
-
40
- # Sort the positions on each line number respectively.
41
- positions_on_line = shared_line_data.map do |position_and_token|
42
- position_and_token[:position].last
43
- end.sort
44
-
45
- # Apply to the final result.
46
- positions_on_line.each do |position_on_line|
47
- shared_line_data.each do |position_and_token|
48
- if position_and_token[:position].last == position_on_line
49
- final_result << position_and_token
50
- end
51
- end
52
- end
28
+ def self.order_results_by_position(results)
29
+ results.sort do |a, b|
30
+ by_line = a[:line_number] <=> b[:line_number]
31
+ # If we're on the same line, refer to the inner index for order.
32
+ by_line.zero? ? a[:index_on_line] <=> b[:index_on_line] : by_line
53
33
  end
34
+ end
54
35
 
55
- final_result
36
+ def line_data_and_token
37
+ {
38
+ line_number: @line_number,
39
+ index_on_line: @index_on_line,
40
+ token: @token
41
+ }
56
42
  end
57
43
 
58
- def position_and_token
59
- {position: @line_position, token: @token}
44
+ def position
45
+ [@line_number, @index_on_line]
60
46
  end
61
47
  end
62
48
  end
@@ -52,32 +52,22 @@ module Masamune
52
52
 
53
53
  # TODO: Add block_params: true to the arguments.
54
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)
55
+ results = find_nodes([VarField, VarRef, Params], token: name, result_type: result_type)
61
56
  order_results(results)
62
57
  end
63
58
 
64
59
  def strings(content: nil, result_type: Hash)
65
- results = find_nodes(get_node_class(:string_content), token: content, result_type: result_type)
60
+ results = find_nodes(StringContent, token: content, result_type: result_type)
66
61
  order_results(results)
67
62
  end
68
63
 
69
64
  def method_definitions(name: nil, result_type: Hash)
70
- results = find_nodes(get_node_class(:def), token: name, result_type: result_type)
65
+ results = find_nodes(Def, token: name, result_type: result_type)
71
66
  order_results(results)
72
67
  end
73
68
 
74
69
  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)
70
+ results = find_nodes([Vcall, Call, Command], token: name, result_type: result_type)
81
71
  order_results(results)
82
72
  end
83
73
 
@@ -95,17 +85,17 @@ module Masamune
95
85
  end
96
86
 
97
87
  def symbol_literals(content: nil, result_type: Hash)
98
- results = find_nodes(get_node_class(:symbol_literal), token: content, result_type: result_type)
88
+ results = find_nodes(SymbolLiteral, token: content, result_type: result_type)
99
89
  order_results(results)
100
90
  end
101
91
 
102
92
  def string_symbols(content: nil, result_type: Hash)
103
- results = find_nodes(get_node_class(:dyna_symbol), token: content, result_type: result_type)
93
+ results = find_nodes(DynaSymbol, token: content, result_type: result_type)
104
94
  order_results(results)
105
95
  end
106
96
 
107
97
  def comments(content: nil, result_type: Hash)
108
- results = find_nodes(get_node_class(:comment), token: content, result_type: result_type)
98
+ results = find_nodes(Comment, token: content, result_type: result_type)
109
99
  order_results(results)
110
100
  end
111
101
 
@@ -116,17 +106,16 @@ module Masamune
116
106
 
117
107
  def block_params(content: nil, result_type: Hash)
118
108
  # TODO: do_block_params + brace_block_params
119
- results = find_nodes(get_node_class(:params), token: content, result_type: result_type)
109
+ results = find_nodes(Params, token: content, result_type: result_type)
120
110
  order_results(results)
121
111
  end
122
112
 
123
113
  def find_nodes(token_classes, token: nil, result_type: Hash)
124
- # Ensure the classes are in an array
125
- token_classes = [token_classes].flatten
114
+ token_classes = Array(token_classes)
126
115
 
127
116
  nodes = []
128
117
  token_classes.each do |klass|
129
- if klass == Masamune::AbstractSyntaxTree::Comment
118
+ if klass == Comment
130
119
  nodes = @comment_list.dup
131
120
  else
132
121
  nodes << @node_list.select {|node| node.class == klass}
@@ -149,17 +138,18 @@ module Masamune
149
138
  nodes.each do |node|
150
139
  # Data for symbols are housed within a nested node, so we handle those differently here.
151
140
  # 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.position_and_token
141
+ if node.class == SymbolLiteral || node.class == DynaSymbol
142
+ final_result << node.get_symbol_data.line_data_and_token
154
143
  else
155
- node.data_nodes.each {|dn| final_result << dn.position_and_token} if node.data_nodes
144
+ node.data_nodes.each {|dn| final_result << dn.line_data_and_token} if node.data_nodes
156
145
  end
157
146
  end
158
147
 
159
148
  # Only order the information if we're returning hashes.
160
149
  # TODO: We might want to change the placement of order_results_by_position
161
150
  # 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
151
+ # nodes.first.class.is_a?(Hash) ? DataNode.order_results_by_position(final_result) : final_result
152
+ final_result
163
153
  end
164
154
 
165
155
  def replace(type:, old_token:, new_token:)
@@ -175,13 +165,7 @@ module Masamune
175
165
  private
176
166
 
177
167
  def get_node_class(type)
178
- begin
179
- "Masamune::AbstractSyntaxTree::#{type.to_s.camelize}".constantize
180
- rescue NameError
181
- # For all other nodes that we haven't covered yet, we just make a general class.
182
- # We can worry about adding the classes for other nodes as we go.
183
- Node
184
- end
168
+ "#{self.class}::#{type.to_s.camelize}".safe_constantize || Node # Return base Node class for any not-yet-covered nodes.
185
169
  end
186
170
 
187
171
  # We only order results when they are a Hash.
@@ -3,22 +3,26 @@ 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)
6
+ line_data_and_token_ary = if type.is_a?(Symbol)
7
7
  type_to_method = type.to_s.pluralize.to_sym
8
8
  ast.send(type_to_method)
9
9
  elsif type.is_a?(Array)
10
10
  type.map {|klass| ast.find_nodes(klass)}.flatten
11
11
  end
12
12
 
13
- tokens_to_replace = position_and_token_ary.select do |pos_and_tok|
14
- pos_and_tok[:token] == old_token
13
+ tokens_to_replace = line_data_and_token_ary.select do |line_data_and_token|
14
+ line_data_and_token[:token] == old_token
15
15
  end
16
16
 
17
17
  # Build from lex nodes
18
18
  result = ast.lex_nodes.map do |lex_node|
19
19
  match_found = false
20
- tokens_to_replace.each do |position_and_token|
21
- if position_and_token[:position] == lex_node.position
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
22
26
  match_found = true
23
27
  break
24
28
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Masamune
4
- VERSION = "1.1.5"
4
+ VERSION = "1.2.1"
5
5
  end
data/lib/masamune.rb CHANGED
@@ -30,7 +30,6 @@ require "masamune/abstract_syntax_tree/nodes/symbol"
30
30
  require "masamune/abstract_syntax_tree/nodes/vcall"
31
31
 
32
32
  require "pp"
33
- require "pry"
34
33
 
35
34
  module Masamune
36
35
  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.1.5
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriel Zayas
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-13 00:00:00.000000000 Z
11
+ date: 2023-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -71,7 +71,7 @@ metadata:
71
71
  homepage_uri: https://www.github.com/gazayas/masamune-ast
72
72
  source_code_uri: https://www.github.com/gazayas/masamune-ast
73
73
  changelog_uri: https://www.github.com/gazayas/masamune-ast
74
- post_install_message:
74
+ post_install_message:
75
75
  rdoc_options: []
76
76
  require_paths:
77
77
  - lib
@@ -86,8 +86,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
86
  - !ruby/object:Gem::Version
87
87
  version: '0'
88
88
  requirements: []
89
- rubygems_version: 3.3.7
90
- signing_key:
89
+ rubygems_version: 3.4.1
90
+ signing_key:
91
91
  specification_version: 4
92
92
  summary: Masamune
93
93
  test_files: []