Class: RipperTags::Visitor

Inherits:
Object
  • Object
show all
Defined in:
lib/ripper-tags/parser.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sexp, path, data) ⇒ Visitor

Returns a new instance of Visitor.



358
359
360
361
362
363
364
365
366
367
# File 'lib/ripper-tags/parser.rb', line 358

def initialize(sexp, path, data)
  @path = path
  @lines = data.split("\n")
  @namespace = []
  @tags = []
  @is_singleton = false
  @current_access = nil

  process(sexp)
end

Instance Attribute Details

#tagsObject (readonly)

Returns the value of attribute tags.



356
357
358
# File 'lib/ripper-tags/parser.rb', line 356

def tags
  @tags
end

Instance Method Details

#emit_tag(kind, line, opts = {}) ⇒ Object



369
370
371
372
373
374
375
376
377
378
# File 'lib/ripper-tags/parser.rb', line 369

def emit_tag(kind, line, opts={})
  @tags << {
    :kind => kind.to_s,
    :line => line,
    :language => 'Ruby',
    :path => @path,
    :pattern => @lines[line-1].chomp,
    :access => @current_access
  }.update(opts).delete_if{ |k,v| v.nil? }
end

#ignore(*args) ⇒ Object Also known as: on_aref_field, on_field, on_fcall, on_args, on_assoc, on_!



553
554
# File 'lib/ripper-tags/parser.rb', line 553

def ignore(*args)
end

#on_alias(name, other, line) ⇒ Object



473
474
475
476
477
478
479
480
481
# File 'lib/ripper-tags/parser.rb', line 473

def on_alias(name, other, line)
  ns = (@namespace.empty?? 'Object' : @namespace.join('::'))

  emit_tag :alias, line,
    :name => name,
    :inherits => other,
    :full_name => "#{ns}#{@is_singleton ? '.' : '#'}#{name}",
    :class => ns
end

#on_assign(name, rhs, line, *junk) ⇒ Object

Ripper trips up on keyword arguments in pre-2.1 Ruby and supplies extra arguments that we just ignore here



448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
# File 'lib/ripper-tags/parser.rb', line 448

def on_assign(name, rhs, line, *junk)
  return unless name =~ /^[A-Z]/ && junk.empty?

  if rhs && :call == rhs[0] && rhs[1] && "#{rhs[1][0]}.#{rhs[2]}" =~ /^(Class|Module|Struct)\.new$/
    kind = $1 == 'Module' ? :module : :class
    superclass = $1 == 'Class' ? rhs[3] : nil
    superclass.flatten! if superclass
    return on_module_or_class(kind, [name, line], superclass, rhs[4])
  end

  namespace = @namespace
  if name.include?('::')
    parts = name.split('::')
    name = parts.pop
    namespace = namespace + parts
  end

  process(rhs)

  emit_tag :constant, line,
    :name => name,
    :full_name => (namespace + [name]).join('::'),
    :class => namespace.join('::')
end

#on_call(*args) ⇒ Object



549
550
551
# File 'lib/ripper-tags/parser.rb', line 549

def on_call(*args)
  process(args)
end

#on_class(name, superclass, *body) ⇒ Object



431
432
433
# File 'lib/ripper-tags/parser.rb', line 431

def on_class(name, superclass, *body)
  on_module_or_class(:class, name, superclass, *body)
end

#on_class_eval(name, body) ⇒ Object



541
542
543
544
545
546
547
# File 'lib/ripper-tags/parser.rb', line 541

def on_class_eval(name, body)
  name, _ = *name
  @namespace << name
  process(body)
ensure
  @namespace.pop
end

#on_def(name, line) ⇒ Object



483
484
485
486
487
488
489
490
491
# File 'lib/ripper-tags/parser.rb', line 483

def on_def(name, line)
  kind = @is_singleton ? 'singleton method' : 'method'
  ns = (@namespace.empty?? 'Object' : @namespace.join('::'))

  emit_tag kind, line,
    :name => name,
    :full_name => "#{ns}#{@is_singleton ? '.' : '#'}#{name}",
    :class => ns
end

#on_def_with_access(klass, name, access, line) ⇒ Object



501
502
503
504
505
506
507
508
509
510
511
# File 'lib/ripper-tags/parser.rb', line 501

def on_def_with_access(klass, name, access, line)
  ns = (@namespace.empty? ? 'Object' : @namespace.join('::'))
  singleton = @is_singleton || klass == 'self'
  kind = singleton ? 'singleton method' : 'method'

  emit_tag kind, line,
    :name => name,
    :full_name => "#{ns}#{singleton ? '.' : '#'}#{name}",
    :class => ns,
    :access => access
end

#on_defs(klass, name, line) ⇒ Object



493
494
495
496
497
498
499
# File 'lib/ripper-tags/parser.rb', line 493

def on_defs(klass, name, line)
  ns = (@namespace + [klass != 'self' ? klass : nil]).compact
  emit_tag 'singleton method', line,
    :name => name,
    :full_name => ns.join('::') + ".#{name}",
    :class => ns.join('::')
end

#on_module(name, *body) ⇒ Object



427
428
429
# File 'lib/ripper-tags/parser.rb', line 427

def on_module(name, *body)
  on_module_or_class(:module, name, nil, *body)
end

#on_module_functionObject



441
442
443
444
# File 'lib/ripper-tags/parser.rb', line 441

def on_module_function()
  @is_singleton = true
  @current_access = 'public'
end

#on_module_or_class(kind, name, superclass, *body) ⇒ Object



398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
# File 'lib/ripper-tags/parser.rb', line 398

def on_module_or_class(kind, name, superclass, *body)
  name, line = *name
  @namespace << name

  prev_access = @current_access
  @current_access = nil

  if superclass
    superclass_name = superclass[0] == :call ?
      superclass[1] :
      superclass[0]
    superclass_name = nil unless superclass_name =~ /^[A-Z]/
  end
  full_name = @namespace.join('::')
  parts = full_name.split('::')
  class_name = parts.pop

  emit_tag kind, line,
    :full_name => full_name,
    :name => class_name,
    :class => parts.any? && parts.join('::') || nil,
    :inherits => superclass_name

  process(body)
ensure
  @current_access = prev_access
  @namespace.pop
end

#on_privateObject



435
# File 'lib/ripper-tags/parser.rb', line 435

def on_private()              @current_access = 'private'   end

#on_private_class_methodObject



438
# File 'lib/ripper-tags/parser.rb', line 438

def on_private_class_method() @current_access = 'private'   end

#on_protectedObject



436
# File 'lib/ripper-tags/parser.rb', line 436

def on_protected()            @current_access = 'protected' end

#on_publicObject



437
# File 'lib/ripper-tags/parser.rb', line 437

def on_public()               @current_access = 'public'    end

#on_public_class_methodObject



439
# File 'lib/ripper-tags/parser.rb', line 439

def on_public_class_method()  @current_access = 'public'    end

#on_rails_def(kind, name, line) ⇒ Object



521
522
523
524
525
526
527
528
529
# File 'lib/ripper-tags/parser.rb', line 521

def on_rails_def(kind, name, line)
  ns = (@namespace.empty?? 'Object' : @namespace.join('::'))

  emit_tag kind, line,
    :language => 'Rails',
    :name => name,
    :full_name => "#{ns}.#{name}",
    :class => ns
end

#on_redefine_access(klass, name, access, line) ⇒ Object



513
514
515
516
517
518
519
# File 'lib/ripper-tags/parser.rb', line 513

def on_redefine_access(klass, name, access, line)
  ns = (@namespace.empty? ? 'Object' : @namespace.join('::'))
  singleton = @is_singleton || klass == 'self'
  full_name = "#{ns}#{singleton ? '.' : '#'}#{name}"
  tag = @tags.select { |t| t[:full_name] == full_name }.last
  tag[:access] = access if tag
end

#on_sclass(name, body) ⇒ Object



531
532
533
534
535
536
537
538
539
# File 'lib/ripper-tags/parser.rb', line 531

def on_sclass(name, body)
  name, _ = *name
  @namespace << name unless name == 'self'
  prev_is_singleton, @is_singleton = @is_singleton, true
  process(body)
ensure
  @namespace.pop     unless name == 'self'
  @is_singleton = prev_is_singleton
end

#process(sexp) ⇒ Object



380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
# File 'lib/ripper-tags/parser.rb', line 380

def process(sexp)
  return unless sexp
  return if Symbol === sexp

  case sexp[0]
  when Array
    sexp.each{ |child| process(child) }
  when Symbol
    name, *args = sexp
    name = name.to_s
    if name.index("@") != 0 && name.index("-@") != 0
      __send__("on_#{name}", *args)
    end
  when String, nil
    # nothing
  end
end