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.



310
311
312
313
314
315
316
317
318
319
# File 'lib/ripper-tags/parser.rb', line 310

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.



308
309
310
# File 'lib/ripper-tags/parser.rb', line 308

def tags
  @tags
end

Instance Method Details

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



321
322
323
324
325
326
327
328
329
330
# File 'lib/ripper-tags/parser.rb', line 321

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

#on_alias(name, other, line) ⇒ Object



420
421
422
423
424
425
426
427
428
# File 'lib/ripper-tags/parser.rb', line 420

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



395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
# File 'lib/ripper-tags/parser.rb', line 395

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 Also known as: on_aref_field, on_field, on_fcall, on_args, on_assoc, on_!



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

def on_call(*args)
end

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



383
384
385
# File 'lib/ripper-tags/parser.rb', line 383

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

#on_class_eval(name, body) ⇒ Object



480
481
482
483
484
485
486
# File 'lib/ripper-tags/parser.rb', line 480

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

#on_def(name, line) ⇒ Object



430
431
432
433
434
435
436
437
438
# File 'lib/ripper-tags/parser.rb', line 430

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



448
449
450
451
452
453
454
455
456
457
458
# File 'lib/ripper-tags/parser.rb', line 448

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



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

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



379
380
381
# File 'lib/ripper-tags/parser.rb', line 379

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

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



350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'lib/ripper-tags/parser.rb', line 350

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



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

def on_private()              @current_access = 'private'   end

#on_private_class_methodObject



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

def on_private_class_method() @current_access = 'private'   end

#on_protectedObject



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

def on_protected()            @current_access = 'protected' end

#on_publicObject



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

def on_public()               @current_access = 'public'    end

#on_public_class_methodObject



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

def on_public_class_method()  @current_access = 'public'    end

#on_rails_def(kind, name, line) ⇒ Object



460
461
462
463
464
465
466
467
468
# File 'lib/ripper-tags/parser.rb', line 460

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_sclass(name, body) ⇒ Object



470
471
472
473
474
475
476
477
478
# File 'lib/ripper-tags/parser.rb', line 470

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



332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/ripper-tags/parser.rb', line 332

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