astrolabe 0.3.0
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 +7 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/.rubocop.yml +29 -0
- data/.travis.yml +13 -0
- data/.yardopts +4 -0
- data/Gemfile +9 -0
- data/Guardfile +16 -0
- data/LICENSE.txt +22 -0
- data/README.md +115 -0
- data/Rakefile +11 -0
- data/astrolabe.gemspec +34 -0
- data/lib/astrolabe/builder.rb +28 -0
- data/lib/astrolabe/node.rb +133 -0
- data/lib/astrolabe/version.rb +15 -0
- data/lib/astrolabe.rb +3 -0
- data/spec/.rubocop.yml +5 -0
- data/spec/astrolabe/node_spec.rb +318 -0
- data/spec/spec_helper.rb +95 -0
- data/spec/support/shared_contexts.rb +17 -0
- metadata +228 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 46c2d6149556152034a1102c6a17a722068b7d05
|
4
|
+
data.tar.gz: 89ff885e03757862cd9d5345bfae9127cd5665c0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b76199cb0b7abcab33a57187876733b87eac1e88f0c1db2f96954b99c13b2f707481bfdb71778eac70c02e180bc65a35508b11dceadc46c9bc41aa3be28a7839
|
7
|
+
data.tar.gz: 3cee02d4725f5ed4a98a3b7ba49818855480a2cdcbd241855dabeb37dea5fe6aaa697544ff8da485f91e5acd9433d24d41a57f435ef9ad9db73b32740a1bdbe0
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
LineLength:
|
3
|
+
Max: 100
|
4
|
+
|
5
|
+
AlignHash:
|
6
|
+
# Alignment of entries using hash rocket as separator. Valid values are:
|
7
|
+
#
|
8
|
+
# key - left alignment of keys
|
9
|
+
# 'a' => 2
|
10
|
+
# 'bb' => 3
|
11
|
+
# separator - alignment of hash rockets, keys are right aligned
|
12
|
+
# 'a' => 2
|
13
|
+
# 'bb' => 3
|
14
|
+
# table - left alignment of keys, hash rockets, and values
|
15
|
+
# 'a' => 2
|
16
|
+
# 'bb' => 3
|
17
|
+
EnforcedHashRocketStyle: table
|
18
|
+
# Alignment of entries using colon as separator. Valid values are:
|
19
|
+
#
|
20
|
+
# key - left alignment of keys
|
21
|
+
# a: 0
|
22
|
+
# bb: 1
|
23
|
+
# separator - alignment of colons, keys are right aligned
|
24
|
+
# a: 0
|
25
|
+
# bb: 1
|
26
|
+
# table - left alignment of keys and values
|
27
|
+
# a: 0
|
28
|
+
# bb: 1
|
29
|
+
EnforcedColonStyle: separator
|
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
# This group allows Guard to skip running RuboCop if RSpec failed.
|
4
|
+
group :red_green_refactor, halt_on_fail: true do
|
5
|
+
guard :rspec, all_on_start: true, cmd: 'bundle exec rspec --format Fuubar' do
|
6
|
+
watch(%r{^spec/.+_spec\.rb$})
|
7
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
8
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
9
|
+
watch(%r{^spec/support/.+\.rb$}) { 'spec' }
|
10
|
+
end
|
11
|
+
|
12
|
+
guard :rubocop, cli: '--format fuubar' do
|
13
|
+
watch(%r{.+\.rb$})
|
14
|
+
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
|
15
|
+
end
|
16
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Yuji Nakayama
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
[](http://badge.fury.io/rb/astrolabe)
|
2
|
+
[](https://gemnasium.com/yujinakayama/astrolabe)
|
3
|
+
[](https://travis-ci.org/yujinakayama/astrolabe)
|
4
|
+
[](https://coveralls.io/r/yujinakayama/astrolabe)
|
5
|
+
[](https://codeclimate.com/github/yujinakayama/astrolabe)
|
6
|
+
|
7
|
+
# Astrolabe
|
8
|
+
|
9
|
+
**Astrolabe** is an AST node library that provides an object-oriented way to handle AST by extending [Parser](https://github.com/whitequark/parser)'s node class.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your `Gemfile`:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'astrolabe'
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
$ bundle install
|
23
|
+
```
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
You can generate an AST that consists of `Astrolabe::Node` by using `Astrolabe::Builder` along with `Parser`:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
require 'astrolabe/builder'
|
31
|
+
require 'parser/current'
|
32
|
+
|
33
|
+
buffer = Parser::Source::Buffer.new('(string)')
|
34
|
+
buffer.source = 'puts :foo'
|
35
|
+
|
36
|
+
builder = Astrolabe::Builder.new
|
37
|
+
parser = Parser::CurrentRuby.new(builder)
|
38
|
+
|
39
|
+
root_node = parser.parse(buffer)
|
40
|
+
root_node.class # => Astrolabe::Node
|
41
|
+
```
|
42
|
+
|
43
|
+
`Astrolabe::Node` is a subclass of [`Parser::AST::Node`](http://rubydoc.info/gems/parser/Parser/AST/Node).
|
44
|
+
|
45
|
+
## APIs
|
46
|
+
|
47
|
+
See these references for all the public APIs:
|
48
|
+
|
49
|
+
* [`Astrolabe::Node`](http://rubydoc.info/gems/astrolabe/Astrolabe/Node)
|
50
|
+
* [`Astrolabe::Builder`](http://rubydoc.info/gems/astrolabe/Astrolabe/Builder)
|
51
|
+
|
52
|
+
### Node Type Predicate Methods
|
53
|
+
|
54
|
+
These would be useful especially when combined with `Enumerable` methods (described below).
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
node.send_type? # Equivalent to: `node.type == :send`
|
58
|
+
node.op_asgn_type? # Equivalent to: `node.type == :op_asgn`
|
59
|
+
|
60
|
+
# Non-word characters (other than a-zA-Z0-9_) in type names are omitted.
|
61
|
+
node.defined_type? # Equivalent to: `node.type == :defined?`
|
62
|
+
```
|
63
|
+
|
64
|
+
### Access to Parent Node
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
def method_taking_block?(node)
|
68
|
+
return unless node.parent.block_type?
|
69
|
+
node.parent.children.first.equal?(node)
|
70
|
+
end
|
71
|
+
|
72
|
+
block_node = parser.parse(buffer)
|
73
|
+
# (block
|
74
|
+
# (send
|
75
|
+
# (int 3) :times)
|
76
|
+
# (args
|
77
|
+
# (arg :i))
|
78
|
+
# (send nil :do_something))
|
79
|
+
|
80
|
+
send_node, args_node, body_node = *block_node
|
81
|
+
method_taking_block?(send_node) # => true
|
82
|
+
```
|
83
|
+
|
84
|
+
### AST Traversal
|
85
|
+
|
86
|
+
These methods bring the power of `Enumerable` to AST.
|
87
|
+
|
88
|
+
Note that you may want to use [`Parser::AST::Processor`](http://rubydoc.info/gems/parser/Parser/AST/Processor)
|
89
|
+
if you don't need to track context of AST.
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
# Iterate ancestor nodes in the order from parent to root.
|
93
|
+
node.each_ancestor do |ancestor_node|
|
94
|
+
p ancestor_node
|
95
|
+
end
|
96
|
+
|
97
|
+
# This is different from `node.children.each { |child| ... }`
|
98
|
+
# which yields all children including non-node element.
|
99
|
+
node.each_child_node do |child_node|
|
100
|
+
p child_node
|
101
|
+
end
|
102
|
+
|
103
|
+
# Collect all lvar nodes under the receiver node.
|
104
|
+
lvar_nodes = node.each_descendant.select(&:lvar_type?)
|
105
|
+
```
|
106
|
+
|
107
|
+
## Compatibility
|
108
|
+
|
109
|
+
Tested on MRI 1.9, 2.0, 2.1, JRuby in 1.9 mode and Rubinius 2.0+.
|
110
|
+
|
111
|
+
## License
|
112
|
+
|
113
|
+
Copyright (c) 2014 Yuji Nakayama
|
114
|
+
|
115
|
+
See the [LICENSE.txt](LICENSE.txt) for details.
|
data/Rakefile
ADDED
data/astrolabe.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'astrolabe/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'astrolabe'
|
9
|
+
spec.version = Astrolabe::Version.to_s
|
10
|
+
spec.authors = ['Yuji Nakayama']
|
11
|
+
spec.email = ['nkymyj@gmail.com']
|
12
|
+
spec.summary = 'Object-oriented AST library for Parser'
|
13
|
+
spec.description = spec.summary
|
14
|
+
spec.homepage = 'https://github.com/yujinakayama/astrolabe'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(/^spec\//)
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_runtime_dependency 'parser', '~> 2.1'
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
25
|
+
spec.add_development_dependency 'rake', '~> 10.3'
|
26
|
+
spec.add_development_dependency 'yard', '~> 0.8'
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
28
|
+
spec.add_development_dependency 'fuubar', '~> 2.0.0.rc1'
|
29
|
+
spec.add_development_dependency 'simplecov', '~> 0.7'
|
30
|
+
spec.add_development_dependency 'rubocop', '~> 0.24'
|
31
|
+
spec.add_development_dependency 'guard-rspec', '>= 4.2.3', '< 5.0'
|
32
|
+
spec.add_development_dependency 'guard-rubocop', '~> 1.0'
|
33
|
+
spec.add_development_dependency 'ruby_gntp', '~> 0.3'
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'astrolabe/node'
|
4
|
+
require 'parser'
|
5
|
+
|
6
|
+
module Astrolabe
|
7
|
+
# `Astrolabe::Builder` is an AST builder that is utilized to let `Parser` generate AST with
|
8
|
+
# {Astrolabe::Node}.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# require 'astrolabe/builder'
|
12
|
+
# require 'parser/current'
|
13
|
+
#
|
14
|
+
# buffer = Parser::Source::Buffer.new('(string)')
|
15
|
+
# buffer.source = 'puts :foo'
|
16
|
+
#
|
17
|
+
# builder = Astrolabe::Builder.new
|
18
|
+
# parser = Parser::CurrentRuby.new(builder)
|
19
|
+
# root_node = parser.parse(buffer)
|
20
|
+
class Builder < Parser::Builders::Default
|
21
|
+
# Generates {Node} from the given information.
|
22
|
+
#
|
23
|
+
# @return [Node] the generated node
|
24
|
+
def n(type, children, source_map)
|
25
|
+
Node.new(type, children, location: source_map)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'parser'
|
4
|
+
|
5
|
+
module Astrolabe
|
6
|
+
# `Astrolabe::Node` is a subclass of `Parser::AST::Node`. It provides an access to parent node and
|
7
|
+
# an object-oriented way to handle AST with the power of `Enumerable`.
|
8
|
+
#
|
9
|
+
# Though not described in the auto-generated API documentation, it has predicate methods for every
|
10
|
+
# node type. These methods would be useful especially when combined with `Enumerable` methods.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# node.send_type? # Equivalent to: `node.type == :send`
|
14
|
+
# node.op_asgn_type? # Equivalent to: `node.type == :op_asgn`
|
15
|
+
#
|
16
|
+
# # Non-word characters (other than a-zA-Z0-9_) in type names are omitted.
|
17
|
+
# node.defined_type? # Equivalent to: `node.type == :defined?`
|
18
|
+
#
|
19
|
+
# # Collect all lvar nodes under the receiver node.
|
20
|
+
# lvar_nodes = node.each_descendant.select(&:lvar_type?)
|
21
|
+
class Node < Parser::AST::Node
|
22
|
+
# @see http://rubydoc.info/gems/ast/AST/Node:initialize
|
23
|
+
def initialize(type, children = [], properties = {})
|
24
|
+
@mutable_attributes = {}
|
25
|
+
|
26
|
+
# ::AST::Node#initialize freezes itself.
|
27
|
+
super
|
28
|
+
|
29
|
+
# #parent= would be invoked multiple times for a node because there are pending nodes while
|
30
|
+
# constructing AST and they are replaced later.
|
31
|
+
# For example, `lvar` and `send` type nodes are initially created as an `ident` type node and
|
32
|
+
# fixed to each type later.
|
33
|
+
# So, the #parent attribute needs to be mutable.
|
34
|
+
each_child_node do |child_node|
|
35
|
+
child_node.parent = self
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
Parser::Meta::NODE_TYPES.each do |node_type|
|
40
|
+
method_name = "#{node_type.to_s.gsub(/\W/, '')}_type?"
|
41
|
+
define_method(method_name) do
|
42
|
+
type == node_type
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the parent node, or `nil` if the receiver is a root node.
|
47
|
+
#
|
48
|
+
# @return [Node, nil] the parent node or `nil`
|
49
|
+
def parent
|
50
|
+
@mutable_attributes[:parent]
|
51
|
+
end
|
52
|
+
|
53
|
+
def parent=(node)
|
54
|
+
@mutable_attributes[:parent] = node
|
55
|
+
end
|
56
|
+
|
57
|
+
protected :parent=
|
58
|
+
|
59
|
+
# Returns whether the receiver is a root node or not.
|
60
|
+
#
|
61
|
+
# @return [Boolean] whether the receiver is a root node or not
|
62
|
+
def root?
|
63
|
+
parent.nil?
|
64
|
+
end
|
65
|
+
|
66
|
+
# Calls the given block for each ancestor node in the order from parent to root.
|
67
|
+
# If no block is given, an `Enumerator` is returned.
|
68
|
+
#
|
69
|
+
# @yieldparam [Node] node each ancestor node
|
70
|
+
# @return [self] if a block is given
|
71
|
+
# @return [Enumerator] if no block is given
|
72
|
+
def each_ancestor(&block)
|
73
|
+
return to_enum(__method__) unless block_given?
|
74
|
+
|
75
|
+
if parent
|
76
|
+
yield parent
|
77
|
+
parent.each_ancestor(&block)
|
78
|
+
end
|
79
|
+
|
80
|
+
self
|
81
|
+
end
|
82
|
+
|
83
|
+
# Calls the given block for each child node.
|
84
|
+
# If no block is given, an `Enumerator` is returned.
|
85
|
+
#
|
86
|
+
# Note that this is different from `node.children.each { |child| ... }` which yields all
|
87
|
+
# children including non-node element.
|
88
|
+
#
|
89
|
+
# @yieldparam [Node] node each child node
|
90
|
+
# @return [self] if a block is given
|
91
|
+
# @return [Enumerator] if no block is given
|
92
|
+
def each_child_node
|
93
|
+
return to_enum(__method__) unless block_given?
|
94
|
+
|
95
|
+
children.each do |child|
|
96
|
+
next unless child.is_a?(Node)
|
97
|
+
yield child
|
98
|
+
end
|
99
|
+
|
100
|
+
self
|
101
|
+
end
|
102
|
+
|
103
|
+
# Calls the given block for each descendant node with depth first order.
|
104
|
+
# If no block is given, an `Enumerator` is returned.
|
105
|
+
#
|
106
|
+
# @yieldparam [Node] node each descendant node
|
107
|
+
# @return [self] if a block is given
|
108
|
+
# @return [Enumerator] if no block is given
|
109
|
+
def each_descendant(&block)
|
110
|
+
return to_enum(__method__) unless block_given?
|
111
|
+
|
112
|
+
each_child_node do |child_node|
|
113
|
+
yield child_node
|
114
|
+
child_node.each_descendant(&block)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Calls the given block for the receiver and each descendant node with depth first order.
|
119
|
+
# If no block is given, an `Enumerator` is returned.
|
120
|
+
#
|
121
|
+
# This method would be useful when you treat the receiver node as a root of tree and want to
|
122
|
+
# iterate all nodes in the tree.
|
123
|
+
#
|
124
|
+
# @yieldparam [Node] node each node
|
125
|
+
# @return [self] if a block is given
|
126
|
+
# @return [Enumerator] if no block is given
|
127
|
+
def each_node(&block)
|
128
|
+
return to_enum(__method__) unless block_given?
|
129
|
+
yield self
|
130
|
+
each_descendant(&block)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
data/lib/astrolabe.rb
ADDED
data/spec/.rubocop.yml
ADDED
@@ -0,0 +1,318 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'astrolabe/node'
|
4
|
+
|
5
|
+
module Astrolabe
|
6
|
+
describe Node, :ast do
|
7
|
+
describe '#parent' do
|
8
|
+
let(:source) { <<-END }
|
9
|
+
def some_method(arg_a, arg_b)
|
10
|
+
do_something
|
11
|
+
end
|
12
|
+
END
|
13
|
+
|
14
|
+
# (def :some_method
|
15
|
+
# (args
|
16
|
+
# (arg :arg_a)
|
17
|
+
# (arg :arg_b))
|
18
|
+
# (send nil :do_something))
|
19
|
+
|
20
|
+
context 'when the node has parent' do
|
21
|
+
let(:target_node) { root_node.each_node.find(&:args_type?) }
|
22
|
+
|
23
|
+
it 'returns the parent node' do
|
24
|
+
expect(target_node.parent).to be_def_type
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when the node does not have parent' do
|
29
|
+
it 'returns nil' do
|
30
|
+
expect(root_node.parent).to be_nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#root?' do
|
36
|
+
let(:source) { <<-END }
|
37
|
+
def some_method
|
38
|
+
do_something
|
39
|
+
end
|
40
|
+
END
|
41
|
+
|
42
|
+
subject { target_node.root? }
|
43
|
+
|
44
|
+
context 'with root node' do
|
45
|
+
let(:target_node) { root_node }
|
46
|
+
it { is_expected.to be true }
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with non-root node' do
|
50
|
+
let(:target_node) { root_node.each_child_node.to_a.first }
|
51
|
+
it { is_expected.to be false }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#each_ancestor' do
|
56
|
+
let(:source) { <<-END }
|
57
|
+
class SomeClass
|
58
|
+
attr_reader :some_attr
|
59
|
+
|
60
|
+
def some_method(arg_a, arg_b)
|
61
|
+
do_something
|
62
|
+
end
|
63
|
+
end
|
64
|
+
END
|
65
|
+
|
66
|
+
# (class
|
67
|
+
# (const nil :SomeClass) nil
|
68
|
+
# (begin
|
69
|
+
# (send nil :attr_reader
|
70
|
+
# (sym :some_attr))
|
71
|
+
# (def :some_method
|
72
|
+
# (args
|
73
|
+
# (arg :arg_a)
|
74
|
+
# (arg :arg_b))
|
75
|
+
# (send nil :do_something))))
|
76
|
+
|
77
|
+
let(:target_node) { root_node.each_node.find(&:args_type?) }
|
78
|
+
let(:expected_types) { [:def, :begin, :class] }
|
79
|
+
|
80
|
+
context 'when a block is given' do
|
81
|
+
it 'yields each ancestor node in order from parent to root' do
|
82
|
+
yielded_types = []
|
83
|
+
|
84
|
+
target_node.each_ancestor do |node|
|
85
|
+
yielded_types << node.type
|
86
|
+
end
|
87
|
+
|
88
|
+
expect(yielded_types).to eq(expected_types)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'returns itself' do
|
92
|
+
returned_value = target_node.each_ancestor {}
|
93
|
+
expect(returned_value).to equal(target_node)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'when no block is given' do
|
98
|
+
it 'returns an enumerator' do
|
99
|
+
expect(target_node.each_ancestor).to be_a Enumerator
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'the returned enumerator' do
|
103
|
+
subject(:enumerator) { target_node.each_ancestor }
|
104
|
+
|
105
|
+
it 'enumerates ancestor nodes' do
|
106
|
+
expected_types.each do |expected_type|
|
107
|
+
expect(enumerator.next.type).to eq(expected_type)
|
108
|
+
end
|
109
|
+
|
110
|
+
expect { enumerator.next }.to raise_error(StopIteration)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '#each_child_node' do
|
117
|
+
let(:source) { <<-END }
|
118
|
+
def some_method(arg_a, arg_b)
|
119
|
+
do_something
|
120
|
+
end
|
121
|
+
END
|
122
|
+
|
123
|
+
# (def :some_method
|
124
|
+
# (args
|
125
|
+
# (arg :arg_a)
|
126
|
+
# (arg :arg_b))
|
127
|
+
# (send nil :do_something))
|
128
|
+
|
129
|
+
let(:target_node) { root_node.each_node.find(&:def_type?) }
|
130
|
+
let(:expected_types) { [:args, :send] }
|
131
|
+
|
132
|
+
context 'when a block is given' do
|
133
|
+
it 'yields each child node' do
|
134
|
+
yielded_types = []
|
135
|
+
|
136
|
+
target_node.each_child_node do |node|
|
137
|
+
yielded_types << node.type
|
138
|
+
end
|
139
|
+
|
140
|
+
expect(yielded_types).to eq(expected_types)
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'returns itself' do
|
144
|
+
returned_value = target_node.each_child_node {}
|
145
|
+
expect(returned_value).to equal(target_node)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context 'when no block is given' do
|
150
|
+
it 'returns an enumerator' do
|
151
|
+
expect(target_node.each_child_node).to be_a(Enumerator)
|
152
|
+
end
|
153
|
+
|
154
|
+
describe 'the returned enumerator' do
|
155
|
+
subject(:enumerator) { target_node.each_child_node }
|
156
|
+
|
157
|
+
it 'enumerates the child nodes' do
|
158
|
+
expected_types.each do |expected_type|
|
159
|
+
expect(enumerator.next.type).to eq(expected_type)
|
160
|
+
end
|
161
|
+
|
162
|
+
expect { enumerator.next }.to raise_error(StopIteration)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe '#each_descendant' do
|
169
|
+
let(:source) { <<-END }
|
170
|
+
class SomeClass
|
171
|
+
attr_reader :some_attr
|
172
|
+
|
173
|
+
def some_method(arg_a, arg_b)
|
174
|
+
do_something
|
175
|
+
end
|
176
|
+
end
|
177
|
+
END
|
178
|
+
|
179
|
+
# (class
|
180
|
+
# (const nil :SomeClass) nil
|
181
|
+
# (begin
|
182
|
+
# (send nil :attr_reader
|
183
|
+
# (sym :some_attr))
|
184
|
+
# (def :some_method
|
185
|
+
# (args
|
186
|
+
# (arg :arg_a)
|
187
|
+
# (arg :arg_b))
|
188
|
+
# (send nil :do_something))))
|
189
|
+
|
190
|
+
let(:target_node) { root_node }
|
191
|
+
let(:expected_types) { [:const, :begin, :send, :sym, :def, :args, :arg, :arg, :send] }
|
192
|
+
|
193
|
+
context 'when a block is given' do
|
194
|
+
it 'yields each descendant node with depth first order' do
|
195
|
+
yielded_types = []
|
196
|
+
|
197
|
+
target_node.each_descendant do |node|
|
198
|
+
yielded_types << node.type
|
199
|
+
end
|
200
|
+
|
201
|
+
expect(yielded_types).to eq(expected_types)
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'returns itself' do
|
205
|
+
returned_value = target_node.each_descendant {}
|
206
|
+
expect(returned_value).to equal(target_node)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
context 'when no block is given' do
|
211
|
+
it 'returns an enumerator' do
|
212
|
+
expect(target_node.each_descendant).to be_a(Enumerator)
|
213
|
+
end
|
214
|
+
|
215
|
+
describe 'the returned enumerator' do
|
216
|
+
subject(:enumerator) { target_node.each_descendant }
|
217
|
+
|
218
|
+
it 'enumerates the descendant nodes' do
|
219
|
+
expected_types.each do |expected_type|
|
220
|
+
expect(enumerator.next.type).to eq(expected_type)
|
221
|
+
end
|
222
|
+
|
223
|
+
expect { enumerator.next }.to raise_error(StopIteration)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe '#each_node' do
|
230
|
+
let(:source) { <<-END }
|
231
|
+
class SomeClass
|
232
|
+
attr_reader :some_attr
|
233
|
+
|
234
|
+
def some_method(arg_a, arg_b)
|
235
|
+
do_something
|
236
|
+
end
|
237
|
+
end
|
238
|
+
END
|
239
|
+
|
240
|
+
# (class
|
241
|
+
# (const nil :SomeClass) nil
|
242
|
+
# (begin
|
243
|
+
# (send nil :attr_reader
|
244
|
+
# (sym :some_attr))
|
245
|
+
# (def :some_method
|
246
|
+
# (args
|
247
|
+
# (arg :arg_a)
|
248
|
+
# (arg :arg_b))
|
249
|
+
# (send nil :do_something))))
|
250
|
+
|
251
|
+
let(:target_node) { root_node }
|
252
|
+
let(:expected_types) { [:class, :const, :begin, :send, :sym, :def, :args, :arg, :arg, :send] }
|
253
|
+
|
254
|
+
context 'when a block is given' do
|
255
|
+
it 'yields itself and each descendant node with depth first order' do
|
256
|
+
yielded_types = []
|
257
|
+
|
258
|
+
target_node.each_node do |node|
|
259
|
+
yielded_types << node.type
|
260
|
+
end
|
261
|
+
|
262
|
+
expect(yielded_types).to eq(expected_types)
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'returns itself' do
|
266
|
+
returned_value = target_node.each_node {}
|
267
|
+
expect(returned_value).to equal(target_node)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
context 'when no block is given' do
|
272
|
+
it 'returns an enumerator' do
|
273
|
+
expect(target_node.each_node).to be_a(Enumerator)
|
274
|
+
end
|
275
|
+
|
276
|
+
describe 'the returned enumerator' do
|
277
|
+
subject(:enumerator) { target_node.each_node }
|
278
|
+
|
279
|
+
it 'enumerates the origin and the descendant nodes' do
|
280
|
+
expected_types.each do |expected_type|
|
281
|
+
expect(enumerator.next.type).to eq(expected_type)
|
282
|
+
end
|
283
|
+
|
284
|
+
expect { enumerator.next }.to raise_error(StopIteration)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
describe '#send_type?' do
|
291
|
+
subject { root_node.send_type? }
|
292
|
+
|
293
|
+
context 'with send type node' do
|
294
|
+
let(:source) { 'do_something' }
|
295
|
+
it { is_expected.to be true }
|
296
|
+
end
|
297
|
+
|
298
|
+
context 'with non-send type node' do
|
299
|
+
let(:source) { 'foo = 1' }
|
300
|
+
it { is_expected.to be false }
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
describe '#defined_type?' do
|
305
|
+
subject { root_node.defined_type? }
|
306
|
+
|
307
|
+
context 'with defined? type node' do
|
308
|
+
let(:source) { 'defined?(Foo)' }
|
309
|
+
it { is_expected.to be true }
|
310
|
+
end
|
311
|
+
|
312
|
+
context 'non-defined? type node' do
|
313
|
+
let(:source) { 'foo = 1' }
|
314
|
+
it { is_expected.to be false }
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
4
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
5
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause this
|
6
|
+
# file to always be loaded, without a need to explicitly require it in any files.
|
7
|
+
#
|
8
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
9
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
10
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
11
|
+
# individual file that may not need all of that loaded. Instead, make a
|
12
|
+
# separate helper file that requires this one and then use it only in the specs
|
13
|
+
# that actually need it.
|
14
|
+
#
|
15
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
16
|
+
# users commonly want.
|
17
|
+
#
|
18
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
19
|
+
RSpec.configure do |config|
|
20
|
+
# The settings below are suggested to provide a good initial experience
|
21
|
+
# with RSpec, but feel free to customize to your heart's content.
|
22
|
+
|
23
|
+
# These two settings work together to allow you to limit a spec run
|
24
|
+
# to individual examples or groups you care about by tagging them with
|
25
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
26
|
+
# get run.
|
27
|
+
config.filter_run :focus
|
28
|
+
config.run_all_when_everything_filtered = true
|
29
|
+
|
30
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
31
|
+
# file, and it's useful to allow more verbose output when running an
|
32
|
+
# individual spec file.
|
33
|
+
if config.files_to_run.one?
|
34
|
+
# Use the documentation formatter for detailed output,
|
35
|
+
# unless a formatter has already been configured
|
36
|
+
# (e.g. via a command-line flag).
|
37
|
+
config.default_formatter = 'doc'
|
38
|
+
end
|
39
|
+
|
40
|
+
# Print the 10 slowest examples and example groups at the
|
41
|
+
# end of the spec run, to help surface which specs are running
|
42
|
+
# particularly slow.
|
43
|
+
# config.profile_examples = 10
|
44
|
+
|
45
|
+
# Run specs in random order to surface order dependencies. If you find an
|
46
|
+
# order dependency and want to debug it, you can fix the order by providing
|
47
|
+
# the seed, which is printed after each run.
|
48
|
+
# --seed 1234
|
49
|
+
config.order = :random
|
50
|
+
|
51
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
52
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
53
|
+
# test failures related to randomization by passing the same `--seed` value
|
54
|
+
# as the one that triggered the failure.
|
55
|
+
Kernel.srand config.seed
|
56
|
+
|
57
|
+
# rspec-expectations config goes here. You can use an alternate
|
58
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
59
|
+
# assertions if you prefer.
|
60
|
+
config.expect_with :rspec do |expectations|
|
61
|
+
# Enable only the newer, non-monkey-patching expect syntax.
|
62
|
+
# For more details, see:
|
63
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
64
|
+
expectations.syntax = :expect
|
65
|
+
end
|
66
|
+
|
67
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
68
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
69
|
+
config.mock_with :rspec do |mocks|
|
70
|
+
# Enable only the newer, non-monkey-patching expect syntax.
|
71
|
+
# For more details, see:
|
72
|
+
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
73
|
+
mocks.syntax = :expect
|
74
|
+
|
75
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
76
|
+
# a real object. This is generally recommended.
|
77
|
+
mocks.verify_partial_doubles = true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
Dir[File.join(File.dirname(__FILE__), 'support', '*')].each do |path|
|
82
|
+
require path
|
83
|
+
end
|
84
|
+
|
85
|
+
if ENV['TRAVIS']
|
86
|
+
require 'simplecov'
|
87
|
+
require 'coveralls'
|
88
|
+
|
89
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
90
|
+
|
91
|
+
SimpleCov.start do
|
92
|
+
add_filter '/spec/'
|
93
|
+
add_filter '/vendor/'
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
shared_context 'AST', :ast do
|
4
|
+
let(:root_node) do
|
5
|
+
fail '#source must be defined with #let' unless respond_to?(:source)
|
6
|
+
|
7
|
+
require 'astrolabe/builder'
|
8
|
+
require 'parser/current'
|
9
|
+
|
10
|
+
buffer = Parser::Source::Buffer.new('(string)')
|
11
|
+
buffer.source = source
|
12
|
+
|
13
|
+
builder = Astrolabe::Builder.new
|
14
|
+
parser = Parser::CurrentRuby.new(builder)
|
15
|
+
parser.parse(buffer)
|
16
|
+
end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: astrolabe
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Yuji Nakayama
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: parser
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.8'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.8'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: fuubar
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 2.0.0.rc1
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 2.0.0.rc1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simplecov
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.7'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.7'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.24'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.24'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: guard-rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 4.2.3
|
132
|
+
- - "<"
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '5.0'
|
135
|
+
type: :development
|
136
|
+
prerelease: false
|
137
|
+
version_requirements: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: 4.2.3
|
142
|
+
- - "<"
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '5.0'
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: guard-rubocop
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - "~>"
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '1.0'
|
152
|
+
type: :development
|
153
|
+
prerelease: false
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - "~>"
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '1.0'
|
159
|
+
- !ruby/object:Gem::Dependency
|
160
|
+
name: ruby_gntp
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - "~>"
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0.3'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - "~>"
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0.3'
|
173
|
+
description: Object-oriented AST library for Parser
|
174
|
+
email:
|
175
|
+
- nkymyj@gmail.com
|
176
|
+
executables: []
|
177
|
+
extensions: []
|
178
|
+
extra_rdoc_files: []
|
179
|
+
files:
|
180
|
+
- ".gitignore"
|
181
|
+
- ".rspec"
|
182
|
+
- ".rubocop.yml"
|
183
|
+
- ".travis.yml"
|
184
|
+
- ".yardopts"
|
185
|
+
- Gemfile
|
186
|
+
- Guardfile
|
187
|
+
- LICENSE.txt
|
188
|
+
- README.md
|
189
|
+
- Rakefile
|
190
|
+
- astrolabe.gemspec
|
191
|
+
- lib/astrolabe.rb
|
192
|
+
- lib/astrolabe/builder.rb
|
193
|
+
- lib/astrolabe/node.rb
|
194
|
+
- lib/astrolabe/version.rb
|
195
|
+
- spec/.rubocop.yml
|
196
|
+
- spec/astrolabe/node_spec.rb
|
197
|
+
- spec/spec_helper.rb
|
198
|
+
- spec/support/shared_contexts.rb
|
199
|
+
homepage: https://github.com/yujinakayama/astrolabe
|
200
|
+
licenses:
|
201
|
+
- MIT
|
202
|
+
metadata: {}
|
203
|
+
post_install_message:
|
204
|
+
rdoc_options: []
|
205
|
+
require_paths:
|
206
|
+
- lib
|
207
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
208
|
+
requirements:
|
209
|
+
- - ">="
|
210
|
+
- !ruby/object:Gem::Version
|
211
|
+
version: '0'
|
212
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
213
|
+
requirements:
|
214
|
+
- - ">="
|
215
|
+
- !ruby/object:Gem::Version
|
216
|
+
version: '0'
|
217
|
+
requirements: []
|
218
|
+
rubyforge_project:
|
219
|
+
rubygems_version: 2.3.0
|
220
|
+
signing_key:
|
221
|
+
specification_version: 4
|
222
|
+
summary: Object-oriented AST library for Parser
|
223
|
+
test_files:
|
224
|
+
- spec/.rubocop.yml
|
225
|
+
- spec/astrolabe/node_spec.rb
|
226
|
+
- spec/spec_helper.rb
|
227
|
+
- spec/support/shared_contexts.rb
|
228
|
+
has_rdoc:
|