reflexive 0.0.3 → 0.0.4
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/Gemfile +16 -0
- data/Rakefile +31 -0
- data/config.ru +3 -0
- data/reflexive.gemspec +1 -1
- data/spec/coderay_html_encoder_spec.rb +57 -0
- data/spec/coderay_ruby_scanner_spec.rb +194 -0
- data/spec/io_interceptor.rb +64 -0
- data/spec/method_lookup_spec.rb +0 -0
- data/spec/methods_spec.rb +202 -0
- data/spec/rails_integration_spec.rb +139 -0
- data/spec/rails_integration_spec_helper.rb +115 -0
- data/spec/reflexive_ripper_spec.rb +351 -0
- data/spec/reflexive_spec.rb +98 -0
- data/spec/ripper_events_recorder.rb +50 -0
- data/spec/ripper_spec.rb +758 -0
- data/spec/sexp_builder_with_scanner_events.rb +39 -0
- data/spec/shell_out.rb +417 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/test_apps/rails2_test_app/README +243 -0
- data/spec/test_apps/rails2_test_app/Rakefile +10 -0
- data/spec/test_apps/rails2_test_app/app/controllers/application_controller.rb +10 -0
- data/spec/test_apps/rails2_test_app/app/controllers/posts_controller.rb +85 -0
- data/spec/test_apps/rails2_test_app/app/helpers/application_helper.rb +3 -0
- data/spec/test_apps/rails2_test_app/app/helpers/posts_helper.rb +2 -0
- data/spec/test_apps/rails2_test_app/app/models/post.rb +5 -0
- data/spec/test_apps/rails2_test_app/app/views/layouts/posts.html.erb +17 -0
- data/spec/test_apps/rails2_test_app/app/views/posts/edit.html.erb +12 -0
- data/spec/test_apps/rails2_test_app/app/views/posts/index.html.erb +18 -0
- data/spec/test_apps/rails2_test_app/app/views/posts/new.html.erb +11 -0
- data/spec/test_apps/rails2_test_app/app/views/posts/show.html.erb +3 -0
- data/spec/test_apps/rails2_test_app/config/boot.rb +110 -0
- data/spec/test_apps/rails2_test_app/config/database.yml +22 -0
- data/spec/test_apps/rails2_test_app/config/environment.rb +43 -0
- data/spec/test_apps/rails2_test_app/config/environments/development.rb +17 -0
- data/spec/test_apps/rails2_test_app/config/environments/production.rb +28 -0
- data/spec/test_apps/rails2_test_app/config/environments/test.rb +28 -0
- data/spec/test_apps/rails2_test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/test_apps/rails2_test_app/config/initializers/inflections.rb +10 -0
- data/spec/test_apps/rails2_test_app/config/initializers/mime_types.rb +5 -0
- data/spec/test_apps/rails2_test_app/config/initializers/new_rails_defaults.rb +21 -0
- data/spec/test_apps/rails2_test_app/config/initializers/session_store.rb +15 -0
- data/spec/test_apps/rails2_test_app/config/locales/en.yml +5 -0
- data/spec/test_apps/rails2_test_app/config/routes.rb +45 -0
- data/spec/test_apps/rails2_test_app/db/development.sqlite3 +0 -0
- data/spec/test_apps/rails2_test_app/db/migrate/20100512073155_create_posts.rb +12 -0
- data/spec/test_apps/rails2_test_app/db/schema.rb +19 -0
- data/spec/test_apps/rails2_test_app/db/seeds.rb +7 -0
- data/spec/test_apps/rails2_test_app/doc/README_FOR_APP +2 -0
- data/spec/test_apps/rails2_test_app/log/development.log +251 -0
- data/spec/test_apps/rails2_test_app/log/production.log +0 -0
- data/spec/test_apps/rails2_test_app/log/server.log +0 -0
- data/spec/test_apps/rails2_test_app/log/test.log +0 -0
- data/spec/test_apps/rails2_test_app/public/404.html +30 -0
- data/spec/test_apps/rails2_test_app/public/422.html +30 -0
- data/spec/test_apps/rails2_test_app/public/500.html +30 -0
- data/spec/test_apps/rails2_test_app/public/favicon.ico +0 -0
- data/spec/test_apps/rails2_test_app/public/images/rails.png +0 -0
- data/spec/test_apps/rails2_test_app/public/index.html +275 -0
- data/spec/test_apps/rails2_test_app/public/javascripts/application.js +2 -0
- data/spec/test_apps/rails2_test_app/public/javascripts/controls.js +963 -0
- data/spec/test_apps/rails2_test_app/public/javascripts/dragdrop.js +973 -0
- data/spec/test_apps/rails2_test_app/public/javascripts/effects.js +1128 -0
- data/spec/test_apps/rails2_test_app/public/javascripts/prototype.js +4320 -0
- data/spec/test_apps/rails2_test_app/public/robots.txt +5 -0
- data/spec/test_apps/rails2_test_app/public/stylesheets/1.css +0 -0
- data/spec/test_apps/rails2_test_app/public/stylesheets/scaffold.css +54 -0
- data/spec/test_apps/rails2_test_app/script/about +4 -0
- data/spec/test_apps/rails2_test_app/script/console +3 -0
- data/spec/test_apps/rails2_test_app/script/dbconsole +3 -0
- data/spec/test_apps/rails2_test_app/script/destroy +3 -0
- data/spec/test_apps/rails2_test_app/script/generate +3 -0
- data/spec/test_apps/rails2_test_app/script/performance/benchmarker +3 -0
- data/spec/test_apps/rails2_test_app/script/performance/profiler +3 -0
- data/spec/test_apps/rails2_test_app/script/plugin +3 -0
- data/spec/test_apps/rails2_test_app/script/runner +3 -0
- data/spec/test_apps/rails2_test_app/script/server +3 -0
- data/spec/test_apps/rails2_test_app/test/fixtures/posts.yml +7 -0
- data/spec/test_apps/rails2_test_app/test/functional/posts_controller_test.rb +45 -0
- data/spec/test_apps/rails2_test_app/test/performance/browsing_test.rb +9 -0
- data/spec/test_apps/rails2_test_app/test/test_helper.rb +38 -0
- data/spec/test_apps/rails2_test_app/test/unit/helpers/posts_helper_test.rb +4 -0
- data/spec/test_apps/rails2_test_app/test/unit/post_test.rb +8 -0
- data/spec/test_apps/rails3_test_app/Gemfile +28 -0
- data/spec/test_apps/rails3_test_app/README +244 -0
- data/spec/test_apps/rails3_test_app/Rakefile +10 -0
- data/spec/test_apps/rails3_test_app/app/controllers/application_controller.rb +4 -0
- data/spec/test_apps/rails3_test_app/app/controllers/posts_controller.rb +83 -0
- data/spec/test_apps/rails3_test_app/app/helpers/application_helper.rb +2 -0
- data/spec/test_apps/rails3_test_app/app/helpers/posts_helper.rb +2 -0
- data/spec/test_apps/rails3_test_app/app/models/post.rb +2 -0
- data/spec/test_apps/rails3_test_app/app/views/layouts/application.html.erb +14 -0
- data/spec/test_apps/rails3_test_app/app/views/posts/_form.html.erb +16 -0
- data/spec/test_apps/rails3_test_app/app/views/posts/edit.html.erb +6 -0
- data/spec/test_apps/rails3_test_app/app/views/posts/index.html.erb +21 -0
- data/spec/test_apps/rails3_test_app/app/views/posts/new.html.erb +5 -0
- data/spec/test_apps/rails3_test_app/app/views/posts/show.html.erb +5 -0
- data/spec/test_apps/rails3_test_app/config/application.rb +49 -0
- data/spec/test_apps/rails3_test_app/config/boot.rb +6 -0
- data/spec/test_apps/rails3_test_app/config/database.yml +22 -0
- data/spec/test_apps/rails3_test_app/config/environment.rb +5 -0
- data/spec/test_apps/rails3_test_app/config/environments/development.rb +19 -0
- data/spec/test_apps/rails3_test_app/config/environments/production.rb +42 -0
- data/spec/test_apps/rails3_test_app/config/environments/test.rb +32 -0
- data/spec/test_apps/rails3_test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/test_apps/rails3_test_app/config/initializers/inflections.rb +10 -0
- data/spec/test_apps/rails3_test_app/config/initializers/mime_types.rb +5 -0
- data/spec/test_apps/rails3_test_app/config/initializers/secret_token.rb +7 -0
- data/spec/test_apps/rails3_test_app/config/initializers/session_store.rb +8 -0
- data/spec/test_apps/rails3_test_app/config/locales/en.yml +5 -0
- data/spec/test_apps/rails3_test_app/config/routes.rb +60 -0
- data/spec/test_apps/rails3_test_app/config.ru +4 -0
- data/spec/test_apps/rails3_test_app/db/development.sqlite3 +0 -0
- data/spec/test_apps/rails3_test_app/db/migrate/20100512075428_create_posts.rb +12 -0
- data/spec/test_apps/rails3_test_app/db/schema.rb +19 -0
- data/spec/test_apps/rails3_test_app/db/seeds.rb +7 -0
- data/spec/test_apps/rails3_test_app/doc/README_FOR_APP +2 -0
- data/spec/test_apps/rails3_test_app/log/development.log +349 -0
- data/spec/test_apps/rails3_test_app/log/production.log +0 -0
- data/spec/test_apps/rails3_test_app/log/server.log +0 -0
- data/spec/test_apps/rails3_test_app/log/test.log +0 -0
- data/spec/test_apps/rails3_test_app/public/404.html +26 -0
- data/spec/test_apps/rails3_test_app/public/422.html +26 -0
- data/spec/test_apps/rails3_test_app/public/500.html +26 -0
- data/spec/test_apps/rails3_test_app/public/favicon.ico +0 -0
- data/spec/test_apps/rails3_test_app/public/images/rails.png +0 -0
- data/spec/test_apps/rails3_test_app/public/index.html +279 -0
- data/spec/test_apps/rails3_test_app/public/javascripts/application.js +2 -0
- data/spec/test_apps/rails3_test_app/public/javascripts/controls.js +965 -0
- data/spec/test_apps/rails3_test_app/public/javascripts/dragdrop.js +974 -0
- data/spec/test_apps/rails3_test_app/public/javascripts/effects.js +1123 -0
- data/spec/test_apps/rails3_test_app/public/javascripts/prototype.js +4874 -0
- data/spec/test_apps/rails3_test_app/public/javascripts/rails.js +118 -0
- data/spec/test_apps/rails3_test_app/public/robots.txt +5 -0
- data/spec/test_apps/rails3_test_app/public/stylesheets/scaffold.css +60 -0
- data/spec/test_apps/rails3_test_app/script/rails +9 -0
- data/spec/test_apps/rails3_test_app/test/fixtures/posts.yml +11 -0
- data/spec/test_apps/rails3_test_app/test/functional/posts_controller_test.rb +49 -0
- data/spec/test_apps/rails3_test_app/test/performance/browsing_test.rb +9 -0
- data/spec/test_apps/rails3_test_app/test/test_helper.rb +13 -0
- data/spec/test_apps/rails3_test_app/test/unit/helpers/posts_helper_test.rb +4 -0
- data/spec/test_apps/rails3_test_app/test/unit/post_test.rb +8 -0
- metadata +142 -2
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
require "open-uri"
|
|
3
|
+
|
|
4
|
+
require "reflexive"
|
|
5
|
+
|
|
6
|
+
require File.expand_path("../rails_integration_spec_helper", __FILE__)
|
|
7
|
+
|
|
8
|
+
shared_examples_for "fresh Rails app with Reflexive installed" do
|
|
9
|
+
it "responds on localhost" do
|
|
10
|
+
get("/").should include("Welcome aboard")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "responds for Reflexive paths" do
|
|
14
|
+
constant_reflexion = get("/reflexive/constants/ActiveRecord::Base")
|
|
15
|
+
constant_reflexion.should include("ActiveRecord")
|
|
16
|
+
constant_reflexion.should include("Object")
|
|
17
|
+
constant_reflexion.should include("Class")
|
|
18
|
+
constant_reflexion.should include("Module")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "Integration with" do
|
|
23
|
+
describe "Rails 2.x" do
|
|
24
|
+
before(:all) do
|
|
25
|
+
bootstrap_gem_environment("rails", "2.3.5")
|
|
26
|
+
build_and_install_test_gem
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "installs proper version of Rails" do
|
|
30
|
+
sh_in_tmp_gemset("rails -v", :out => :return).should include("Rails 2")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "installs test Reflexive gem" do
|
|
34
|
+
sh_in_tmp_gemset("gem list", :out => :return).should include("reflexive")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe "creates Rails application" do
|
|
38
|
+
before(:all) do
|
|
39
|
+
create_rails_app("2")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "which has config/environment.rb file" do
|
|
43
|
+
Dir.chdir($app_dir) do
|
|
44
|
+
File.exist?("config/environment.rb")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe "and installs Reflexive gem into it" do
|
|
49
|
+
before(:all) do
|
|
50
|
+
patch_app_file("config/environment.rb",
|
|
51
|
+
"Rails::Initializer.run do |config|",
|
|
52
|
+
<<-RUBY)
|
|
53
|
+
Rails::Initializer.run do |config|
|
|
54
|
+
config.gem "reflexive"
|
|
55
|
+
config.middleware.insert_after("Rack::Lock", "Reflexive::Application")
|
|
56
|
+
RUBY
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "properly" do
|
|
60
|
+
Dir.chdir($app_dir) do
|
|
61
|
+
IO.read("config/environment.rb").should include("Reflexive")
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
describe "and runs application" do
|
|
66
|
+
before(:all) do
|
|
67
|
+
Dir.chdir($app_dir) do
|
|
68
|
+
spawn_server_and_wait_for_response("ruby script/server")
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it_should_behave_like "fresh Rails app with Reflexive installed"
|
|
73
|
+
|
|
74
|
+
after(:all) do
|
|
75
|
+
terminate_server_blocking
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
describe "Rails 3.x" do
|
|
83
|
+
before(:all) do
|
|
84
|
+
bootstrap_gem_environment("rails", "3.0.0.beta3")
|
|
85
|
+
build_and_install_test_gem
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "installs proper version of Rails" do
|
|
89
|
+
sh_in_tmp_gemset("rails -v", :out => :return).should include("Rails 3")
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "installs test Reflexive gem" do
|
|
93
|
+
sh_in_tmp_gemset("gem list", :out => :return).should include("reflexive")
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
describe "creates Rails application" do
|
|
97
|
+
before(:all) do
|
|
98
|
+
create_rails_app("3")
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "which has config/application.rb file" do
|
|
102
|
+
Dir.chdir($app_dir) do
|
|
103
|
+
File.exist?("config/application.rb")
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
describe "and installs Reflexive gem into it" do
|
|
108
|
+
before(:all) do
|
|
109
|
+
patch_app_file("config/application.rb",
|
|
110
|
+
"class Application < Rails::Application",
|
|
111
|
+
<<-RUBY)
|
|
112
|
+
class Application < Rails::Application
|
|
113
|
+
config.middleware.insert_after("Rack::Lock", "Reflexive::Application")
|
|
114
|
+
RUBY
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "properly" do
|
|
118
|
+
Dir.chdir($app_dir) do
|
|
119
|
+
IO.read("config/application.rb").should include("Reflexive")
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
describe "and runs application" do
|
|
124
|
+
before(:all) do
|
|
125
|
+
Dir.chdir($app_dir) do
|
|
126
|
+
spawn_server_and_wait_for_response("rails server")
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it_should_behave_like "fresh Rails app with Reflexive installed"
|
|
131
|
+
|
|
132
|
+
after(:all) do
|
|
133
|
+
terminate_server_blocking
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
require "reflexive"
|
|
3
|
+
require "open-uri"
|
|
4
|
+
|
|
5
|
+
def sh(*args)
|
|
6
|
+
require File.expand_path("../shell_out", __FILE__)
|
|
7
|
+
shell_out_args = args.dup
|
|
8
|
+
options = shell_out_args.pop if shell_out_args[-1].is_a?(Hash)
|
|
9
|
+
shell_out_args << { :raise_exceptions => true,
|
|
10
|
+
:verbose => true }.merge(options || {})
|
|
11
|
+
ShellOut(*shell_out_args)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def tmp_gemset_env
|
|
15
|
+
{ "GEM_HOME" => $tmp_gemdir,
|
|
16
|
+
"GEM_PATH" => $tmp_gemdir }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def sh_in_tmp_gemset(cmd, options = {})
|
|
20
|
+
sh(tmp_gemset_env, cmd, options)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
$purge_at_exit = []
|
|
24
|
+
|
|
25
|
+
at_exit do
|
|
26
|
+
for dir in $purge_at_exit
|
|
27
|
+
FileUtils::Verbose.rm_rf(dir)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def mktmpdir(prefix)
|
|
32
|
+
tmp_dir = Dir.mktmpdir
|
|
33
|
+
$purge_at_exit << tmp_dir.dup
|
|
34
|
+
tmp_dir
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def gem_repository_option
|
|
38
|
+
gem_repository_path = File.expand_path("../../tmp/gem_repository", __FILE__)
|
|
39
|
+
|
|
40
|
+
if File.directory?(gem_repository_path)
|
|
41
|
+
"--source file://#{ gem_repository_path }"
|
|
42
|
+
else
|
|
43
|
+
""
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def bootstrap_gem_environment(*args)
|
|
48
|
+
$tmp_gemdir = mktmpdir("reflexive_test_gemset")
|
|
49
|
+
while name = args.shift
|
|
50
|
+
version = args.shift
|
|
51
|
+
sh_in_tmp_gemset "gem install #{ name } --version='#{ version }' " <<
|
|
52
|
+
"--no-update-sources --quiet #{ gem_repository_option }"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def make_tmp_gemset_name
|
|
57
|
+
t = Time.now.strftime("%Y%m%d")
|
|
58
|
+
"reflexive_test_gemset_#{t}_#{$$}_#{rand(0x100000000).to_s(36)}"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def build_and_install_test_gem
|
|
62
|
+
Dir.chdir(File.expand_path("../../", __FILE__)) do
|
|
63
|
+
sh({ "GEM_VERSION" => "9.9.9" }, "gem build reflexive.gemspec")
|
|
64
|
+
begin
|
|
65
|
+
sh_in_tmp_gemset("gem install reflexive-9.9.9.gem --quiet")
|
|
66
|
+
ensure
|
|
67
|
+
File.delete("reflexive-9.9.9.gem")
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def spawn_server_and_wait_for_response(cmd)
|
|
73
|
+
$server_pid = spawn(tmp_gemset_env, cmd)
|
|
74
|
+
puts "Spawned server with #{ $server_pid } PID"
|
|
75
|
+
tries = 0
|
|
76
|
+
print "Waiting for server to start..."
|
|
77
|
+
started = false
|
|
78
|
+
while (tries += 1) < 10 && !started
|
|
79
|
+
started = get("/").include?("Welcome aboard") rescue false
|
|
80
|
+
print "."
|
|
81
|
+
sleep 1
|
|
82
|
+
end
|
|
83
|
+
print "\n"
|
|
84
|
+
abort "Failed to start server" unless started
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def terminate_server_blocking
|
|
88
|
+
puts "Terminating server with #{ $server_pid } PID..."
|
|
89
|
+
`kill -9 #{ $server_pid }`
|
|
90
|
+
Process::waitpid2($server_pid)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def get(path)
|
|
94
|
+
open("http://localhost:3000#{ path }").read
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def create_rails_app(version)
|
|
98
|
+
unless $tmp_dir # one dir is enough
|
|
99
|
+
$tmp_dir = mktmpdir("reflexive_test_rails_apps")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
$app_dir = File.join($tmp_dir, "reflexive_test_rails#{ version }_app")
|
|
103
|
+
|
|
104
|
+
Dir.chdir($tmp_dir) do
|
|
105
|
+
sh_in_tmp_gemset("rails reflexive_test_rails#{ version }_app")
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def patch_app_file(path, pattern, replacement)
|
|
110
|
+
Dir.chdir($app_dir) do
|
|
111
|
+
contents = IO.read(path)
|
|
112
|
+
contents.sub!(pattern, replacement)
|
|
113
|
+
File.open(path, "w") { |f| f.write(contents) }
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
require "reflexive/reflexive_ripper"
|
|
2
|
+
|
|
3
|
+
Rspec::Matchers.define :have_scopes do |*expected_scopes|
|
|
4
|
+
match do |actual_scanner_events|
|
|
5
|
+
@actual_scopes = actual_scanner_events.
|
|
6
|
+
map { |e| e[:meta_scope] }.compact
|
|
7
|
+
@actual_scopes == expected_scopes
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
failure_message_for_should do |actual_scanner_events|
|
|
11
|
+
"expected that scanner events: #{ actual_scanner_events } \n" <<
|
|
12
|
+
"(with scopes: #{ @actual_scopes }) \n" <<
|
|
13
|
+
"would have following scopes: #{ expected_scopes[0] }"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
Rspec::Matchers.define :have_tags do |*expected_tags|
|
|
18
|
+
match do |actual_scanner_events|
|
|
19
|
+
@actual_tags = actual_scanner_events.map { |e| e[:tags] }.compact
|
|
20
|
+
(expected_tags - @actual_tags).empty?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
failure_message_for_should do |actual_scanner_events|
|
|
24
|
+
"expected that scanner events: #{ actual_scanner_events } \n" <<
|
|
25
|
+
"(with tags: #{ @actual_tags }) \n" <<
|
|
26
|
+
"would have following tags: #{ expected_tags }"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
Rspec::Matchers.define :have_exact_tags do |*expected_tags|
|
|
31
|
+
match do |actual_scanner_events|
|
|
32
|
+
@actual_tags = actual_scanner_events.map { |e| e[:tags] }.compact
|
|
33
|
+
expected_tags == @actual_tags
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
failure_message_for_should do |actual_scanner_events|
|
|
37
|
+
"expected that scanner events: #{ actual_scanner_events } \n" <<
|
|
38
|
+
"(with tags: #{ @actual_tags }) \n" <<
|
|
39
|
+
"would have exact tags: #{ expected_tags[0] }"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe Reflexive::ReflexiveRipper do
|
|
44
|
+
def scanner_events_for(source)
|
|
45
|
+
parser = Reflexive::ReflexiveRipper.new(source)
|
|
46
|
+
parser.parse
|
|
47
|
+
parser.scanner_events
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "collects scanner events as hashes" do
|
|
51
|
+
scanner_events_for("a = 42").should == [
|
|
52
|
+
{:ident=>"a", :tags=>{:local_variable_assignment=>"1:a"}},
|
|
53
|
+
{:sp=>" "}, {:op=>"="}, {:sp=>" "}, {:int=>"42"}
|
|
54
|
+
]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe "injects method call scanner event tags" do
|
|
58
|
+
specify "m!" do
|
|
59
|
+
scanner_events_for("m!").should(have_tags(
|
|
60
|
+
{:method_call=>{:name=>"m!", :receiver=>[], :scope => []}}
|
|
61
|
+
))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
specify "A.b!()" do
|
|
65
|
+
scanner_events_for("A.b!").should(have_tags(
|
|
66
|
+
{:method_call=>{:name=>"b!", :receiver=>["A"], :scope => []}}
|
|
67
|
+
))
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
specify "A::B.c!()" do
|
|
71
|
+
scanner_events_for("A::B.c!()").should(have_tags(
|
|
72
|
+
{:method_call=>{:name=>"c!", :receiver=>["A::B"], :scope => []}}
|
|
73
|
+
))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
specify "module A; B.c!(); end" do
|
|
77
|
+
scanner_events_for("module A; B.c!(); end").should(have_tags(
|
|
78
|
+
{:method_call=>{:name=>"c!", :receiver=>["B"], :scope => ["A"]}}
|
|
79
|
+
))
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
describe "injects local variable assignment event tags" do
|
|
84
|
+
specify "v = 1" do
|
|
85
|
+
scanner_events_for("a = 42").should(have_tags(
|
|
86
|
+
:local_variable_assignment=>"1:a"))
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
specify "def m(arg) end" do
|
|
90
|
+
scanner_events_for("def m(arg); end").should(have_tags(
|
|
91
|
+
:local_variable_assignment=>"2:arg"))
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
specify "a, b = 1, 2" do
|
|
95
|
+
scanner_events_for("a, b = 1, 2").should(have_tags(
|
|
96
|
+
{:local_variable_assignment=>"1:a"},
|
|
97
|
+
{:local_variable_assignment=>"1:b"}))
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
specify "a, b, *c, d = 1, 2" do
|
|
101
|
+
scanner_events_for("a, b, *c, d = 1, 2").should(have_tags(
|
|
102
|
+
{:local_variable_assignment=>"1:a"},
|
|
103
|
+
{:local_variable_assignment=>"1:b"},
|
|
104
|
+
{:local_variable_assignment=>"1:c"},
|
|
105
|
+
{:local_variable_assignment=>"1:d"}
|
|
106
|
+
))
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
specify "1.tap { (dv = 1).tap { puts dv } }" do
|
|
110
|
+
scanner_events_for("1.tap { (dv = 1).tap { puts dv } }").should(have_exact_tags(
|
|
111
|
+
{:local_variable_assignment=>"2:dv"},
|
|
112
|
+
{:method_call=>{:name=>"puts", :receiver=>[], :scope => []}},
|
|
113
|
+
{:local_variable_access=>"2:dv"}
|
|
114
|
+
))
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
specify "1.tap { x = 1; 1.tap { puts x } }" do
|
|
118
|
+
scanner_events_for("1.tap { x = 1; 1.tap { puts x } }").should(have_tags(
|
|
119
|
+
{:local_variable_assignment=>"2:x"},
|
|
120
|
+
{:local_variable_assignment=>"2:x"}))
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
specify "tv = 1; def m; puts tv; end" do
|
|
124
|
+
scanner_events_for("tv = 1; def m; puts tv; end").should(have_tags(
|
|
125
|
+
{:local_variable_assignment=>"1:tv"},
|
|
126
|
+
{:method_call=>{:name=>"puts", :receiver=>[:instance], :scope => []}},
|
|
127
|
+
{:method_call=>{:name=>"tv", :receiver=>[:instance], :scope => []}}))
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
describe "scope handling" do
|
|
133
|
+
describe "for method calls" do
|
|
134
|
+
specify "from top level" do
|
|
135
|
+
scanner_events_for("m()").should(have_tags(
|
|
136
|
+
{:method_call=>{:name=>"m", :receiver=>[], :scope => []}}))
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
specify "class definition level" do
|
|
140
|
+
scanner_events_for("class C; cm(); end").should(have_tags(
|
|
141
|
+
{:method_call=>{:name=>"cm", :receiver=>["C"], :scope => ["C"]}}))
|
|
142
|
+
scanner_events_for("module M; cm(); end").should(have_tags(
|
|
143
|
+
{:method_call=>{:name=>"cm", :receiver=>["M"], :scope => ["M"]}}))
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
specify "class instance level" do
|
|
147
|
+
scanner_events_for("class C; def im1; im2; end end").should(have_tags(
|
|
148
|
+
{:method_call=>{:name=>"im2", :receiver=>["C", :instance], :scope => ["C"]}}))
|
|
149
|
+
scanner_events_for("module M; def im1; im2; end end").should(have_tags(
|
|
150
|
+
{:method_call=>{:name=>"im2", :receiver=>["M", :instance], :scope => ["M"]}}))
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
specify "class singleton level" do
|
|
154
|
+
scanner_events_for("class C; def self.cm1() cm2; end end").should(have_tags(
|
|
155
|
+
{:method_call=>{:name=>"cm2", :receiver=>["C"], :scope => ["C"]}}))
|
|
156
|
+
scanner_events_for("module M; def self.cm1() cm2; end end").should(have_tags(
|
|
157
|
+
{:method_call=>{:name=>"cm2", :receiver=>["M"], :scope => ["M"]}}))
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
pending "nested method calls with constant references" do
|
|
161
|
+
src = <<-RUBY
|
|
162
|
+
module M
|
|
163
|
+
class C
|
|
164
|
+
def self.m
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
class M::C
|
|
169
|
+
def m
|
|
170
|
+
c = C.m
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
RUBY
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
describe "for constant references" do
|
|
178
|
+
specify "top level" do
|
|
179
|
+
scanner_events_for("C").should(have_tags(
|
|
180
|
+
:constant_access=>{:name=>"C", :scope=>[]}
|
|
181
|
+
))
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
specify "path" do
|
|
185
|
+
scanner_events_for("A::B").should(have_tags(
|
|
186
|
+
{:constant_access=>{:name=>"A", :scope=>[]}},
|
|
187
|
+
{:constant_access=>{:name=>"A::B", :scope=>[]}}
|
|
188
|
+
))
|
|
189
|
+
scanner_events_for("A::B::C").should(have_tags(
|
|
190
|
+
{:constant_access=>{:name=>"A", :scope=>[]}},
|
|
191
|
+
{:constant_access=>{:name=>"A::B", :scope=>[]}},
|
|
192
|
+
{:constant_access=>{:name=>"A::B::C", :scope=>[]}}
|
|
193
|
+
))
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
specify "top path" do
|
|
197
|
+
scanner_events_for("::A::B").should(have_tags(
|
|
198
|
+
{:constant_access=>{:name=>"::A::B", :scope=>[]}}
|
|
199
|
+
))
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
specify "nested" do
|
|
203
|
+
scanner_events_for("module A; module B; C; end end").should(have_tags(
|
|
204
|
+
{:constant_access=>{:name=>"A", :scope=>[]}},
|
|
205
|
+
{:constant_access=>{:name=>"B", :scope=>["A"]}},
|
|
206
|
+
{:constant_access=>{:name=>"C", :scope=>["A", "B"]}}
|
|
207
|
+
))
|
|
208
|
+
scanner_events_for("module A; class B; C; end end").should(have_tags(
|
|
209
|
+
{:constant_access=>{:name=>"A", :scope=>[]}},
|
|
210
|
+
{:constant_access=>{:name=>"B", :scope=>["A"]}},
|
|
211
|
+
{:constant_access=>{:name=>"C", :scope=>["A", "B"]}}
|
|
212
|
+
))
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
specify "combined (nested with path)" do
|
|
216
|
+
scanner_events_for("module M; C::D; end").should(have_tags(
|
|
217
|
+
{:constant_access=>{:name=>"M", :scope=>[]}},
|
|
218
|
+
{:constant_access=>{:name=>"C", :scope=>["M"]}},
|
|
219
|
+
{:constant_access=>{:name=>"C::D", :scope=>["M"]}}
|
|
220
|
+
))
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
specify "combined (nested with top level)" do
|
|
224
|
+
scanner_events_for("module M; ::C::D; end").should(have_tags(
|
|
225
|
+
{:constant_access=>{:name=>"M", :scope=>[]}},
|
|
226
|
+
{:constant_access=>{:name=>"::C::D", :scope=>["M"]}}
|
|
227
|
+
))
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
specify "from instance methods" do
|
|
231
|
+
scanner_events_for("def m; C; end").should(have_tags(
|
|
232
|
+
{:constant_access=>{:name=>"C", :scope=>[]}}
|
|
233
|
+
))
|
|
234
|
+
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
describe "injects scope meta events" do
|
|
240
|
+
example "simple class def" do
|
|
241
|
+
scanner_events_for("class C; end").should(
|
|
242
|
+
have_scopes(["C"], []))
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
example "nested class def" do
|
|
246
|
+
scanner_events_for("class C; class D; end end").should(
|
|
247
|
+
have_scopes(["C"], ["C", "D"], ["C"], []))
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
example "class inside module def" do
|
|
251
|
+
scanner_events_for("module M; class C; end end").should(
|
|
252
|
+
have_scopes(["M"], ["M", "C"], ["M"], []))
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it "handles const_path_ref" do
|
|
256
|
+
scanner_events_for("class Const::PathRef < ::TopConstRef; end").should(
|
|
257
|
+
have_scopes(["Const::PathRef"], []))
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it "handles top_const_ref" do
|
|
261
|
+
scanner_events_for("class ::TopConstRef; end").should(
|
|
262
|
+
have_scopes(["::TopConstRef"], []))
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# describe "injects require/load argument tag" do
|
|
267
|
+
# specify "require" do
|
|
268
|
+
# scanner_events_for("require 'f'").should(have_tags(
|
|
269
|
+
# {:local_variable_assignment=>"1:tv"}
|
|
270
|
+
# ))
|
|
271
|
+
# end
|
|
272
|
+
# end
|
|
273
|
+
|
|
274
|
+
it "shouldn't get confused with non-scope changing const refs" do
|
|
275
|
+
scanner_events_for("v = :class; SomeConst = 123").should(
|
|
276
|
+
have_scopes())
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it "should handle complex arbitrary nesting" do
|
|
280
|
+
src = <<-RUBY
|
|
281
|
+
class TC
|
|
282
|
+
def m
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
module M1
|
|
287
|
+
def m
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
module M2
|
|
291
|
+
def m
|
|
292
|
+
end
|
|
293
|
+
class C1
|
|
294
|
+
|
|
295
|
+
end
|
|
296
|
+
class C1
|
|
297
|
+
def m
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
class C3
|
|
303
|
+
def m
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
module M1::M2
|
|
310
|
+
class C4
|
|
311
|
+
module M4
|
|
312
|
+
def m
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
class C5
|
|
317
|
+
module M3
|
|
318
|
+
end
|
|
319
|
+
class C6
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
RUBY
|
|
325
|
+
scanner_events_for(src).should(
|
|
326
|
+
have_scopes(["TC"],
|
|
327
|
+
[],
|
|
328
|
+
["M1"],
|
|
329
|
+
["M1", "M2"],
|
|
330
|
+
["M1", "M2", "C1"],
|
|
331
|
+
["M1", "M2"],
|
|
332
|
+
["M1", "M2", "C1"],
|
|
333
|
+
["M1", "M2"],
|
|
334
|
+
["M1"],
|
|
335
|
+
["M1", "C3"],
|
|
336
|
+
["M1"],
|
|
337
|
+
[],
|
|
338
|
+
["M1::M2"],
|
|
339
|
+
["M1::M2", "C4"],
|
|
340
|
+
["M1::M2", "C4", "M4"],
|
|
341
|
+
["M1::M2", "C4"],
|
|
342
|
+
["M1::M2", "C4", "C5"],
|
|
343
|
+
["M1::M2", "C4", "C5", "M3"],
|
|
344
|
+
["M1::M2", "C4", "C5"],
|
|
345
|
+
["M1::M2", "C4", "C5", "C6"],
|
|
346
|
+
["M1::M2", "C4", "C5"],
|
|
347
|
+
["M1::M2", "C4"],
|
|
348
|
+
["M1::M2"],
|
|
349
|
+
[]))
|
|
350
|
+
end
|
|
351
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require "reflexive/helpers"
|
|
2
|
+
require "reflexive/constantize"
|
|
3
|
+
require "reflexive/descendants"
|
|
4
|
+
|
|
5
|
+
describe "Reflexive.loaded_features_lookup" do
|
|
6
|
+
before(:all) do
|
|
7
|
+
@native_feature = $LOADED_FEATURES.detect { |f| f =~ /\.so\z/ }
|
|
8
|
+
@ruby_feature = $LOADED_FEATURES.detect { |f| f =~ /\.rb\z/ }
|
|
9
|
+
raise "Can't setup test: need at least one native and ruby feature loaded" unless @native_feature && @ruby_feature
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "doesn't looks up native features" do
|
|
13
|
+
Reflexive.loaded_features_lookup(@native_feature).should == nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "looks up ruby features when passed feature basename" do
|
|
17
|
+
ruby_feature_basename = File.basename(@ruby_feature)
|
|
18
|
+
Reflexive.loaded_features_lookup(ruby_feature_basename).should == @ruby_feature
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "looks up ruby features when passed feature basename and path part" do
|
|
22
|
+
feature_dirname = File.dirname(@ruby_feature)
|
|
23
|
+
feature_basename = File.basename(@ruby_feature)
|
|
24
|
+
feature_name = File.join(feature_dirname.split("/").last(2).join("/"),
|
|
25
|
+
feature_basename)
|
|
26
|
+
Reflexive.loaded_features_lookup(feature_name).should == @ruby_feature
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "looks up ruby features when passed feature basename without extension" do
|
|
30
|
+
ruby_feature_basename = File.basename(@ruby_feature).sub(/\.\w+\z/, "")
|
|
31
|
+
Reflexive.loaded_features_lookup(ruby_feature_basename).should == @ruby_feature
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "Reflexive.constant_lookup" do
|
|
36
|
+
module M1
|
|
37
|
+
class C1
|
|
38
|
+
end
|
|
39
|
+
module M2
|
|
40
|
+
module M3
|
|
41
|
+
class C2
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "looks up top-level constants" do
|
|
48
|
+
Reflexive.constant_lookup("::String", "Some::Ignored::Scope").should == ::String
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "returns nil for non existing top-level constant" do
|
|
52
|
+
Reflexive.constant_lookup("::StringAsd", "Some::Ignored::Scope").should == nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "looks up top-level constants without scope" do
|
|
56
|
+
Reflexive.constant_lookup("String", "").should == ::String
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "looks up non top-level constants with scope" do
|
|
60
|
+
Reflexive.constant_lookup("C1", "M1").should == ::M1::C1
|
|
61
|
+
Reflexive.constant_lookup("C2", "M1::M2::M3").should == ::M1::M2::M3::C2
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "returns nil for non existing non top-level constants with scope" do
|
|
65
|
+
Reflexive.constant_lookup("CNotExist", "M1").should == nil
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe "Reflexive.load_path_lookup" do
|
|
70
|
+
it "looks up features present in $LOAD_PATH" do
|
|
71
|
+
feature = nil
|
|
72
|
+
$LOAD_PATH.each { |p| break if (feature = Dir["#{ p }/*.rb"].first) }
|
|
73
|
+
feature_basename = File.basename(feature).sub(/\.\w+\z/, "")
|
|
74
|
+
Reflexive.load_path_lookup(feature_basename).should == feature
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe "Reflexive.descendants" do
|
|
79
|
+
class X2 ; end
|
|
80
|
+
class A2 < X2; end
|
|
81
|
+
class B2 < X2; end
|
|
82
|
+
|
|
83
|
+
module M2
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
class C2
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
C2.extend(M2)
|
|
90
|
+
|
|
91
|
+
it "finds class descendant" do
|
|
92
|
+
Reflexive.descendants(X2).should =~ [B2, A2]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "finds singleton class descendant" do
|
|
96
|
+
Reflexive.descendants(M2).should =~ [C2]
|
|
97
|
+
end
|
|
98
|
+
end
|