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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1ee5dca320a96035fcea4f73effbc3fceff2ee531808bf94d99aa21086186ce5
4
- data.tar.gz: 3f170766c1e97a15e9c550e61fc5f2048b28b48a5f12e2b4841a31b0dad6ebbb
3
+ metadata.gz: a00f60e535cf2096a37cd6efd639aa7c132c70e58c3b422a23538128368b5c85
4
+ data.tar.gz: 5d548fc4b9d5cf25c1099a2b446542f57342694d7b414052df004dcd2cf311c2
5
5
  SHA512:
6
- metadata.gz: 7650eff09ecb23034c236363ee70a971f003736a967f8efd5ae8f36e68d598f73a4239a38d839f478b4aa6b36662d7114834dedf501acfed6bd2adcb6494890e
7
- data.tar.gz: fbd0fc4a505b03dc38304abdfadd9cb31fccf5f746bbb325056c63e9a790d7814bd7292d40c95da7441731cf3ab0613f2e9879c4c27f07f61445370a499665a2
6
+ metadata.gz: c80bcefac510bfd4103d56fd13f39a46d1e4531eceb678d620709b97fe0c941f20f1e7ffddc6058e77aab46ab093d1d4ba768b6860649c5a57197e36f89bf109
7
+ data.tar.gz: 731a46f94d655a820acdd949d7d7fa03f3fc37277858b5b5daea3c0c13444720b3b1ca829d0f304d5aecb3f390e3055168503ce6655653268cb89fcf19ab28e3
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- masamune-ast (1.1.0)
4
+ masamune-ast (1.1.1)
5
5
  activesupport
6
6
 
7
7
  GEM
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
- Masamune::AbstractSyntaxTree::DataNode.new(content, @ast_id)
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 = Masamune::AbstractSyntaxTree::BlockVar.new(contents[1], ast_id)
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
@@ -9,7 +9,7 @@ module Masamune
9
9
 
10
10
  def extract_data_nodes
11
11
  [
12
- Masamune::AbstractSyntaxTree::DataNode.new(@contents.last, @ast_id)
12
+ DataNode.new(@contents.last, @ast_id)
13
13
  ]
14
14
  end
15
15
  end
@@ -9,7 +9,7 @@ module Masamune
9
9
 
10
10
  def extract_data_nodes
11
11
  [
12
- Masamune::AbstractSyntaxTree::DataNode.new(@contents[1], @ast_id)
12
+ DataNode.new(@contents[1], @ast_id)
13
13
  ]
14
14
  end
15
15
  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 = Masamune::AbstractSyntaxTree::BlockVar.new(contents[1], ast_id)
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
@@ -14,7 +14,7 @@ module Masamune
14
14
  # to ensure that it's being handled properly.
15
15
  unless @contents[1].nil?
16
16
  @contents[1].map do |content|
17
- Masamune::AbstractSyntaxTree::DataNode.new(content, @ast_id)
17
+ DataNode.new(content, @ast_id)
18
18
  end
19
19
  end
20
20
  end
@@ -9,7 +9,7 @@ module Masamune
9
9
 
10
10
  def extract_data_nodes
11
11
  [
12
- Masamune::AbstractSyntaxTree::DataNode.new(@contents[1], @ast_id)
12
+ DataNode.new(@contents[1], @ast_id)
13
13
  ]
14
14
  end
15
15
  end
@@ -9,7 +9,7 @@ module Masamune
9
9
 
10
10
  def extract_data_nodes
11
11
  [
12
- Masamune::AbstractSyntaxTree::DataNode.new(@contents[1], @ast_id)
12
+ DataNode.new(@contents[1], @ast_id)
13
13
  ]
14
14
  end
15
15
  end
@@ -11,7 +11,7 @@ module Masamune
11
11
 
12
12
  def extract_data_nodes
13
13
  [
14
- Masamune::AbstractSyntaxTree::DataNode.new(@contents[1], @ast_id)
14
+ DataNode.new(@contents[1], @ast_id)
15
15
  ]
16
16
  end
17
17
  end
@@ -9,7 +9,7 @@ module Masamune
9
9
 
10
10
  def extract_data_nodes
11
11
  [
12
- Masamune::AbstractSyntaxTree::DataNode.new(@contents[1], @ast_id)
12
+ DataNode.new(@contents[1], @ast_id)
13
13
  ]
14
14
  end
15
15
  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
- Masamune::LexNode.new(raw_lex_nodes.index(lex_node), lex_node, self.__id__)
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 = Masamune::AbstractSyntaxTree::Node.new(tree_node, self.__id__)
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
- var_nodes = []
87
+ nodes = []
87
88
  token_classes.each do |klass|
88
- var_nodes << @node_list.select {|node| node.class == klass}
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
- var_nodes.flatten!
94
+ nodes.flatten!
94
95
 
95
96
  if token
96
- var_nodes = var_nodes.select {|node| node.data_nodes.first.token == token}.flatten
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
- var_nodes.each do |node|
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
- Masamune::AbstractSyntaxTree::DataNode.order_results_by_position(final_result)
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
- class_name = "Masamune::AbstractSyntaxTree::#{type.to_s.camelize}"
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
- msmn_node = Masamune::AbstractSyntaxTree::Node
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Masamune
4
- VERSION = "1.1.0"
4
+ VERSION = "1.1.1"
5
5
  end
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.0
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-02 00:00:00.000000000 Z
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/slicer.rb
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
@@ -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