sexp_processor 4.3.0 → 4.4.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.tar.gz.sig +0 -0
- data/History.txt +6 -0
- data/lib/sexp_processor.rb +200 -1
- data/test/test_sexp_processor.rb +75 -0
- metadata +12 -12
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/History.txt
CHANGED
data/lib/sexp_processor.rb
CHANGED
@@ -33,7 +33,7 @@ require 'sexp'
|
|
33
33
|
|
34
34
|
class SexpProcessor
|
35
35
|
|
36
|
-
VERSION = "4.
|
36
|
+
VERSION = "4.4.0"
|
37
37
|
|
38
38
|
##
|
39
39
|
# Automatically shifts off the Sexp type before handing the
|
@@ -404,6 +404,205 @@ class SexpInterpreter < SexpProcessor
|
|
404
404
|
end
|
405
405
|
end
|
406
406
|
|
407
|
+
##
|
408
|
+
# A simple subclass of SexpProcessor that tracks method and class
|
409
|
+
# stacks for you. Use #method_name, #klass_name, or #signature to
|
410
|
+
# refer to where you're at in processing. If you have to subclass
|
411
|
+
# process_(class|module|defn|defs) you _must_ call super.
|
412
|
+
|
413
|
+
class MethodBasedSexpProcessor < SexpProcessor
|
414
|
+
@@no_class = :main
|
415
|
+
@@no_method = :none
|
416
|
+
|
417
|
+
attr_reader :class_stack, :method_stack, :sclass, :method_locations
|
418
|
+
|
419
|
+
def initialize
|
420
|
+
super
|
421
|
+
@sclass = []
|
422
|
+
@class_stack = []
|
423
|
+
@method_stack = []
|
424
|
+
@method_locations = {}
|
425
|
+
self.require_empty = false
|
426
|
+
end
|
427
|
+
|
428
|
+
##
|
429
|
+
# Adds name to the class stack, for the duration of the block
|
430
|
+
|
431
|
+
def in_klass name
|
432
|
+
if Sexp === name then
|
433
|
+
name = case name.first
|
434
|
+
when :colon2 then
|
435
|
+
name = name.flatten
|
436
|
+
name.delete :const
|
437
|
+
name.delete :colon2
|
438
|
+
name.join("::")
|
439
|
+
when :colon3 then
|
440
|
+
name.last.to_s
|
441
|
+
else
|
442
|
+
raise "unknown type #{name.inspect}"
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
@class_stack.unshift name
|
447
|
+
yield
|
448
|
+
ensure
|
449
|
+
@class_stack.shift
|
450
|
+
end
|
451
|
+
|
452
|
+
##
|
453
|
+
# Adds name to the method stack, for the duration of the block
|
454
|
+
|
455
|
+
def in_method(name, file, line)
|
456
|
+
method_name = Regexp === name ? name.inspect : name.to_s
|
457
|
+
@method_stack.unshift method_name
|
458
|
+
@method_locations[signature] = "#{file}:#{line}"
|
459
|
+
yield
|
460
|
+
ensure
|
461
|
+
@method_stack.shift
|
462
|
+
end
|
463
|
+
|
464
|
+
##
|
465
|
+
# Tracks whether we're in a singleton class or not. Doesn't track
|
466
|
+
# actual receiver.
|
467
|
+
|
468
|
+
def in_sklass
|
469
|
+
@sclass.push true
|
470
|
+
yield
|
471
|
+
ensure
|
472
|
+
@sclass.pop
|
473
|
+
end
|
474
|
+
|
475
|
+
##
|
476
|
+
# Returns the first class in the list, or @@no_class if there are
|
477
|
+
# none.
|
478
|
+
|
479
|
+
def klass_name
|
480
|
+
name = @class_stack.first
|
481
|
+
|
482
|
+
if Sexp === name then
|
483
|
+
raise "you shouldn't see me"
|
484
|
+
elsif @class_stack.any?
|
485
|
+
@class_stack.reverse.join("::").sub(/\([^\)]+\)$/, '')
|
486
|
+
else
|
487
|
+
@@no_class
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
##
|
492
|
+
# Returns the first method in the list, or "#none" if there are
|
493
|
+
# none.
|
494
|
+
|
495
|
+
def method_name
|
496
|
+
m = @method_stack.first || @@no_method
|
497
|
+
m = "##{m}" unless m =~ /::/
|
498
|
+
m
|
499
|
+
end
|
500
|
+
|
501
|
+
##
|
502
|
+
# Process a class node until empty. Tracks all nesting. If you have
|
503
|
+
# to subclass and override this method, you can clall super with a
|
504
|
+
# block.
|
505
|
+
|
506
|
+
def process_class(exp)
|
507
|
+
exp.shift unless auto_shift_type # node type
|
508
|
+
in_klass exp.shift do
|
509
|
+
if block_given? then
|
510
|
+
yield
|
511
|
+
else
|
512
|
+
process_until_empty exp
|
513
|
+
end
|
514
|
+
end
|
515
|
+
s()
|
516
|
+
end
|
517
|
+
|
518
|
+
##
|
519
|
+
# Process a method node until empty. Tracks your location. If you
|
520
|
+
# have to subclass and override this method, you can clall super
|
521
|
+
# with a block.
|
522
|
+
|
523
|
+
def process_defn(exp)
|
524
|
+
exp.shift unless auto_shift_type # node type
|
525
|
+
name = @sclass.empty? ? exp.shift : "::#{exp.shift}"
|
526
|
+
in_method name, exp.file, exp.line do
|
527
|
+
if block_given? then
|
528
|
+
yield
|
529
|
+
else
|
530
|
+
process_until_empty exp
|
531
|
+
end
|
532
|
+
end
|
533
|
+
s()
|
534
|
+
end
|
535
|
+
|
536
|
+
##
|
537
|
+
# Process a singleton method node until empty. Tracks your location.
|
538
|
+
# If you have to subclass and override this method, you can clall
|
539
|
+
# super with a block.
|
540
|
+
|
541
|
+
def process_defs(exp)
|
542
|
+
exp.shift unless auto_shift_type # node type
|
543
|
+
process exp.shift # recv
|
544
|
+
in_method "::#{exp.shift}", exp.file, exp.line do
|
545
|
+
if block_given? then
|
546
|
+
yield
|
547
|
+
else
|
548
|
+
process_until_empty exp
|
549
|
+
end
|
550
|
+
end
|
551
|
+
s()
|
552
|
+
end
|
553
|
+
|
554
|
+
##
|
555
|
+
# Process a module node until empty. Tracks all nesting. If you have
|
556
|
+
# to subclass and override this method, you can clall super with a
|
557
|
+
# block.
|
558
|
+
|
559
|
+
def process_module(exp)
|
560
|
+
exp.shift unless auto_shift_type # node type
|
561
|
+
in_klass exp.shift do
|
562
|
+
if block_given? then
|
563
|
+
yield
|
564
|
+
else
|
565
|
+
process_until_empty exp
|
566
|
+
end
|
567
|
+
end
|
568
|
+
s()
|
569
|
+
end
|
570
|
+
|
571
|
+
##
|
572
|
+
# Process a singleton class node until empty. Tracks all nesting. If
|
573
|
+
# you have to subclass and override this method, you can clall super
|
574
|
+
# with a block.
|
575
|
+
|
576
|
+
def process_sclass(exp)
|
577
|
+
exp.shift unless auto_shift_type # node type
|
578
|
+
in_sklass do
|
579
|
+
if block_given? then
|
580
|
+
yield
|
581
|
+
else
|
582
|
+
process_until_empty exp
|
583
|
+
end
|
584
|
+
end
|
585
|
+
s()
|
586
|
+
end
|
587
|
+
|
588
|
+
##
|
589
|
+
# Process each element of #exp in turn.
|
590
|
+
|
591
|
+
def process_until_empty exp
|
592
|
+
until exp.empty?
|
593
|
+
sexp = exp.shift
|
594
|
+
process sexp if Sexp === sexp
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
598
|
+
##
|
599
|
+
# Returns the method signature for the current method.
|
600
|
+
|
601
|
+
def signature
|
602
|
+
"#{klass_name}#{method_name}"
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
407
606
|
class Object
|
408
607
|
|
409
608
|
##
|
data/test/test_sexp_processor.rb
CHANGED
@@ -295,3 +295,78 @@ class TestSexpProcessor < Minitest::Test
|
|
295
295
|
def test_warn_on_default=; skip; end
|
296
296
|
|
297
297
|
end
|
298
|
+
|
299
|
+
class TestMethodBasedSexpProcessor < Minitest::Test
|
300
|
+
attr_accessor :processor
|
301
|
+
|
302
|
+
def setup
|
303
|
+
self.processor = MethodBasedSexpProcessor.new
|
304
|
+
end
|
305
|
+
|
306
|
+
def test_in_klass
|
307
|
+
assert_empty processor.class_stack
|
308
|
+
|
309
|
+
processor.in_klass "xxx::yyy" do
|
310
|
+
assert_equal ["xxx::yyy"], processor.class_stack
|
311
|
+
end
|
312
|
+
|
313
|
+
assert_empty processor.class_stack
|
314
|
+
end
|
315
|
+
|
316
|
+
def test_in_method
|
317
|
+
assert_empty processor.method_stack
|
318
|
+
|
319
|
+
processor.in_method "xxx", "file.rb", 42 do
|
320
|
+
assert_equal ["xxx"], processor.method_stack
|
321
|
+
end
|
322
|
+
|
323
|
+
assert_empty processor.method_stack
|
324
|
+
|
325
|
+
expected = {"main#xxx" => "file.rb:42"}
|
326
|
+
assert_equal expected, processor.method_locations
|
327
|
+
end
|
328
|
+
|
329
|
+
def test_klass_name
|
330
|
+
assert_equal :main, processor.klass_name
|
331
|
+
|
332
|
+
processor.class_stack << "whatevs" << "flog"
|
333
|
+
assert_equal "flog::whatevs", processor.klass_name
|
334
|
+
end
|
335
|
+
|
336
|
+
def test_klass_name_sexp
|
337
|
+
processor.in_klass s(:colon2, s(:const, :X), :Y) do
|
338
|
+
assert_equal "X::Y", processor.klass_name
|
339
|
+
end
|
340
|
+
|
341
|
+
processor.in_klass s(:colon3, :Y) do
|
342
|
+
assert_equal "Y", processor.klass_name
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
def test_method_name
|
347
|
+
assert_equal "#none", processor.method_name
|
348
|
+
|
349
|
+
processor.method_stack << "whatevs"
|
350
|
+
assert_equal "#whatevs", processor.method_name
|
351
|
+
end
|
352
|
+
|
353
|
+
def test_method_name_cls
|
354
|
+
assert_equal "#none", processor.method_name
|
355
|
+
|
356
|
+
processor.method_stack << "::whatevs"
|
357
|
+
assert_equal "::whatevs", processor.method_name
|
358
|
+
end
|
359
|
+
|
360
|
+
def test_signature
|
361
|
+
assert_equal "main#none", processor.signature
|
362
|
+
|
363
|
+
processor.class_stack << "X"
|
364
|
+
assert_equal "X#none", processor.signature
|
365
|
+
|
366
|
+
processor.method_stack << "y"
|
367
|
+
assert_equal "X#y", processor.signature
|
368
|
+
|
369
|
+
processor.class_stack.shift
|
370
|
+
assert_equal "main#y", processor.signature
|
371
|
+
end
|
372
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sexp_processor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 47
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 4
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- 0
|
10
|
-
version: 4.
|
10
|
+
version: 4.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ryan Davis
|
@@ -16,9 +16,9 @@ bindir: bin
|
|
16
16
|
cert_chain:
|
17
17
|
- |
|
18
18
|
-----BEGIN CERTIFICATE-----
|
19
|
-
|
19
|
+
MIIDPjCCAiagAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMRMwEQYDVQQDDApyeWFu
|
20
20
|
ZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB
|
21
|
-
|
21
|
+
GRYDY29tMB4XDTEzMDkxNjIzMDQxMloXDTE0MDkxNjIzMDQxMlowRTETMBEGA1UE
|
22
22
|
AwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS
|
23
23
|
JomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda
|
24
24
|
b9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx
|
@@ -28,15 +28,15 @@ cert_chain:
|
|
28
28
|
qhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV
|
29
29
|
gBEfoTEGr7Zii72cx+sCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw
|
30
30
|
HQYDVR0OBBYEFEfFe9md/r/tj/Wmwpy+MI8d9k/hMA0GCSqGSIb3DQEBBQUAA4IB
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
AQCFZ7JTzoy1gcG4d8A6dmOJy7ygtO5MFpRIz8HuKCF5566nOvpy7aHhDDzFmQuu
|
32
|
+
FX3zDU6ghx5cQIueDhf2SGOncyBmmJRRYawm3wI0o1MeN6LZJ/3cRaOTjSFy6+S6
|
33
|
+
zqDmHBp8fVA2TGJtO0BLNkbGVrBJjh0UPmSoGzWlRhEVnYC33TpDAbNA+u39UrQI
|
34
|
+
ynwhNN7YbnmSR7+JU2cUjBFv2iPBO+TGuWC+9L2zn3NHjuc6tnmSYipA9y8Hv+As
|
35
|
+
Y4evBVezr3SjXz08vPqRO5YRdO3zfeMT8gBjRqZjWJGMZ2lD4XNfrs7eky74CyZw
|
36
|
+
xx3n58i0lQkBE1EpKE0lFu/y
|
37
37
|
-----END CERTIFICATE-----
|
38
38
|
|
39
|
-
date: 2013-
|
39
|
+
date: 2013-10-18 00:00:00 Z
|
40
40
|
dependencies:
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: minitest
|
metadata.gz.sig
CHANGED
Binary file
|