ruby_scribe 0.0.4 → 0.1.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.
- data/lib/ruby_scribe/emitter.rb +111 -129
- data/lib/ruby_scribe/emitter_config.rb +28 -0
- data/lib/ruby_scribe/emitter_helpers.rb +1 -1
- data/lib/ruby_scribe/ext/sexp.rb +1 -7
- data/lib/ruby_scribe/sexp_helpers.rb +285 -0
- data/lib/ruby_scribe/version.rb +1 -1
- data/lib/ruby_scribe.rb +2 -0
- data/spec/ruby_scribe/sexp_helpers_spec.rb +256 -0
- metadata +7 -17
- data/lib/ruby_scribe/transformer.rb +0 -18
- data/lib/ruby_scribe/transformer_helpers.rb +0 -7
- data/lib/ruby_scribe/transformers/block_method_to_procifier.rb +0 -43
- data/lib/ruby_scribe/transformers/custom.rb +0 -27
- data/lib/ruby_scribe/transformers/eachifier.rb +0 -39
- data/lib/ruby_scribe/transformers/symbol_names.rb +0 -68
- data/lib/ruby_scribe/transformers/tapifier.rb +0 -73
- data/spec/ruby_scribe/transformer_spec.rb +0 -27
- data/spec/ruby_scribe/transformers/block_method_to_procifier_spec.rb +0 -20
- data/spec/ruby_scribe/transformers/custom_spec.rb +0 -25
- data/spec/ruby_scribe/transformers/eachifier_spec.rb +0 -27
- data/spec/ruby_scribe/transformers/symbol_names_spec.rb +0 -44
- data/spec/ruby_scribe/transformers/tapifier_spec.rb +0 -57
@@ -1,27 +0,0 @@
|
|
1
|
-
module RubyScribe
|
2
|
-
module Transformers
|
3
|
-
|
4
|
-
# = Custom Transformer
|
5
|
-
# Allows for implementation of the transform to happen in-line through a block passed to the initializer.
|
6
|
-
#
|
7
|
-
# Example:
|
8
|
-
#
|
9
|
-
# # This contrived example reverses all string literals
|
10
|
-
# RubyScribe::Transformers::Custom.new do |expression|
|
11
|
-
# if sexp?(expression) && expression.kind == :str
|
12
|
-
# s(:str, expression.body[0].reverse)
|
13
|
-
# else
|
14
|
-
# super
|
15
|
-
# end
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
class Custom < RubyScribe::Transformer
|
19
|
-
def initialize(&block)
|
20
|
-
class_eval do
|
21
|
-
define_method(:transform, &block)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module RubyScribe
|
2
|
-
module Transformers
|
3
|
-
|
4
|
-
# = For to Each Block Transform
|
5
|
-
# Finds instances using "for something in collection"-style of iteration and converts
|
6
|
-
# it to using a standard collection.each block.
|
7
|
-
#
|
8
|
-
# Example:
|
9
|
-
#
|
10
|
-
# for element in collection
|
11
|
-
# do_something(element)
|
12
|
-
# end
|
13
|
-
#
|
14
|
-
# Converts To:
|
15
|
-
#
|
16
|
-
# collection.each do |element|
|
17
|
-
# do_something(element)
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
class Eachifier < Transformer
|
21
|
-
def transform(e)
|
22
|
-
if e.is_a?(Sexp) && e.kind == :for
|
23
|
-
super transform_for_to_each(e)
|
24
|
-
else
|
25
|
-
super
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def transform_for_to_each(e)
|
30
|
-
s(:iter,
|
31
|
-
s(:call, e.body[0], :each, s(:arglist)),
|
32
|
-
e.body[1],
|
33
|
-
e.body[2]
|
34
|
-
)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
module RubyScribe
|
2
|
-
module Transformers
|
3
|
-
|
4
|
-
# = Symbol Names
|
5
|
-
# Sometimes you'll come across code written by a Java developer who uses camel-cased names for variables and methods.
|
6
|
-
# This transformer will allow you to apply some transformation (defined through a block to initialize) to every symbol name
|
7
|
-
# in the application, which includes all of these:
|
8
|
-
# * Method Names (Definitions and Calls)
|
9
|
-
# * Local Variable Names
|
10
|
-
# * Instance Variable Names
|
11
|
-
# * Class Variable Names
|
12
|
-
#
|
13
|
-
# Big Caveat: This transformer does not detect instances where the symbol name is referenced inside an eval-ed string, for example
|
14
|
-
# when you are instance_evaling some large string. As always, run your tests after any transformation.
|
15
|
-
#
|
16
|
-
# Example:
|
17
|
-
#
|
18
|
-
# # Underscores symbol names
|
19
|
-
# RubyScribe::Transformers::SymbolNames.new {|name| name.underscore }
|
20
|
-
#
|
21
|
-
# # Given This:
|
22
|
-
# def myMethod
|
23
|
-
# myVariable = 1
|
24
|
-
# @iVar = myMethod(myVariable)
|
25
|
-
# end
|
26
|
-
#
|
27
|
-
# # Translates to This:
|
28
|
-
# def my_method
|
29
|
-
# my_variable = 1
|
30
|
-
# @i_var = my_method(my_variable)
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
# # Or maybe translate from English to French
|
34
|
-
# RubyScribe::Transformers::SymbolNames.new {|name| Google::Translate.new(:fr).translate(name) }
|
35
|
-
#
|
36
|
-
class SymbolNames < RubyScribe::Transformer
|
37
|
-
def initialize(&block)
|
38
|
-
@name_transformer = block
|
39
|
-
end
|
40
|
-
|
41
|
-
def transform(e)
|
42
|
-
super transform_symbols(e)
|
43
|
-
end
|
44
|
-
|
45
|
-
def transform_symbols(e)
|
46
|
-
return e unless sexp?(e)
|
47
|
-
|
48
|
-
case e.kind
|
49
|
-
when :defn
|
50
|
-
e.clone.tap {|c| c[1] = @name_transformer.call(c[1].to_s).to_sym }
|
51
|
-
when :defs
|
52
|
-
e.clone.tap {|c| c[2] = @name_transformer.call(c[2].to_s).to_sym }
|
53
|
-
when :call
|
54
|
-
e.clone.tap {|c| c[2] = @name_transformer.call(c[2].to_s).to_sym }
|
55
|
-
when :lasgn, :lvar
|
56
|
-
e.clone.tap {|c| c[1] = @name_transformer.call(c[1].to_s).to_sym }
|
57
|
-
when :cvdecl, :cvasgn, :cvar
|
58
|
-
e.clone.tap {|c| c[1] = ("@@" + @name_transformer.call(c[1].to_s.gsub(/^@@/, ''))).to_sym }
|
59
|
-
when :iasgn, :ivar
|
60
|
-
e.clone.tap {|c| c[1] = ("@" + @name_transformer.call(c[1].to_s.gsub(/^@/, ''))).to_sym }
|
61
|
-
else
|
62
|
-
e
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|
68
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
module RubyScribe
|
2
|
-
module Transformers
|
3
|
-
|
4
|
-
# = Method Temporary Variables to Tap Block
|
5
|
-
# Looks for instances of method declarations where:
|
6
|
-
# 1. A local variable is assigned to something as the first statement.
|
7
|
-
# 2. As the last statement, that local variable is returned is expressed.
|
8
|
-
#
|
9
|
-
# These instances of using "temporary variables" to construct something for returning can be more
|
10
|
-
# elegantly expressed by using the .tap idiom.
|
11
|
-
#
|
12
|
-
# Example:
|
13
|
-
#
|
14
|
-
# def my_method
|
15
|
-
# temp = ""
|
16
|
-
# temp << "Something"
|
17
|
-
# call_something(temp)
|
18
|
-
# temp
|
19
|
-
# end
|
20
|
-
#
|
21
|
-
# Converts To:
|
22
|
-
#
|
23
|
-
# def my_method
|
24
|
-
# "".tap do |temp|
|
25
|
-
# temp << "Something"
|
26
|
-
# call_something(temp)
|
27
|
-
# end
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
class Tapifier < Transformer
|
31
|
-
def transform(e)
|
32
|
-
if matches_method_to_use_tap?(e)
|
33
|
-
super transform_method_to_use_tap(e)
|
34
|
-
else
|
35
|
-
super
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def matches_method_to_use_tap?(e)
|
40
|
-
e.is_a?(Sexp) && [:defn, :defs].include?(e.kind) &&
|
41
|
-
matches_block_to_use_tap?(e.body[2])
|
42
|
-
end
|
43
|
-
|
44
|
-
def matches_block_to_use_tap?(e)
|
45
|
-
return matches_block_to_use_tap?(e.body[0]) if e.body.size == 1 && e.body[0].kind == :block
|
46
|
-
|
47
|
-
e.is_a?(Sexp) && e.kind == :block && # Some block (or method body)
|
48
|
-
e.body[0].kind == :lasgn && # The first line assigns to a local variable
|
49
|
-
expresses_local_variable?(e.body[-1], e.body[0].body[0])
|
50
|
-
end
|
51
|
-
|
52
|
-
def expresses_local_variable?(e, local_variable)
|
53
|
-
(e.kind == :lvar && e.body[0] == local_variable) ||
|
54
|
-
(e.kind == :return && expresses_local_variable?(e.body[0], local_variable))
|
55
|
-
end
|
56
|
-
|
57
|
-
def transform_method_to_use_tap(e)
|
58
|
-
s(e.kind, e.body[0], e.body[1], transform_block_to_use_tap(e.body[2]))
|
59
|
-
end
|
60
|
-
|
61
|
-
def transform_block_to_use_tap(e)
|
62
|
-
return s(:scope, transform_block_to_use_tap(e.body[0])) if e.body.size == 1 && e.kind == :scope && e.body[0].kind == :block
|
63
|
-
|
64
|
-
s(:block, s(:iter,
|
65
|
-
s(:call, e.body[0].body[1], :tap, s(:arglist)),
|
66
|
-
s(:lasgn, e.body[0].body[0]),
|
67
|
-
s(*([:block] + e.body[1..-2]))
|
68
|
-
))
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe RubyScribe::Transformer.new do
|
4
|
-
|
5
|
-
describe "a for block" do
|
6
|
-
subject { %{
|
7
|
-
def my_method
|
8
|
-
call_something
|
9
|
-
|
10
|
-
for element in array
|
11
|
-
do_something(element)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
}}
|
15
|
-
|
16
|
-
it { should transform_to("the same", %{
|
17
|
-
def my_method
|
18
|
-
call_something
|
19
|
-
|
20
|
-
for element in array
|
21
|
-
do_something(element)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
}) }
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe RubyScribe::Transformers::BlockMethodToProcifier.new do
|
4
|
-
|
5
|
-
describe "a block call with method invocation" do
|
6
|
-
subject { %{collection.map {|d| d.name }}}
|
7
|
-
it { should transform_to("use Symbol#to_proc", %{collection.map(&:name)}) }
|
8
|
-
end
|
9
|
-
|
10
|
-
describe "a block call with chained method invocation" do
|
11
|
-
subject { %{collection.map {|d| d.name.first }}}
|
12
|
-
it { should transform_to("itself", subject) }
|
13
|
-
end
|
14
|
-
|
15
|
-
describe "a multiple-argument block call with method invocation" do
|
16
|
-
subject { %{collection.map {|d, i| d.name + i }}}
|
17
|
-
it { should transform_to("itself", subject) }
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
CustomTransformer = RubyScribe::Transformers::Custom.new do |expression|
|
4
|
-
if sexp?(expression) && expression.kind == :str
|
5
|
-
s(:str, expression.body[0].reverse)
|
6
|
-
else
|
7
|
-
super
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
describe CustomTransformer do
|
12
|
-
|
13
|
-
describe "some strings" do
|
14
|
-
subject { %{
|
15
|
-
s = "one"
|
16
|
-
t = "two"
|
17
|
-
}}
|
18
|
-
|
19
|
-
it { should transform_to("reverse", %{
|
20
|
-
s = "eno"
|
21
|
-
t = "owt"
|
22
|
-
}) }
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe RubyScribe::Transformers::Eachifier.new do
|
4
|
-
|
5
|
-
describe "a for block" do
|
6
|
-
subject { %{
|
7
|
-
def my_method
|
8
|
-
call_something
|
9
|
-
|
10
|
-
for element in array
|
11
|
-
do_something(element)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
}}
|
15
|
-
|
16
|
-
it { should transform_to("each", %{
|
17
|
-
def my_method
|
18
|
-
call_something
|
19
|
-
|
20
|
-
array.each do |element|
|
21
|
-
do_something(element)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
}) }
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
SymbolUnderscorer = RubyScribe::Transformers::SymbolNames.new do |name|
|
4
|
-
name.underscore
|
5
|
-
end
|
6
|
-
|
7
|
-
describe SymbolUnderscorer do
|
8
|
-
|
9
|
-
describe "method definition" do
|
10
|
-
subject { %{def myMethod; end; def self.anotherMethod; end} }
|
11
|
-
it { should transform_to("underscored", %{def my_method; end; def self.another_method; end}) }
|
12
|
-
end
|
13
|
-
|
14
|
-
describe "method call" do
|
15
|
-
subject { %{myMethod.doSomething} }
|
16
|
-
it { should transform_to("underscored", %{my_method.do_something}) }
|
17
|
-
end
|
18
|
-
|
19
|
-
describe "method arguments" do
|
20
|
-
subject { %{my(argOne, argTwo)} }
|
21
|
-
it { should transform_to("underscored", %{my(arg_one, arg_two)}) }
|
22
|
-
end
|
23
|
-
|
24
|
-
describe "block arguments" do
|
25
|
-
subject { %{collection.each {|argOne, argTwo| something }} }
|
26
|
-
it { should transform_to("underscored", %{collection.each {|arg_one, arg_two| something }}) }
|
27
|
-
end
|
28
|
-
|
29
|
-
describe "local variable" do
|
30
|
-
subject { %{def my; myVariable = 1; myVariable; end} }
|
31
|
-
it { should transform_to("underscored", %{def my; my_variable = 1; my_variable; end}) }
|
32
|
-
end
|
33
|
-
|
34
|
-
describe "instance variable" do
|
35
|
-
subject { %{@myVariable = 1; @myVariable} }
|
36
|
-
it { should transform_to("underscored", %{@my_variable = 1; @my_variable}) }
|
37
|
-
end
|
38
|
-
|
39
|
-
describe "class variable" do
|
40
|
-
subject { %{@@myVariable = 1; @@myVariable; def my; @@myVariable = 1; end} }
|
41
|
-
it { should transform_to("underscored", %{@@my_variable = 1; @@my_variable; def my; @@my_variable = 1; end}) }
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RubyScribe::Transformers::Tapifier.new do
|
4
|
-
|
5
|
-
describe "a method setting up and returning a temporary variable" do
|
6
|
-
subject {%{
|
7
|
-
def my_method
|
8
|
-
temp = ""
|
9
|
-
temp << "Something"
|
10
|
-
call_something(temp)
|
11
|
-
temp
|
12
|
-
end
|
13
|
-
}}
|
14
|
-
|
15
|
-
it { should transform_to("wrap in #tap", %{
|
16
|
-
def my_method
|
17
|
-
"".tap do |temp|
|
18
|
-
temp << "Something"
|
19
|
-
call_something(temp)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
}) }
|
23
|
-
end
|
24
|
-
|
25
|
-
describe "a method setting up and explicitly returning a temporary variable" do
|
26
|
-
subject {%{
|
27
|
-
def my_method
|
28
|
-
temp = ""
|
29
|
-
temp << "Something"
|
30
|
-
call_something(temp)
|
31
|
-
return temp
|
32
|
-
end
|
33
|
-
}}
|
34
|
-
|
35
|
-
it { should transform_to("wrap in #tap", %{
|
36
|
-
def my_method
|
37
|
-
"".tap do |temp|
|
38
|
-
temp << "Something"
|
39
|
-
call_something(temp)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
}) }
|
43
|
-
end
|
44
|
-
|
45
|
-
describe "a method setting up and not returning a temporary variable" do
|
46
|
-
subject {%{
|
47
|
-
def my_method
|
48
|
-
temp = ""
|
49
|
-
temp << "Something"
|
50
|
-
call_something(temp)
|
51
|
-
end
|
52
|
-
}}
|
53
|
-
|
54
|
-
it { should transform_to("itself", subject) }
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|