masamune-ast 1.1.0 → 1.1.2

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: 0cafe74abe55158e29178163ef544558f8e8d042d8adae0668a8625e1883c843
4
+ data.tar.gz: f0068f9e6783403ba0d17f65902c0ecfded0806424383c8d325168ce0b4c7a58
5
5
  SHA512:
6
- metadata.gz: 7650eff09ecb23034c236363ee70a971f003736a967f8efd5ae8f36e68d598f73a4239a38d839f478b4aa6b36662d7114834dedf501acfed6bd2adcb6494890e
7
- data.tar.gz: fbd0fc4a505b03dc38304abdfadd9cb31fccf5f746bbb325056c63e9a790d7814bd7292d40c95da7441731cf3ab0613f2e9879c4c27f07f61445370a499665a2
6
+ metadata.gz: b6647c5ea9745d2e1f842a0d0eea3de05e795c7afa9a3241cf9d6a87dd802c4c62e7c9fdb266afcbc8e54ffe51af25d9bacc32830d4f28009f9c34b2a4f733a8
7
+ data.tar.gz: d7781f44d57a0bca23d7a61eaed10cdb687431a66540433ac0e01f43c6a625cd05aea2cd06168b1ea980d2fffaa827634ba3633ca8a94950df2110a60d4f9f5c
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.2)
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.
@@ -69,6 +70,14 @@ module Masamune
69
70
  def brace_block_params
70
71
  end
71
72
 
73
+ # @tree only shows comments as a type of `:void_stmt` and
74
+ # doesn't have a data node, so we get comments from @lex_nodes.
75
+ def comments(content: nil)
76
+ comments = @lex_nodes.select {|node| node.type == :comment}
77
+ comments.select {|comment| comment.token == content} if content
78
+ comments.map {|comment| {position: comment.position, token: comment.token}}
79
+ end
80
+
72
81
  def all_methods
73
82
  method_definitions + method_calls
74
83
  end
@@ -83,37 +92,48 @@ module Masamune
83
92
  # Ensure the classes are in an array
84
93
  token_classes = [token_classes].flatten
85
94
 
86
- var_nodes = []
95
+ nodes = []
87
96
  token_classes.each do |klass|
88
- var_nodes << @node_list.select {|node| node.class == klass}
97
+ nodes << @node_list.select {|node| node.class == klass}
89
98
  end
90
99
 
91
100
  # Searching for multiple classes will yield multi-dimensional arrays,
92
101
  # so we ensure everything is flattened out before moving forward.
93
- var_nodes.flatten!
102
+ nodes.flatten!
94
103
 
95
104
  if token
96
- var_nodes = var_nodes.select {|node| node.data_nodes.first.token == token}.flatten
105
+ # TODO: This most likely shouldn't be `node.data_nodes.first`.
106
+ # There are probably more data_nodes we need to check depending on the node class.
107
+ nodes = nodes.select {|node| node.data_nodes.first.token == token}.flatten
97
108
  end
98
109
 
99
110
  final_result = []
100
- var_nodes.each do |node|
101
- node.data_nodes.each {|dn| final_result << dn.position_and_token}
111
+ nodes.each do |node|
112
+ node.data_nodes.each {|dn| final_result << dn.position_and_token} if node.data_nodes
102
113
  end
103
114
 
104
- Masamune::AbstractSyntaxTree::DataNode.order_results_by_position(final_result)
115
+ DataNode.order_results_by_position(final_result)
116
+ end
117
+
118
+ def replace(type:, old_token:, new_token:)
119
+ Slasher.replace(
120
+ type: type,
121
+ old_token: old_token,
122
+ new_token: new_token,
123
+ code: @code,
124
+ ast: self
125
+ )
105
126
  end
106
127
 
107
128
  private
108
129
 
109
130
  def get_node_class(type)
110
131
  begin
111
- class_name = "Masamune::AbstractSyntaxTree::#{type.to_s.camelize}"
112
- klass = class_name.constantize
132
+ "Masamune::AbstractSyntaxTree::#{type.to_s.camelize}".constantize
113
133
  rescue NameError
114
134
  # For all other nodes that we haven't covered yet, we just make a general class.
115
135
  # We can worry about adding the classes for other nodes as we go.
116
- msmn_node = Masamune::AbstractSyntaxTree::Node
136
+ Node
117
137
  end
118
138
  end
119
139
  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.2"
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.2
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