reflexive 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/Gemfile +16 -0
  2. data/Rakefile +31 -0
  3. data/config.ru +3 -0
  4. data/reflexive.gemspec +1 -1
  5. data/spec/coderay_html_encoder_spec.rb +57 -0
  6. data/spec/coderay_ruby_scanner_spec.rb +194 -0
  7. data/spec/io_interceptor.rb +64 -0
  8. data/spec/method_lookup_spec.rb +0 -0
  9. data/spec/methods_spec.rb +202 -0
  10. data/spec/rails_integration_spec.rb +139 -0
  11. data/spec/rails_integration_spec_helper.rb +115 -0
  12. data/spec/reflexive_ripper_spec.rb +351 -0
  13. data/spec/reflexive_spec.rb +98 -0
  14. data/spec/ripper_events_recorder.rb +50 -0
  15. data/spec/ripper_spec.rb +758 -0
  16. data/spec/sexp_builder_with_scanner_events.rb +39 -0
  17. data/spec/shell_out.rb +417 -0
  18. data/spec/spec_helper.rb +4 -0
  19. data/spec/test_apps/rails2_test_app/README +243 -0
  20. data/spec/test_apps/rails2_test_app/Rakefile +10 -0
  21. data/spec/test_apps/rails2_test_app/app/controllers/application_controller.rb +10 -0
  22. data/spec/test_apps/rails2_test_app/app/controllers/posts_controller.rb +85 -0
  23. data/spec/test_apps/rails2_test_app/app/helpers/application_helper.rb +3 -0
  24. data/spec/test_apps/rails2_test_app/app/helpers/posts_helper.rb +2 -0
  25. data/spec/test_apps/rails2_test_app/app/models/post.rb +5 -0
  26. data/spec/test_apps/rails2_test_app/app/views/layouts/posts.html.erb +17 -0
  27. data/spec/test_apps/rails2_test_app/app/views/posts/edit.html.erb +12 -0
  28. data/spec/test_apps/rails2_test_app/app/views/posts/index.html.erb +18 -0
  29. data/spec/test_apps/rails2_test_app/app/views/posts/new.html.erb +11 -0
  30. data/spec/test_apps/rails2_test_app/app/views/posts/show.html.erb +3 -0
  31. data/spec/test_apps/rails2_test_app/config/boot.rb +110 -0
  32. data/spec/test_apps/rails2_test_app/config/database.yml +22 -0
  33. data/spec/test_apps/rails2_test_app/config/environment.rb +43 -0
  34. data/spec/test_apps/rails2_test_app/config/environments/development.rb +17 -0
  35. data/spec/test_apps/rails2_test_app/config/environments/production.rb +28 -0
  36. data/spec/test_apps/rails2_test_app/config/environments/test.rb +28 -0
  37. data/spec/test_apps/rails2_test_app/config/initializers/backtrace_silencers.rb +7 -0
  38. data/spec/test_apps/rails2_test_app/config/initializers/inflections.rb +10 -0
  39. data/spec/test_apps/rails2_test_app/config/initializers/mime_types.rb +5 -0
  40. data/spec/test_apps/rails2_test_app/config/initializers/new_rails_defaults.rb +21 -0
  41. data/spec/test_apps/rails2_test_app/config/initializers/session_store.rb +15 -0
  42. data/spec/test_apps/rails2_test_app/config/locales/en.yml +5 -0
  43. data/spec/test_apps/rails2_test_app/config/routes.rb +45 -0
  44. data/spec/test_apps/rails2_test_app/db/development.sqlite3 +0 -0
  45. data/spec/test_apps/rails2_test_app/db/migrate/20100512073155_create_posts.rb +12 -0
  46. data/spec/test_apps/rails2_test_app/db/schema.rb +19 -0
  47. data/spec/test_apps/rails2_test_app/db/seeds.rb +7 -0
  48. data/spec/test_apps/rails2_test_app/doc/README_FOR_APP +2 -0
  49. data/spec/test_apps/rails2_test_app/log/development.log +251 -0
  50. data/spec/test_apps/rails2_test_app/log/production.log +0 -0
  51. data/spec/test_apps/rails2_test_app/log/server.log +0 -0
  52. data/spec/test_apps/rails2_test_app/log/test.log +0 -0
  53. data/spec/test_apps/rails2_test_app/public/404.html +30 -0
  54. data/spec/test_apps/rails2_test_app/public/422.html +30 -0
  55. data/spec/test_apps/rails2_test_app/public/500.html +30 -0
  56. data/spec/test_apps/rails2_test_app/public/favicon.ico +0 -0
  57. data/spec/test_apps/rails2_test_app/public/images/rails.png +0 -0
  58. data/spec/test_apps/rails2_test_app/public/index.html +275 -0
  59. data/spec/test_apps/rails2_test_app/public/javascripts/application.js +2 -0
  60. data/spec/test_apps/rails2_test_app/public/javascripts/controls.js +963 -0
  61. data/spec/test_apps/rails2_test_app/public/javascripts/dragdrop.js +973 -0
  62. data/spec/test_apps/rails2_test_app/public/javascripts/effects.js +1128 -0
  63. data/spec/test_apps/rails2_test_app/public/javascripts/prototype.js +4320 -0
  64. data/spec/test_apps/rails2_test_app/public/robots.txt +5 -0
  65. data/spec/test_apps/rails2_test_app/public/stylesheets/1.css +0 -0
  66. data/spec/test_apps/rails2_test_app/public/stylesheets/scaffold.css +54 -0
  67. data/spec/test_apps/rails2_test_app/script/about +4 -0
  68. data/spec/test_apps/rails2_test_app/script/console +3 -0
  69. data/spec/test_apps/rails2_test_app/script/dbconsole +3 -0
  70. data/spec/test_apps/rails2_test_app/script/destroy +3 -0
  71. data/spec/test_apps/rails2_test_app/script/generate +3 -0
  72. data/spec/test_apps/rails2_test_app/script/performance/benchmarker +3 -0
  73. data/spec/test_apps/rails2_test_app/script/performance/profiler +3 -0
  74. data/spec/test_apps/rails2_test_app/script/plugin +3 -0
  75. data/spec/test_apps/rails2_test_app/script/runner +3 -0
  76. data/spec/test_apps/rails2_test_app/script/server +3 -0
  77. data/spec/test_apps/rails2_test_app/test/fixtures/posts.yml +7 -0
  78. data/spec/test_apps/rails2_test_app/test/functional/posts_controller_test.rb +45 -0
  79. data/spec/test_apps/rails2_test_app/test/performance/browsing_test.rb +9 -0
  80. data/spec/test_apps/rails2_test_app/test/test_helper.rb +38 -0
  81. data/spec/test_apps/rails2_test_app/test/unit/helpers/posts_helper_test.rb +4 -0
  82. data/spec/test_apps/rails2_test_app/test/unit/post_test.rb +8 -0
  83. data/spec/test_apps/rails3_test_app/Gemfile +28 -0
  84. data/spec/test_apps/rails3_test_app/README +244 -0
  85. data/spec/test_apps/rails3_test_app/Rakefile +10 -0
  86. data/spec/test_apps/rails3_test_app/app/controllers/application_controller.rb +4 -0
  87. data/spec/test_apps/rails3_test_app/app/controllers/posts_controller.rb +83 -0
  88. data/spec/test_apps/rails3_test_app/app/helpers/application_helper.rb +2 -0
  89. data/spec/test_apps/rails3_test_app/app/helpers/posts_helper.rb +2 -0
  90. data/spec/test_apps/rails3_test_app/app/models/post.rb +2 -0
  91. data/spec/test_apps/rails3_test_app/app/views/layouts/application.html.erb +14 -0
  92. data/spec/test_apps/rails3_test_app/app/views/posts/_form.html.erb +16 -0
  93. data/spec/test_apps/rails3_test_app/app/views/posts/edit.html.erb +6 -0
  94. data/spec/test_apps/rails3_test_app/app/views/posts/index.html.erb +21 -0
  95. data/spec/test_apps/rails3_test_app/app/views/posts/new.html.erb +5 -0
  96. data/spec/test_apps/rails3_test_app/app/views/posts/show.html.erb +5 -0
  97. data/spec/test_apps/rails3_test_app/config/application.rb +49 -0
  98. data/spec/test_apps/rails3_test_app/config/boot.rb +6 -0
  99. data/spec/test_apps/rails3_test_app/config/database.yml +22 -0
  100. data/spec/test_apps/rails3_test_app/config/environment.rb +5 -0
  101. data/spec/test_apps/rails3_test_app/config/environments/development.rb +19 -0
  102. data/spec/test_apps/rails3_test_app/config/environments/production.rb +42 -0
  103. data/spec/test_apps/rails3_test_app/config/environments/test.rb +32 -0
  104. data/spec/test_apps/rails3_test_app/config/initializers/backtrace_silencers.rb +7 -0
  105. data/spec/test_apps/rails3_test_app/config/initializers/inflections.rb +10 -0
  106. data/spec/test_apps/rails3_test_app/config/initializers/mime_types.rb +5 -0
  107. data/spec/test_apps/rails3_test_app/config/initializers/secret_token.rb +7 -0
  108. data/spec/test_apps/rails3_test_app/config/initializers/session_store.rb +8 -0
  109. data/spec/test_apps/rails3_test_app/config/locales/en.yml +5 -0
  110. data/spec/test_apps/rails3_test_app/config/routes.rb +60 -0
  111. data/spec/test_apps/rails3_test_app/config.ru +4 -0
  112. data/spec/test_apps/rails3_test_app/db/development.sqlite3 +0 -0
  113. data/spec/test_apps/rails3_test_app/db/migrate/20100512075428_create_posts.rb +12 -0
  114. data/spec/test_apps/rails3_test_app/db/schema.rb +19 -0
  115. data/spec/test_apps/rails3_test_app/db/seeds.rb +7 -0
  116. data/spec/test_apps/rails3_test_app/doc/README_FOR_APP +2 -0
  117. data/spec/test_apps/rails3_test_app/log/development.log +349 -0
  118. data/spec/test_apps/rails3_test_app/log/production.log +0 -0
  119. data/spec/test_apps/rails3_test_app/log/server.log +0 -0
  120. data/spec/test_apps/rails3_test_app/log/test.log +0 -0
  121. data/spec/test_apps/rails3_test_app/public/404.html +26 -0
  122. data/spec/test_apps/rails3_test_app/public/422.html +26 -0
  123. data/spec/test_apps/rails3_test_app/public/500.html +26 -0
  124. data/spec/test_apps/rails3_test_app/public/favicon.ico +0 -0
  125. data/spec/test_apps/rails3_test_app/public/images/rails.png +0 -0
  126. data/spec/test_apps/rails3_test_app/public/index.html +279 -0
  127. data/spec/test_apps/rails3_test_app/public/javascripts/application.js +2 -0
  128. data/spec/test_apps/rails3_test_app/public/javascripts/controls.js +965 -0
  129. data/spec/test_apps/rails3_test_app/public/javascripts/dragdrop.js +974 -0
  130. data/spec/test_apps/rails3_test_app/public/javascripts/effects.js +1123 -0
  131. data/spec/test_apps/rails3_test_app/public/javascripts/prototype.js +4874 -0
  132. data/spec/test_apps/rails3_test_app/public/javascripts/rails.js +118 -0
  133. data/spec/test_apps/rails3_test_app/public/robots.txt +5 -0
  134. data/spec/test_apps/rails3_test_app/public/stylesheets/scaffold.css +60 -0
  135. data/spec/test_apps/rails3_test_app/script/rails +9 -0
  136. data/spec/test_apps/rails3_test_app/test/fixtures/posts.yml +11 -0
  137. data/spec/test_apps/rails3_test_app/test/functional/posts_controller_test.rb +49 -0
  138. data/spec/test_apps/rails3_test_app/test/performance/browsing_test.rb +9 -0
  139. data/spec/test_apps/rails3_test_app/test/test_helper.rb +13 -0
  140. data/spec/test_apps/rails3_test_app/test/unit/helpers/posts_helper_test.rb +4 -0
  141. data/spec/test_apps/rails3_test_app/test/unit/post_test.rb +8 -0
  142. metadata +142 -2
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source "http://rubygems.org"
2
+
3
+ # keeping this in sync with reflexive.gemspec manually
4
+
5
+ gem "rack"
6
+ gem "sinatra"
7
+ gem "sinatra_more"
8
+ gem "coderay"
9
+ gem "rdiscount"
10
+
11
+ group :development do
12
+ gem "rails", "3.0.0.beta3"
13
+ gem "rspec", "2.0.0.beta.8"
14
+ gem "sinatra-reloader"
15
+ gem "thin"
16
+ end
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ $LOAD_PATH.unshift(File.expand_path("../lib", __FILE__))
2
+
3
+ desc "Run specs (without Rails integration spec - requires rvm, run manually with `spec ./spec/rails_integration_spec.rb')"
4
+ task :spec do
5
+ sh "spec #{ (Dir["./spec/*_spec.rb"] - ["./spec/rails_integration_spec.rb"]).join(" ") }"
6
+ end
7
+
8
+ GEM_NAME = "reflexive"
9
+
10
+ desc "Relese next version of reflexive gem"
11
+ task :release do
12
+ require "rubygems"
13
+ require "rubygems/version"
14
+ require "yaml"
15
+
16
+ current_version = YAML.load(`gem specification #{ GEM_NAME } -r`)["version"] || Gem::Version.new("0.0.0")
17
+ new_version = (current_version.segments[0..-2] + [current_version.segments[-1].succ]).join(".")
18
+ ENV["GEM_VERSION"] = new_version
19
+
20
+ puts "Releasing #{ GEM_NAME } #{ new_version }"
21
+
22
+ sh "gem build #{ GEM_NAME }.gemspec --verbose"
23
+
24
+ sh "gem push #{ GEM_NAME }-#{ new_version }.gem --verbose"
25
+
26
+ sh "gem install #{ GEM_NAME } --version=#{ new_version } --local --verbose"
27
+
28
+ File.delete("#{ GEM_NAME }-#{ new_version }.gem")
29
+ end
30
+
31
+ task :default => :spec
data/config.ru ADDED
@@ -0,0 +1,3 @@
1
+ require File.expand_path("../lib/reflexive/application", __FILE__)
2
+
3
+ run Reflexive::Application
data/reflexive.gemspec CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
6
6
  s.homepage = "http://github.com/dolzenko/reflexive"
7
7
  s.summary = "Reflexive"
8
8
 
9
- s.files = Dir.glob("{lib,public,views}/**/*") + %w(reflexive.gemspec)
9
+ s.files = Dir.glob("{lib,public,views,spec}/**/*") + %w(reflexive.gemspec Rakefile Gemfile config.ru)
10
10
 
11
11
  s.required_ruby_version = '>= 1.9.1'
12
12
 
@@ -0,0 +1,57 @@
1
+ require "reflexive/coderay_html_encoder"
2
+
3
+ describe Reflexive::CodeRayHtmlEncoder do
4
+ def encoder
5
+ Reflexive::CodeRayHtmlEncoder.new(:wrap => :div, :css => :style)
6
+ end
7
+
8
+ it "emits links for :constant tokens" do
9
+ encoder = Reflexive::CodeRayHtmlEncoder.new(:wrap => :div, :css => :style)
10
+ encoder.encode_tokens([["Cons", :constant,
11
+ {:constant_access=>{:name=>"Cons", :scope=>[]}}]]).should(include("<a href"))
12
+ end
13
+
14
+ it "emits links with proper nesting info" do
15
+ tokens = [["Cons", :constant,
16
+ {:constant_access=>{:name=>"Cons", :scope=>["A", "B"]}}]]
17
+
18
+ encoder.encode_tokens(tokens).should include("constant_lookup?name=Cons&scope=A%3A%3AB")
19
+ end
20
+
21
+ it "emits load_path links" do
22
+ tokens = [["f", :content, { :load_path => true }]]
23
+ encoder.encode_tokens(tokens).should include("?path=f")
24
+ end
25
+
26
+ it "emits class method links" do
27
+ tokens = [ [
28
+ "m!", :ident,
29
+ {:method_call=>{:name=>"m!", :receiver=>["A"]} }
30
+ ] ]
31
+ encoder.encode_tokens(tokens).should include("/constants/A/class_methods/m%21")
32
+ end
33
+
34
+ it "emits instance method links" do
35
+ tokens = [ [
36
+ "m!", :ident,
37
+ {:method_call=>{:name=>"m!", :receiver=>["A", :instance]} }
38
+ ] ]
39
+ encoder.encode_tokens(tokens).should include("/constants/A/instance_methods/m%21")
40
+ end
41
+
42
+ it "emits variable assignment id" do
43
+ tokens = [ [
44
+ "a", :ident,
45
+ {:local_variable_assignment=>"1:a"}
46
+ ] ]
47
+ encoder.encode_tokens(tokens).should include("span id='lv:1:a'")
48
+ end
49
+
50
+ it "emits variable access links" do
51
+ tokens = [ [
52
+ "a", :ident,
53
+ {:local_variable_access=>"1:a"}
54
+ ] ]
55
+ encoder.encode_tokens(tokens).should include("href='#lv:1:a'")
56
+ end
57
+ end
@@ -0,0 +1,194 @@
1
+ require "reflexive/coderay_ruby_scanner"
2
+ require "coderay/scanners/ruby"
3
+
4
+ describe Reflexive::CodeRayRubyScanner do
5
+ def reflexive_tokens(src)
6
+ Reflexive::CodeRayRubyScanner.new(src).tokenize
7
+ end
8
+
9
+ def reflexive_tokens_without_meta_and_tags(src)
10
+ Reflexive::CodeRayRubyScanner.new(src).tokenize.
11
+ reject { |t| t[1] == :meta_scope }.
12
+ reject { |t| t[0] == :method_call }.
13
+ map { |t| t[2].is_a?(Hash) ? t[0..1] : t }
14
+ end
15
+
16
+ def coderay_tokens(src)
17
+ squeezed_tokes = []
18
+ ::CodeRay::Scanners::Ruby.new(src).tokenize.each do |token|
19
+ if squeezed_tokes.size > 0 &&
20
+ squeezed_tokes[-1][1] == token[1]
21
+ squeezed_tokes[-1][0] << token[0]
22
+ else
23
+ squeezed_tokes << token
24
+ end
25
+ end
26
+ end
27
+
28
+ pending "squeezes constants" do
29
+ src = <<-RUBY
30
+ class ConstRef < Const::PathRef
31
+ RefenceConstInClassBody = ::TopConstRef
32
+ def m
33
+ Const::PathRef
34
+ end
35
+ end
36
+
37
+ class Const::PathRef < ::TopConstRef
38
+ def self.m
39
+ reference_in_method_body ::TopConstRef
40
+ end
41
+ end
42
+
43
+ class ::TopConstRef
44
+ end
45
+
46
+ class Const::Deeply::Nested::PathRef < ConstRef
47
+ end
48
+ RUBY
49
+ tokens = reflexive_tokens(src)
50
+ tokens.should include(["ConstRef", :constant, { :scope => nil }])
51
+ tokens.should include(["Const::PathRef", :constant, { :scope => ["ConstRef"] }])
52
+ tokens.should include(["Const::PathRef", :constant, { :scope => nil }])
53
+ tokens.should include(["::TopConstRef", :constant, { :scope => nil }])
54
+ tokens.should include(["::TopConstRef", :constant, { :scope => ["Const::PathRef"] }])
55
+ tokens.should include(["Const::Deeply::Nested::PathRef", :constant, { :scope => nil }])
56
+ end
57
+
58
+ it "injects load_path tags" do
59
+ reflexive_tokens("require('f')").should include(["f", :content, { :load_path => true }])
60
+ reflexive_tokens("require 'f'").should include(["f", :content, { :load_path => true }])
61
+ end
62
+
63
+ it "injects instance method tags"
64
+
65
+ ONE_LINERS = <<-RUBY.gsub(/^ */, "")
66
+ %Q{str}
67
+ %r<regexp>
68
+ :symbol
69
+ :@instance_var_symbol
70
+ :@@class_var_symbol
71
+ :$global_var_symbol
72
+ :ConstantSymbol
73
+ :+
74
+ :if
75
+ #!/usr/bin/env ruby
76
+ %q[haha! [nesting [rocks] ] ! ]
77
+ %Q[hehe! \#{ %Q]nesting \#{"really"} rocks] } ! ]
78
+ some_string.to_i /\\s+/
79
+ S = 'bla' * 100 + "\n" + "\t"*4
80
+ :"\#{undef :blubb}\#@@cv"
81
+ undef :"bla", /, :"\#{undef :blubb}\#@@cv"
82
+ @hash.delete_if { |o,| yield(o) }
83
+ "double quoted string"
84
+ # comment
85
+ "a \#{ b + "c"}"
86
+ 42 if true
87
+ /regexp with modifiers/xm
88
+ a = ?s
89
+ q = "\\n"
90
+ call_something()
91
+ a = 1 && 2 || 3
92
+ @ivar = 123
93
+ @@cvar = 345
94
+ $gvar = 345
95
+ float = 1.2345
96
+ `shell`
97
+ v = %w(w1 w2)
98
+ "a\#{" b \#{@c} d" if @c} d \#{@e}; f."
99
+ RUBY
100
+
101
+ # ONE_LINERS.split("\n").each do |src|
102
+ # it "should parse `#{ src }' just as CodeRay parser does" do
103
+ # reflexive_tokens(src).should == coderay_tokens(src)
104
+ # end
105
+ # end
106
+
107
+
108
+ it "generates CodeRay compatible token stream" do
109
+ src = <<-RUBY.gsub(/^ */, "")
110
+ #{ ONE_LINERS }
111
+ [].each do |*args, &block|
112
+ self.class.define_method do
113
+ end
114
+ end
115
+ class Qwe < Asd
116
+ alias qwe asd
117
+ module Sdf
118
+ def self.sm
119
+ end
120
+ end
121
+ end
122
+ =begin
123
+ heredoc1
124
+ =end
125
+ <<-QWE
126
+ QWE
127
+ if 1 > 0
128
+ elsif false
129
+ end
130
+ begin
131
+ 42
132
+ rescue Exception => e
133
+ [] << 'q'
134
+ end
135
+ def `(cmd)
136
+ end
137
+ RUBY
138
+ expected_tokens = [
139
+ [:open, :string], ["%Q{", :delimiter], ["str", :content], ["}", :delimiter], [:close, :string], ["\n", :space],
140
+ [:open, :regexp], ["%r<", :delimiter], ["regexp", :content], [">", :delimiter], [:close, :regexp], ["\n", :space],
141
+ [:open, :symbol], [":", :delimiter], ["symbol", :content], [:close, :symbol], ["\n", :space],
142
+ [:open, :symbol], [":", :delimiter], ["@instance_var_symbol", :content], [:close, :symbol], ["\n", :space],
143
+ [:open, :symbol], [":", :delimiter], ["@@class_var_symbol", :content], [:close, :symbol], ["\n", :space],
144
+ [:open, :symbol], [":", :delimiter], ["$global_var_symbol", :content], [:close, :symbol], ["\n", :space],
145
+ [:open, :symbol], [":", :delimiter], ["ConstantSymbol", :content], [:close, :symbol], ["\n", :space],
146
+ [:open, :symbol], [":", :delimiter], ["+", :content], [:close, :symbol], ["\n", :space],
147
+ [:open, :symbol], [":", :delimiter], ["if", :content], [:close, :symbol], ["\n", :space],
148
+ ["#!/usr/bin/env ruby\n", :comment], [:open, :string], ["%q[", :delimiter], ["haha! [nesting [rocks] ] ! ", :content], ["]", :delimiter], [:close, :string], ["\n", :space],
149
+ [:open, :string], ["%Q[", :delimiter], ["hehe! ", :content], [:open, :inline], ["\#{", :inline_delimiter], [" ", :space], [:open, :string], ["%Q]", :delimiter], ["nesting ", :content], [:open, :inline], ["\#{", :inline_delimiter], [:open, :string], ["\"", :delimiter], ["really", :content], ["\"", :delimiter], [:close, :string], ["}", :inline_delimiter], [:close, :inline], [" rocks", :content], ["]", :delimiter], [:close, :string], [" ", :space], ["}", :inline_delimiter], [:close, :inline], [" ! ", :content], ["]", :delimiter], [:close, :string], ["\n", :space],
150
+ ["some_string", :ident], [".", :operator], ["to_i", :ident], [" ", :space], [:open, :regexp], ["/", :delimiter], ["\\s+", :content], ["/", :delimiter], [:close, :regexp], ["\n", :space],
151
+ ["S", :constant], [" ", :space], ["=", :operator], [" ", :space], [:open, :string], ["'", :delimiter], ["bla", :content], ["'", :delimiter], [:close, :string], [" ", :space], ["*", :operator], [" ", :space], ["100", :integer], [" ", :space], ["+", :operator], [" ", :space], [:open, :string], ["\"", :delimiter], ["\n", :content], ["\"", :delimiter], [:close, :string], [" ", :space], ["+", :operator], [" ", :space], [:open, :string], ["\"", :delimiter], ["\t", :content], ["\"", :delimiter], [:close, :string], ["*", :operator], ["4", :integer], ["\n", :space],
152
+ [:open, :symbol], [":\"", :delimiter], [:open, :inline], ["\#{", :inline_delimiter], ["undef", :content], [:close, :symbol], [" ", :space], [:open, :symbol], [":", :delimiter], ["blubb", :content], [:close, :symbol], ["}", :inline_delimiter], [:close, :inline], ["#", :escape], ["@@cv", :class_variable], ["\"", :delimiter], [:close, :string], ["\n", :space],
153
+ ["undef", :reserved], [" ", :space], [:open, :symbol], [":\"", :delimiter], ["bla", :content], ["\"", :delimiter], [:close, :symbol], [",", :operator], [" ", :space], ["/,", :operator], [" ", :space], [:open, :symbol], [":\"", :delimiter], [:open, :inline], ["\#{", :inline_delimiter], ["undef", :content], [:close, :symbol], [" ", :space], [:open, :symbol], [":", :delimiter], ["blubb", :content], [:close, :symbol], ["}", :inline_delimiter], [:close, :inline], ["#", :escape], ["@@cv", :class_variable], ["\"", :delimiter], [:close, :string], ["\n", :space],
154
+ ["@hash", :instance_variable], [".", :operator], ["delete_if", :ident], [" ", :space], ["{", :operator], [" ", :space], ["|", :operator], ["o", :ident], [",|", :operator], [" ", :space], ["yield", :reserved], ["(", :operator], ["o", :ident], [")", :operator], [" ", :space], ["}", :operator], ["\n", :space],
155
+ [:open, :string], ["\"", :delimiter], ["double quoted string", :content], ["\"", :delimiter], [:close, :string], ["\n", :space],
156
+ ["# comment\n", :comment], [:open, :string], ["\"", :delimiter], ["a ", :content], [:open, :inline], ["\#{", :inline_delimiter], [" ", :space], ["b", :ident], [" ", :space], ["+", :operator], [" ", :space], [:open, :string], ["\"", :delimiter], ["c", :content], ["\"", :delimiter], [:close, :string], ["}", :inline_delimiter], [:close, :inline], ["\"", :delimiter], [:close, :string], ["\n", :space],
157
+ ["42", :integer], [" ", :space], ["if", :reserved], [" ", :space], ["true", :reserved], ["\n", :space],
158
+ [:open, :regexp], ["/", :delimiter], ["regexp with modifiers", :content], ["/xm", :delimiter], [:close, :regexp], ["\n", :space],
159
+ ["a", :ident], [" ", :space], ["=", :operator], [" ", :space], ["?s", :integer], ["\n", :space],
160
+ ["q", :ident], [" ", :space], ["=", :operator], [" ", :space], [:open, :string], ["\"", :delimiter], ["\\n", :content], ["\"", :delimiter], [:close, :string], ["\n", :space],
161
+ ["call_something", :ident], ["()", :operator], ["\n", :space],
162
+ ["a", :ident], [" ", :space], ["=", :operator], [" ", :space], ["1", :integer], [" ", :space], ["&&", :operator], [" ", :space], ["2", :integer], [" ", :space], ["||", :operator], [" ", :space], ["3", :integer], ["\n", :space],
163
+ ["@ivar", :instance_variable], [" ", :space], ["=", :operator], [" ", :space], ["123", :integer], ["\n", :space],
164
+ ["@@cvar", :class_variable], [" ", :space], ["=", :operator], [" ", :space], ["345", :integer], ["\n", :space],
165
+ ["$gvar", :global_variable], [" ", :space], ["=", :operator], [" ", :space], ["345", :integer], ["\n", :space],
166
+ ["float", :ident], [" ", :space], ["=", :operator], [" ", :space], ["1.2345", :float], ["\n", :space],
167
+ [:open, :shell], ["`", :delimiter], ["shell", :content], ["`", :delimiter], [:close, :shell], ["\n", :space],
168
+ ["v", :ident], [" ", :space], ["=", :operator], [" ", :space], ["%w(w1 w2)", :content], ["\n", :space],
169
+ [:open, :string], ["\"", :delimiter], ["a", :content], [:open, :inline], ["\#{", :inline_delimiter], [:open, :string], ["\"", :delimiter], [" b ", :content], [:open, :inline], ["\#{", :inline_delimiter], ["@c", :instance_variable], ["}", :inline_delimiter], [:close, :inline], [" d", :content], ["\"", :delimiter], [:close, :string], [" ", :space], ["if", :reserved], [" ", :space], ["@c", :instance_variable], ["}", :inline_delimiter], [:close, :inline], [" d ", :content], [:open, :inline], ["\#{", :inline_delimiter], ["@e", :instance_variable], ["}", :inline_delimiter], [:close, :inline], ["; f.", :content], ["\"", :delimiter], [:close, :string], ["\n\n", :space], ["[].", :operator], ["each", :ident], [" ", :space], ["do", :reserved], [" ", :space], ["|*", :operator], ["args", :ident], [",", :operator], [" ", :space], ["&", :operator], ["block", :ident], ["|", :operator], ["\n", :space],
170
+ ["self", :reserved], [".", :operator], ["class", :ident], [".", :operator], ["define_method", :ident], [" ", :space], ["do", :reserved], ["\n", :space],
171
+ ["end", :reserved], ["\n", :space],
172
+ ["end", :reserved], ["\n", :space],
173
+ ["class", :reserved], [" ", :space], ["Qwe", :constant], [" ", :space], ["<", :operator], [" ", :space], ["Asd", :constant], ["\n", :space],
174
+ ["alias", :reserved], [" ", :space], ["qwe", :ident], [" ", :space], ["asd", :ident], ["\n", :space],
175
+ ["module", :reserved], [" ", :space], ["Sdf", :constant], ["\n", :space],
176
+ ["def", :reserved], [" ", :space], ["self", :reserved], [".", :operator], ["sm", :ident], ["\n", :space],
177
+ ["end", :reserved], ["\n", :space],
178
+ ["end", :reserved], ["\n", :space],
179
+ ["end", :reserved], ["\n", :space],
180
+ ["=begin\nheredoc1\n=end\n", :comment], ["<<-QWE", :heredoc_beg], ["\n", :space],
181
+ ["if", :reserved], [" ", :space], ["1", :integer], [" ", :space], [">", :operator], [" ", :space], ["0", :integer], ["\n", :space],
182
+ ["elsif", :reserved], [" ", :space], ["false", :reserved], ["\n", :space],
183
+ ["end", :reserved], ["\n", :space],
184
+ ["begin", :reserved], ["\n", :space],
185
+ ["42", :integer], ["\n", :space],
186
+ ["rescue", :reserved], [" ", :space], ["Exception", :constant], [" ", :space], ["=>", :operator], [" ", :space], ["e", :ident], ["\n", :space],
187
+ ["[]", :operator], [" ", :space], ["<<", :operator], [" ", :space], [:open, :string], ["'", :delimiter], ["q", :content], ["'", :delimiter], [:close, :string], ["\n", :space],
188
+ ["end", :reserved], ["\n", :space],
189
+ ["def", :reserved], [" ", :space], ["`", :method], ["(", :operator], ["cmd", :ident], [")", :operator], ["\n", :space],
190
+ ["end", :reserved], ["\n", :space]]
191
+ reflexive_tokens_without_meta_and_tags(src).should == expected_tokens
192
+ end
193
+ end
194
+
@@ -0,0 +1,64 @@
1
+ # Safe way to intercept IO stream
2
+ # where just replacing STDOUT doesn't work:
3
+ # http://rubyforge.org/tracker/index.php?func=detail&aid=5217&group_id=426&atid=1698
4
+ #
5
+ module IoInterceptor
6
+ def intercept
7
+ begin
8
+ @intercept = true
9
+ @intercepted = ""
10
+ yield
11
+ ensure
12
+ @intercept = false
13
+ end
14
+ @intercepted
15
+ end
16
+
17
+ def supress
18
+ begin
19
+ @supress = true
20
+ yield
21
+ ensure
22
+ @supress = false
23
+ end
24
+ end
25
+
26
+ def write(str)
27
+ if @supress || @intercept
28
+ @intercepted << str.to_s unless @supress
29
+ str.size
30
+ else
31
+ super
32
+ end
33
+ end
34
+ end
35
+
36
+ if $PROGRAM_NAME == __FILE__
37
+ require 'spec'
38
+
39
+ describe IoInterceptor do
40
+ before do
41
+ STDOUT.extend(IoInterceptor)
42
+ end
43
+
44
+ it "intercepts output to stream when the stream is extended with it" do
45
+ STDOUT.intercept { STDOUT.puts("42") }.should == "42\n"
46
+ STDOUT.intercept { STDOUT.puts("24") }.should == "24\n"
47
+ end
48
+
49
+ it "intercepted IO#write still returns the number of bytes written" do
50
+ STDOUT.intercept { STDOUT.write("42").should == 2 }
51
+ end
52
+
53
+ it "intercepted IO#write argument is converted using to_s" do
54
+ obj = "42"
55
+ def obj.to_s
56
+ "custom to_s"
57
+ end
58
+
59
+ STDOUT.intercept { STDOUT.puts(obj) }.should == "#{ obj.to_s }\n"
60
+ end
61
+ end
62
+
63
+ exit ::Spec::Runner::CommandLine.run
64
+ end
File without changes
@@ -0,0 +1,202 @@
1
+ require "reflexive/methods"
2
+
3
+ Rspec::Matchers.define :generate_methods do |expected|
4
+ match do |actual|
5
+ Reflexive::Methods.new(actual).all == eval(expected)
6
+ end
7
+
8
+ failure_message_for_should do |actual|
9
+ require "pp"
10
+ require "stringio"
11
+ pp_out = StringIO.new
12
+ PP.pp(Reflexive::Methods.new(actual).all, pp_out)
13
+ "expected:\n#{ expected }\ngot:\n#{ pp_out.string }"
14
+ end
15
+ end
16
+
17
+ describe Reflexive::Methods do
18
+ describe "ModuleInclusionC" do
19
+ module ModuleInclusionA
20
+ def module_instance_from_A_WTF!
21
+ end
22
+ end
23
+
24
+ module ModuleInclusionB
25
+ include ModuleInclusionA
26
+
27
+ def module_instance_from_B_WTF!
28
+ end
29
+ end
30
+
31
+ module ModuleInclusionC
32
+ include ModuleInclusionB
33
+ end
34
+
35
+ it "works" do
36
+ ModuleInclusionC.should generate_methods(<<-METHODS_PP)
37
+ [{"[M] ModuleInclusionB"=>
38
+ {:instance=>{:public=>[:module_instance_from_B_WTF!]}}},
39
+ {"[M] ModuleInclusionA"=>
40
+ {:instance=>{:public=>[:module_instance_from_A_WTF!]}}}]
41
+ METHODS_PP
42
+ end
43
+ end
44
+ describe "Inheritance" do
45
+ class InheritanceA
46
+ def self.singleton_inherited_from_A_WTF!
47
+ end
48
+ end
49
+
50
+ class InheritanceB < InheritanceA
51
+ end
52
+
53
+ class InheritanceC < InheritanceB
54
+ def test
55
+ end
56
+ end
57
+
58
+ it "works" do
59
+ InheritanceC.should generate_methods(<<-METHODS_PP)
60
+ [{"[C] InheritanceC"=>{:instance=>{:public=>[:test]}}},
61
+ {"[C] InheritanceA"=>{:class=>{:public=>[:singleton_inherited_from_A_WTF!]}}}]
62
+ METHODS_PP
63
+ end
64
+ end
65
+
66
+ describe "SingletonAndInstance" do
67
+ module M
68
+ def instance_from_moduleWTF!
69
+ end
70
+ end
71
+
72
+ module SM
73
+ def singleton_from_moduleWTF!
74
+ end
75
+ end
76
+
77
+ class SingletonAndInstanceTest
78
+ include M
79
+ extend SM
80
+
81
+ def self.singletonWTF!
82
+ end
83
+
84
+ def instanceWTF!
85
+ end
86
+ end
87
+
88
+ it "works" do
89
+ SingletonAndInstanceTest.should generate_methods(<<-METHODS_PP)
90
+ [{"[C] SingletonAndInstanceTest"=>
91
+ {:class=>{:public=>[:singletonWTF!]},
92
+ :instance=>{:public=>[:instanceWTF!]}}},
93
+ {"S[M] SM"=>{:class=>{:public=>[:singleton_from_moduleWTF!]}}},
94
+ {"[M] M"=>{:instance=>{:public=>[:instance_from_moduleWTF!]}}}]
95
+ METHODS_PP
96
+ end
97
+ end
98
+
99
+ describe "ExtendWithInstanceAndClass" do
100
+ module ExtendWithInstanceAndClassM
101
+ def self.singleton_WTF!
102
+ end
103
+
104
+ def instance_WTF!
105
+ end
106
+ end
107
+
108
+ class ExtendWithInstanceAndClass
109
+ extend ExtendWithInstanceAndClassM
110
+ end
111
+
112
+ it "works" do
113
+ ExtendWithInstanceAndClass.should generate_methods(<<-METHODS_PP)
114
+ [{"S[M] ExtendWithInstanceAndClassM"=>{:class=>{:public=>[:instance_WTF!]}}}]
115
+ METHODS_PP
116
+ end
117
+ end
118
+
119
+ describe "SingletonVisibility" do
120
+ class SingletonVisibility
121
+ def self.class_method
122
+ end
123
+
124
+ class << self
125
+
126
+ def public_singleton_method
127
+ end
128
+ public :public_singleton_method
129
+
130
+ def protected_singleton_method
131
+ end
132
+ protected :protected_singleton_method
133
+
134
+ def private_singleton_method
135
+ end
136
+ private :private_singleton_method
137
+ end
138
+ end
139
+
140
+ it "works" do
141
+ SingletonVisibility.should generate_methods(<<-METHODS_PP)
142
+ [{"[C] SingletonVisibility"=>
143
+ {:class=>
144
+ {:public=>[:class_method, :public_singleton_method],
145
+ :protected=>[:protected_singleton_method],
146
+ :private=>[:private_singleton_method]}}}]
147
+ METHODS_PP
148
+ end
149
+ end
150
+
151
+ describe "SingletonOverrides" do
152
+ class SingletonOverridesA
153
+ def self.overriden
154
+ puts "A"
155
+ # super
156
+ end
157
+ end
158
+
159
+ module SingletonOverridesMB
160
+ def overriden
161
+ puts " MB"
162
+ super
163
+ end
164
+ end
165
+
166
+ class SingletonOverridesB < SingletonOverridesA
167
+ extend SingletonOverridesMB
168
+
169
+ def self.overriden
170
+ end
171
+ end
172
+
173
+ module SingletonOverridesMC
174
+ def overriden
175
+ end
176
+
177
+ def singleton_WTF
178
+ end
179
+ end
180
+
181
+ class SingletonOverridesC < SingletonOverridesB
182
+ extend SingletonOverridesMC
183
+
184
+ def self.class_WTF
185
+ end
186
+
187
+ def self.overriden
188
+ end
189
+ end
190
+
191
+ it "works" do
192
+ SingletonOverridesC.should generate_methods(<<-METHODS_PP)
193
+ [{"[C] SingletonOverridesC"=>{:class=>{:public=>[:class_WTF, :overriden]}}},
194
+ {"S[M] SingletonOverridesMC"=>
195
+ {:class=>{:public=>[:overriden, :singleton_WTF]}}},
196
+ {"[C] SingletonOverridesB"=>{:class=>{:public=>[:overriden]}}},
197
+ {"S[M] SingletonOverridesMB"=>{:class=>{:public=>[:overriden]}}},
198
+ {"[C] SingletonOverridesA"=>{:class=>{:public=>[:overriden]}}}]
199
+ METHODS_PP
200
+ end
201
+ end
202
+ end