reflexive 0.0.6 → 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/Gemfile +9 -7
- data/Rakefile +10 -4
- data/config.ru +1 -1
- data/lib/reflexive/application.rb +50 -30
- data/lib/reflexive/coderay_html_encoder.rb +1 -1
- data/lib/reflexive/coderay_ruby_scanner.rb +2 -0
- data/lib/reflexive/core_ext/module/reflexive_instance_methods.rb +44 -0
- data/lib/reflexive/descendants.rb +12 -2
- data/lib/reflexive/helpers.rb +26 -9
- data/lib/reflexive/method_lookup.rb +199 -0
- data/lib/reflexive/methods.rb +3 -2
- data/lib/reflexive/parse_tree_top_down_walker.rb +69 -8
- data/lib/reflexive/reflexive_ripper.rb +5 -2
- data/lib/reflexive/routing_helpers.rb +74 -53
- data/public/stylesheets/reflexive/reflexive.css +5 -0
- data/reflexive.gemspec +9 -6
- data/spec/coderay_html_encoder_spec.rb +8 -2
- data/spec/integration_spec.rb +227 -0
- data/spec/integration_spec_fixture.rb +87 -0
- data/spec/method_lookup_spec.rb +348 -0
- data/spec/methods_spec.rb +246 -28
- data/spec/rails_integration_spec.rb +7 -0
- data/spec/rails_integration_spec_helper.rb +21 -11
- data/spec/reflexive_ripper_spec.rb +57 -19
- data/spec/reflexive_spec.rb +15 -0
- data/views/constants_show.erb +18 -1
- data/views/dashboard.erb +3 -4
- data/views/layout.erb +10 -0
- data/views/methods_apidock.erb +9 -1
- data/views/methods_choose.erb +19 -0
- metadata +76 -40
data/lib/reflexive/methods.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "reflexive/core_ext/kernel/singleton_class"
|
2
|
+
require "reflexive/core_ext/module/reflexive_instance_methods"
|
2
3
|
|
3
4
|
module Reflexive
|
4
5
|
class Methods
|
@@ -36,7 +37,7 @@ module Reflexive
|
|
36
37
|
def each_immediate_class_and_instance_method(&block)
|
37
38
|
VISIBILITIES.each do |visibility|
|
38
39
|
[ @klass_or_module, @klass_or_module.singleton_class ].each do |klass|
|
39
|
-
methods = klass.send("#{ visibility }_instance_methods", false)
|
40
|
+
methods = klass.send("reflexive_#{ visibility }_instance_methods", false)
|
40
41
|
methods.each { |m| block.call(klass.instance_method(m)) }
|
41
42
|
end
|
42
43
|
end
|
@@ -123,7 +124,7 @@ module Reflexive
|
|
123
124
|
# when no methods are found - returns nil
|
124
125
|
def collect_instance_methods(klass)
|
125
126
|
methods_with_visibility = VISIBILITIES.map do |visibility|
|
126
|
-
methods = klass.send("#{ visibility }_instance_methods", false)
|
127
|
+
methods = klass.send("reflexive_#{ visibility }_instance_methods", false)
|
127
128
|
[visibility, methods] unless methods.empty?
|
128
129
|
end.compact
|
129
130
|
Hash[methods_with_visibility] unless methods_with_visibility.empty?
|
@@ -91,7 +91,17 @@ module Reflexive
|
|
91
91
|
return unless params_event
|
92
92
|
params_event = params_event[1] if params_event[0] == :paren # ?
|
93
93
|
found = false
|
94
|
-
|
94
|
+
|
95
|
+
if options_arguments = params_event[2]
|
96
|
+
options_arguments.each do |optional_argument|
|
97
|
+
if scanner_event?(event = optional_argument[0])
|
98
|
+
add_local_variable(event)
|
99
|
+
keep_walking(optional_argument[1..-1])
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
for scanner_event in extract_scanner_events_from_tree(params_event.values_at(1,3,4,5))
|
95
105
|
if scanner_event[:ident]
|
96
106
|
found = true
|
97
107
|
add_local_variable(scanner_event)
|
@@ -167,10 +177,11 @@ module Reflexive
|
|
167
177
|
|
168
178
|
def on_def(name, params, body)
|
169
179
|
push_local_variables_context
|
180
|
+
# TODO this is hack :(
|
181
|
+
push_namespace_instance_scope unless @in_singleton_class_defition
|
170
182
|
add_local_variables_from_params_event(params)
|
171
|
-
push_namespace_instance_scope
|
172
183
|
keep_walking(body)
|
173
|
-
pop_namespace_scope
|
184
|
+
pop_namespace_scope unless @in_singleton_class_defition
|
174
185
|
pop_local_variables_context
|
175
186
|
end
|
176
187
|
|
@@ -182,7 +193,7 @@ module Reflexive
|
|
182
193
|
end
|
183
194
|
|
184
195
|
def on_class(name, ancestor, body)
|
185
|
-
keep_walking(name)
|
196
|
+
keep_walking(name, ancestor)
|
186
197
|
push_local_variables_context
|
187
198
|
push_namespace_scope(resolve_constant_ref(name))
|
188
199
|
keep_walking(body)
|
@@ -192,7 +203,9 @@ module Reflexive
|
|
192
203
|
|
193
204
|
def on_sclass(target, body)
|
194
205
|
push_local_variables_context
|
206
|
+
@in_singleton_class_defition = true
|
195
207
|
keep_walking(body)
|
208
|
+
@in_singleton_class_defition = false
|
196
209
|
pop_local_variables_context
|
197
210
|
end
|
198
211
|
|
@@ -231,13 +244,61 @@ module Reflexive
|
|
231
244
|
|
232
245
|
def on_command(operation, command_args)
|
233
246
|
method_call(operation, nil) if is_ident?(operation)
|
247
|
+
if operation[:ident] == "autoload" &&
|
248
|
+
(arguments = resolve_arguments(command_args))
|
249
|
+
|
250
|
+
if [:const, :tstring_content].include?(arguments[0].keys.first)
|
251
|
+
constant_access(arguments[0], arguments[0].values.first)
|
252
|
+
end
|
253
|
+
end
|
234
254
|
keep_walking(command_args)
|
235
255
|
end
|
236
256
|
|
257
|
+
def resolve_arguments(arguments)
|
258
|
+
arguments = arguments[1] if arguments[0] == :arg_paren
|
259
|
+
if arguments[0] == :args_add_block
|
260
|
+
if arguments[1].is_a?(Array)
|
261
|
+
arguments[1].map { |a| resolve_argument(a) }
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def resolve_argument(argument)
|
267
|
+
if argument[0] == :symbol_literal
|
268
|
+
# [:symbol_literal, [:symbol, {:const=>"C"}]]
|
269
|
+
if argument[1].is_a?(Array)
|
270
|
+
if argument[1][0] == :symbol
|
271
|
+
argument[1][1] # {:const=>"C"}
|
272
|
+
end
|
273
|
+
end
|
274
|
+
elsif argument[0] == :string_literal
|
275
|
+
# [:string_literal, [:string_content, {:tstring_content=>"C"}]]
|
276
|
+
if argument[1].is_a?(Array)
|
277
|
+
if argument[1][0] == :string_content
|
278
|
+
argument[1][1] # {:tstring_content=>"C"}
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
237
284
|
def on_fcall(operation)
|
238
285
|
method_call(operation, nil) if is_ident?(operation)
|
239
286
|
end
|
240
287
|
|
288
|
+
def on_method_add_arg(method, arguments)
|
289
|
+
|
290
|
+
if method[0] == :fcall &&
|
291
|
+
scanner_event?(method[1]) &&
|
292
|
+
method[1][:ident] == "autoload"
|
293
|
+
if arguments = resolve_arguments(arguments)
|
294
|
+
if [:const, :tstring_content].include?(arguments[0].keys.first)
|
295
|
+
constant_access(arguments[0], arguments[0].values.first)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
keep_walking(method, arguments)
|
300
|
+
end
|
301
|
+
|
241
302
|
# primary_value => anything
|
242
303
|
# operation2 : tIDENTIFIER
|
243
304
|
# | tCONSTANT
|
@@ -277,9 +338,9 @@ module Reflexive
|
|
277
338
|
def on_call(receiver, dot, method)
|
278
339
|
if rcv = resolve_receiver(receiver)
|
279
340
|
method_call(method, [rcv])
|
280
|
-
else
|
281
|
-
keep_walking(receiver)
|
282
341
|
end
|
342
|
+
|
343
|
+
keep_walking(receiver)
|
283
344
|
end
|
284
345
|
|
285
346
|
def on_var_ref(ref_event)
|
@@ -328,8 +389,8 @@ module Reflexive
|
|
328
389
|
|
329
390
|
def method_call(scanner_event, receiver, *args)
|
330
391
|
unless receiver
|
331
|
-
# implict self concept
|
332
|
-
receiver = @scope.
|
392
|
+
# implict self concept (will be fetched from constant_access_scope)
|
393
|
+
receiver = @scope.last == :instance ? :instance : :class
|
333
394
|
end
|
334
395
|
merge_tags(scanner_event,
|
335
396
|
{:method_call =>
|
@@ -1,70 +1,91 @@
|
|
1
1
|
require "cgi" unless defined?(CGI) && defined?(CGI::escape)
|
2
2
|
|
3
|
-
module
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
else
|
11
|
-
new_method_path(receiver.join("::"), :class, name)
|
12
|
-
end rescue(r(method_call_tag))
|
13
|
-
end
|
3
|
+
module Reflexive
|
4
|
+
module RoutingHelpers
|
5
|
+
# method_call_tag is the scanner event tag emitted by ReflexiveRipper
|
6
|
+
def method_call_path(method_call_tag)
|
7
|
+
# r method_call_tag.values_at(:name, :receiver)
|
8
|
+
name, receiver, scope = method_call_tag.values_at(:name, :receiver, :scope)
|
9
|
+
scope = scope.join("::")
|
14
10
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
11
|
+
if receiver == :class
|
12
|
+
scope = "Kernel" if scope.empty?
|
13
|
+
new_method_path(scope, :class, name)
|
14
|
+
elsif receiver == :instance
|
15
|
+
scope = "Kernel" if scope.empty?
|
16
|
+
new_method_path(scope, :instance, name)
|
17
|
+
else
|
18
|
+
receiver = receiver.join("::")
|
19
|
+
new_method_path(Reflexive.constant_lookup(receiver, scope), :class, name)
|
20
|
+
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
# if receiver.last == :instance
|
23
|
+
# new_method_path(receiver[0..-2].join("::"), :instance, name)
|
24
|
+
# else
|
25
|
+
# new_method_path(receiver.join("::"), :class, name)
|
26
|
+
# end rescue(r(method_call_tag))
|
27
|
+
end
|
25
28
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
# entry point for method links (may dispatch to
|
30
|
+
# class_method_definition_path or method_documentation_path based on whether
|
31
|
+
# the method definition was found by with our reflection capabilities)
|
32
|
+
def new_method_path(constant, level, method_name)
|
33
|
+
"/reflexive/constants/#{ constant }/#{ level }_methods/#{ CGI.escape(method_name.to_s) }"
|
34
|
+
end
|
29
35
|
|
30
|
-
|
31
|
-
|
32
|
-
|
36
|
+
def method_path(constant, method_name)
|
37
|
+
"/reflexive/constants/#{ constant }/methods/#{ CGI.escape(method_name.to_s) }"
|
38
|
+
end
|
33
39
|
|
34
|
-
|
35
|
-
|
36
|
-
|
40
|
+
def new_method_definition_path(constant, level, method_name)
|
41
|
+
new_method_path(constant, level, method_name) + "/definition"
|
42
|
+
end
|
37
43
|
|
38
|
-
|
39
|
-
|
40
|
-
|
44
|
+
def class_method_definition_path(constant, method_name)
|
45
|
+
new_method_path(constant, :class, method_name) + "/definition"
|
46
|
+
end
|
41
47
|
|
42
|
-
|
43
|
-
|
44
|
-
|
48
|
+
def instance_method_definition_path(constant, method_name)
|
49
|
+
new_method_path(constant, :instance, method_name) + "/definition"
|
50
|
+
end
|
45
51
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
52
|
+
def method_documentation_path(constant, level, method_name)
|
53
|
+
new_method_path(constant, level, method_name) + "/apidock"
|
54
|
+
end
|
50
55
|
|
51
|
-
|
52
|
-
|
53
|
-
|
56
|
+
def dashboard_path
|
57
|
+
"/reflexive/dashboard"
|
58
|
+
end
|
54
59
|
|
55
|
-
|
56
|
-
|
57
|
-
|
60
|
+
def up_path(path)
|
61
|
+
file_path(File.expand_path("../", path))
|
62
|
+
end
|
58
63
|
|
59
|
-
|
60
|
-
|
61
|
-
|
64
|
+
def file_path(path)
|
65
|
+
File.join("/reflexive/files", path)
|
66
|
+
end
|
62
67
|
|
63
|
-
|
64
|
-
|
65
|
-
|
68
|
+
def constant_lookup_path(name, scope)
|
69
|
+
"/reflexive/constant_lookup" <<
|
70
|
+
"?name=#{ CGI.escape(name) }&scope=#{ CGI.escape(scope.join("::"))}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def load_path_lookup_path(path)
|
74
|
+
"/reflexive/load_path_lookup?path=#{ CGI.escape(path.to_s) }"
|
75
|
+
end
|
76
|
+
|
77
|
+
def constant_path(constant)
|
78
|
+
"/reflexive/constants/#{ constant }"
|
79
|
+
end
|
80
|
+
|
81
|
+
def apidock_path(constant, level, method_name)
|
82
|
+
path = "http://apidock.com/ruby/#{ constant }/#{ CGI.escape(method_name.to_s) }"
|
83
|
+
path << "/class" if level == :class
|
84
|
+
path
|
85
|
+
end
|
66
86
|
|
67
|
-
|
68
|
-
|
87
|
+
def method_definition_path(constant, level, method_name)
|
88
|
+
method_path(constant, method_name) + "/definition"
|
89
|
+
end
|
69
90
|
end
|
70
91
|
end
|
data/reflexive.gemspec
CHANGED
@@ -13,13 +13,16 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.required_ruby_version = '>= 1.9.1'
|
14
14
|
|
15
15
|
# keeping this in sync with Gemfile manually
|
16
|
-
s.add_dependency "rack"
|
17
|
-
s.add_dependency "sinatra"
|
18
|
-
s.add_dependency "sinatra_more"
|
19
|
-
s.add_dependency "coderay"
|
20
|
-
s.add_dependency "rdiscount"
|
16
|
+
s.add_dependency "rack", "1.1.0"
|
17
|
+
s.add_dependency "sinatra", "1.0"
|
18
|
+
s.add_dependency "sinatra_more", "0.3.40"
|
19
|
+
s.add_dependency "coderay", "0.9.3"
|
20
|
+
# s.add_dependency "rdiscount"
|
21
21
|
|
22
22
|
s.add_development_dependency "rails", "3.0.0.beta3"
|
23
23
|
s.add_development_dependency "rspec", "2.0.0.beta.8"
|
24
|
-
s.add_development_dependency "sinatra-reloader"
|
24
|
+
s.add_development_dependency "sinatra-reloader", "0.4.1"
|
25
|
+
s.add_development_dependency "thin", "1.2.7"
|
26
|
+
s.add_development_dependency "rack-test", "0.5.3"
|
27
|
+
s.add_development_dependency "webrat", "0.7.1"
|
25
28
|
end
|
@@ -11,6 +11,12 @@ describe Reflexive::CodeRayHtmlEncoder do
|
|
11
11
|
{:constant_access=>{:name=>"Cons", :scope=>[]}}]]).should(include("<a href"))
|
12
12
|
end
|
13
13
|
|
14
|
+
it "emits constant links for :content tokens" do
|
15
|
+
encoder = Reflexive::CodeRayHtmlEncoder.new(:wrap => :div, :css => :style)
|
16
|
+
encoder.encode_tokens([["Cons", :content,
|
17
|
+
{:constant_access=>{:name=>"Cons", :scope=>[]}}]]).should(include("<a href"))
|
18
|
+
end
|
19
|
+
|
14
20
|
it "emits links with proper nesting info" do
|
15
21
|
tokens = [["Cons", :constant,
|
16
22
|
{:constant_access=>{:name=>"Cons", :scope=>["A", "B"]}}]]
|
@@ -26,7 +32,7 @@ describe Reflexive::CodeRayHtmlEncoder do
|
|
26
32
|
it "emits class method links" do
|
27
33
|
tokens = [ [
|
28
34
|
"m!", :ident,
|
29
|
-
{:method_call=>{:name=>"m!", :receiver=>["A"]} }
|
35
|
+
{:method_call=>{:name=>"m!", :receiver=>:class, :scope=>["A"]} }
|
30
36
|
] ]
|
31
37
|
encoder.encode_tokens(tokens).should include("/constants/A/class_methods/m%21")
|
32
38
|
end
|
@@ -34,7 +40,7 @@ describe Reflexive::CodeRayHtmlEncoder do
|
|
34
40
|
it "emits instance method links" do
|
35
41
|
tokens = [ [
|
36
42
|
"m!", :ident,
|
37
|
-
{:method_call=>{:name=>"m!", :receiver=>["A"
|
43
|
+
{:method_call=>{:name=>"m!", :receiver=>:instance, :scope => ["A"]} }
|
38
44
|
] ]
|
39
45
|
encoder.encode_tokens(tokens).should include("/constants/A/instance_methods/m%21")
|
40
46
|
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
require "reflexive/application"
|
2
|
+
require "rack/test"
|
3
|
+
require "nokogiri"
|
4
|
+
require "webrat/core/matchers"
|
5
|
+
|
6
|
+
FIXTURE_FILE_PATH = File.expand_path("../integration_spec_fixture.rb", __FILE__)
|
7
|
+
require FIXTURE_FILE_PATH
|
8
|
+
|
9
|
+
describe Reflexive::Application do
|
10
|
+
include Rack::Test::Methods
|
11
|
+
include Webrat::Matchers
|
12
|
+
|
13
|
+
include Reflexive::RoutingHelpers
|
14
|
+
|
15
|
+
def app
|
16
|
+
Reflexive::Application
|
17
|
+
end
|
18
|
+
|
19
|
+
it "shows dashboard" do
|
20
|
+
get(dashboard_path)
|
21
|
+
last_response.should be_ok
|
22
|
+
last_response.body.should include("Reflexive", "$LOAD_PATH", "Favorites")
|
23
|
+
last_response.body.should have_selector('a', :content => "Date")
|
24
|
+
last_response.body.should have_selector('a', :content => "Gem")
|
25
|
+
last_response.body.should have_selector('a', :content => "FileUtils")
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "class/module browser" do
|
29
|
+
def constant_browser_for(constant)
|
30
|
+
get(constant_path(constant))
|
31
|
+
last_response.should be_ok
|
32
|
+
last_response.body
|
33
|
+
end
|
34
|
+
|
35
|
+
it "shows class name" do
|
36
|
+
get(constant_path("OpenStruct"))
|
37
|
+
last_response.should be_ok
|
38
|
+
last_response.body.should include("OpenStruct")
|
39
|
+
end
|
40
|
+
|
41
|
+
it "shows files in which class is defined" do
|
42
|
+
constant_browser_for("OpenStruct").
|
43
|
+
should include("ostruct.rb")
|
44
|
+
constant_browser_for("IntegrationSpecFixture::TestClass").
|
45
|
+
should include("integration_spec_fixture.rb")
|
46
|
+
end
|
47
|
+
|
48
|
+
it "shows superclass" do
|
49
|
+
constant_browser_for("IntegrationSpecFixture::TestClass").
|
50
|
+
should include("TestBaseClass")
|
51
|
+
constant_browser_for("OpenStruct").
|
52
|
+
should include("BasicObject")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "shows instance methods" do
|
56
|
+
constant_browser_for("IntegrationSpecFixture::TestClass").
|
57
|
+
should include("public_meth", "protected_meth", "private_meth")
|
58
|
+
end
|
59
|
+
|
60
|
+
it "shows class methods" do
|
61
|
+
constant_browser_for("IntegrationSpecFixture::TestClass").
|
62
|
+
should include("class_meth")
|
63
|
+
end
|
64
|
+
|
65
|
+
it "shows inherited instance methods" do
|
66
|
+
constant_browser_for("IntegrationSpecFixture::TestClass").
|
67
|
+
should include("inherited_meth")
|
68
|
+
end
|
69
|
+
|
70
|
+
it "shows inherited class methods" do
|
71
|
+
constant_browser_for("IntegrationSpecFixture::TestClass").
|
72
|
+
should include("inherited_class_meth")
|
73
|
+
end
|
74
|
+
|
75
|
+
it "shows instance methods for module" do
|
76
|
+
constant_browser_for("IntegrationSpecFixture::TestModule").
|
77
|
+
should include("module_meth")
|
78
|
+
end
|
79
|
+
|
80
|
+
it "shows class methods for module" do
|
81
|
+
constant_browser_for("IntegrationSpecFixture::TestModule").
|
82
|
+
should include("module_class_meth")
|
83
|
+
end
|
84
|
+
|
85
|
+
it "shows classes module is included in" do
|
86
|
+
constant_browser_for("IntegrationSpecFixture::TestModule").
|
87
|
+
should include("TestClass")
|
88
|
+
end
|
89
|
+
|
90
|
+
it "shows classes class is derived from" do
|
91
|
+
constant_browser_for("IntegrationSpecFixture::TestBaseClass").
|
92
|
+
should include("TestClass")
|
93
|
+
end
|
94
|
+
|
95
|
+
it "shows classes nested inside the class" do
|
96
|
+
constant_browser_for("IntegrationSpecFixture::TestClass").
|
97
|
+
should have_selector("a", :content => "NestedClass")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "source browser" do
|
102
|
+
def source_browser
|
103
|
+
get(file_path(FIXTURE_FILE_PATH))
|
104
|
+
last_response.should be_ok
|
105
|
+
last_response.body
|
106
|
+
end
|
107
|
+
|
108
|
+
it "shows arbitrary files from file system" do
|
109
|
+
get(file_path(FIXTURE_FILE_PATH))
|
110
|
+
last_response.should be_ok
|
111
|
+
last_response.body.should include("integration_spec_fixture.rb")
|
112
|
+
end
|
113
|
+
|
114
|
+
it "browses directories" do
|
115
|
+
dir = File.dirname(FIXTURE_FILE_PATH)
|
116
|
+
get(file_path(dir))
|
117
|
+
last_response.should be_ok
|
118
|
+
|
119
|
+
Dir["#{ dir }/*"].each do |path|
|
120
|
+
last_response.body.should include(File.basename(path))
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it "highlights the code" do
|
125
|
+
source_browser.should have_selector("span.no")
|
126
|
+
source_browser.should have_selector("span.s")
|
127
|
+
source_browser.should have_selector("span.r")
|
128
|
+
source_browser.should have_selector("span.co")
|
129
|
+
end
|
130
|
+
|
131
|
+
it "links class names" do
|
132
|
+
source_browser.should have_selector('a[href$="constant_lookup?name=TestBaseClass&scope=IntegrationSpecFixture"]')
|
133
|
+
end
|
134
|
+
|
135
|
+
it "links module names" do
|
136
|
+
source_browser.should have_selector('a[href$="constant_lookup?name=IntegrationSpecFixture&scope="]')
|
137
|
+
end
|
138
|
+
|
139
|
+
it "links arguments to require/load" do
|
140
|
+
source_browser.should have_selector('a[href$="load_path_lookup?path=ostruct"]')
|
141
|
+
end
|
142
|
+
|
143
|
+
it "links method calls from top level" do
|
144
|
+
source_browser.should have_selector('a[href$="constants/Kernel/class_methods/require"]')
|
145
|
+
end
|
146
|
+
|
147
|
+
it "links method calls from class instance level" do
|
148
|
+
source_browser.should have_selector('a[href$="constants/IntegrationSpecFixture::TestClass/class_methods/inherited_class_meth"]')
|
149
|
+
end
|
150
|
+
|
151
|
+
it "links method calls from class definition level" do
|
152
|
+
source_browser.should have_selector('a[href$="constants/IntegrationSpecFixture::TestClass/class_methods/another_inherited_class_meth"]')
|
153
|
+
end
|
154
|
+
|
155
|
+
it "links local variable assignments and access" do
|
156
|
+
source_browser.should have_selector('span[id^="lv:"][id$=":local_var"]', :content => "local_var") do |local_var_assignment|
|
157
|
+
source_browser.should have_selector('a[href="#' + local_var_assignment.first["id"] + '"]')
|
158
|
+
end
|
159
|
+
source_browser.should have_selector('span[id^="lv:"][id$=":another_local_var"]', :content => "another_local_var")
|
160
|
+
# source_browser.should have_selector('a.lva', :content => "another_local_var")
|
161
|
+
end
|
162
|
+
|
163
|
+
it "links method calls" do
|
164
|
+
source_browser.should have_selector('a[href$="constants/IntegrationSpecFixture::TestClass/instance_methods/not_defined_meth"]', :content => "not_defined_meth")
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "constant lookup" do
|
169
|
+
it "redirects to found constant" do
|
170
|
+
get(constant_lookup_path("TestModule", ["IntegrationSpecFixture::TestClass"]))
|
171
|
+
|
172
|
+
last_response.should be_redirect
|
173
|
+
last_response.body.should be_empty
|
174
|
+
|
175
|
+
follow_redirect!
|
176
|
+
|
177
|
+
last_response.body.should match(/module\s+IntegrationSpecFixture::TestModule/)
|
178
|
+
last_response.body.should include("integration_spec_fixture.rb")
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe "method lookup" do
|
183
|
+
it "redirects to found method" do
|
184
|
+
get(new_method_path("IntegrationSpecFixture::TestClass", :instance, "inherited_meth"))
|
185
|
+
|
186
|
+
last_response.should be_redirect
|
187
|
+
last_response.body.should be_empty
|
188
|
+
|
189
|
+
follow_redirect!
|
190
|
+
|
191
|
+
last_request.path.should include("constants/IntegrationSpecFixture::TestClass/instance_methods/inherited_meth/definition")
|
192
|
+
end
|
193
|
+
|
194
|
+
it "shows error message when method is not found" do
|
195
|
+
get(new_method_path("IntegrationSpecFixture::TestClass", :instance, "not_defined_meth"))
|
196
|
+
|
197
|
+
last_response.should be_ok
|
198
|
+
last_response.body.should include("Reflexive Error")
|
199
|
+
end
|
200
|
+
|
201
|
+
it "redirect to documentation for core methods" do
|
202
|
+
get(new_method_path("IntegrationSpecFixture::TestClass", :class, "class_eval"))
|
203
|
+
|
204
|
+
last_response.should be_redirect
|
205
|
+
|
206
|
+
follow_redirect!
|
207
|
+
|
208
|
+
last_request.path.should include("constants/Module/instance_methods/class_eval/apidock")
|
209
|
+
end
|
210
|
+
|
211
|
+
it "uses heuristics providing user a way to choose method for module instance methods" do
|
212
|
+
get(new_method_path("IntegrationSpecFixture::HeuristicLookupBaseModule", :instance, "meth"))
|
213
|
+
|
214
|
+
last_response.should be_ok
|
215
|
+
last_response.body.should include("HeuristicLookupIncludingClass1")
|
216
|
+
last_response.body.should include("HeuristicLookupIncludingClass2")
|
217
|
+
end
|
218
|
+
|
219
|
+
it "uses heuristics providing user a way to choose method for class instance methods" do
|
220
|
+
get(new_method_path("IntegrationSpecFixture::HeuristicLookupBaseClass", :instance, "meth"))
|
221
|
+
|
222
|
+
last_response.should be_ok
|
223
|
+
last_response.body.should include("HeuristicLookupInheritingClass1")
|
224
|
+
last_response.body.should include("HeuristicLookupInheritingClass2")
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|