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 CHANGED
Binary file
data/History.txt CHANGED
@@ -1,3 +1,9 @@
1
+ === 4.4.0 / 2013-10-18
2
+
3
+ * 1 minor enhancement:
4
+
5
+ * Added MethodBasedSexpProcessor, extracted from Flog.
6
+
1
7
  === 4.3.0 / 2013-08-19
2
8
 
3
9
  * 1 minor enhancement:
@@ -33,7 +33,7 @@ require 'sexp'
33
33
 
34
34
  class SexpProcessor
35
35
 
36
- VERSION = "4.3.0"
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
  ##
@@ -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: 51
4
+ hash: 47
5
5
  prerelease:
6
6
  segments:
7
7
  - 4
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 4.3.0
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
- MIIDPjCCAiagAwIBAgIBADANBgkqhkiG9w0BAQUFADBFMRMwEQYDVQQDDApyeWFu
19
+ MIIDPjCCAiagAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMRMwEQYDVQQDDApyeWFu
20
20
  ZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB
21
- GRYDY29tMB4XDTA5MDMwNjE4NTMxNVoXDTEwMDMwNjE4NTMxNVowRTETMBEGA1UE
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
- AQAY59gYvDxqSqgC92nAP9P8dnGgfZgLxP237xS6XxFGJSghdz/nI6pusfCWKM8m
32
- vzjjH2wUMSSf3tNudQ3rCGLf2epkcU13/rguI88wO6MrE0wi4ZqLQX+eZQFskJb/
33
- w6x9W1ur8eR01s397LSMexySDBrJOh34cm2AlfKr/jokKCTwcM0OvVZnAutaovC0
34
- l1SVZ0ecg88bsWHA0Yhh7NFxK1utWoIhtB6AFC/+trM0FQEB/jZkIS8SaNzn96Rl
35
- n0sZEf77FLf5peR8TP/PtmIg7Cyqz23sLM4mCOoTGIy5OcZ8TdyiyINUHtb5ej/T
36
- FBHgymkyj/AOSqKRIpXPhjC6
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-08-19 00:00:00 Z
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