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.



225
226
227
228
229
230
231
232
233
234
# File 'lib/ripper-tags/parser.rb', line 225

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.



223
224
225
# File 'lib/ripper-tags/parser.rb', line 223

def tags
  @tags
end

Instance Method Details

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



236
237
238
239
240
241
242
243
244
245
# File 'lib/ripper-tags/parser.rb', line 236

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



328
329
330
331
332
333
334
335
336
# File 'lib/ripper-tags/parser.rb', line 328

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



305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/ripper-tags/parser.rb', line 305

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

  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



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

def on_call(*args)
end

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



295
296
297
# File 'lib/ripper-tags/parser.rb', line 295

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

#on_class_eval(name, body) ⇒ Object



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

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

#on_def(name, line) ⇒ Object



338
339
340
341
342
343
344
345
346
# File 'lib/ripper-tags/parser.rb', line 338

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_defs(klass, name, line) ⇒ Object



348
349
350
351
352
353
354
# File 'lib/ripper-tags/parser.rb', line 348

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



291
292
293
# File 'lib/ripper-tags/parser.rb', line 291

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

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



262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/ripper-tags/parser.rb', line 262

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



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

def on_private()   @current_access = 'private'   end

#on_protectedObject



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

def on_protected() @current_access = 'protected' end

#on_publicObject



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

def on_public()    @current_access = 'public'    end

#on_rails_def(kind, name, line) ⇒ Object



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

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



366
367
368
369
370
371
372
373
374
# File 'lib/ripper-tags/parser.rb', line 366

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



247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/ripper-tags/parser.rb', line 247

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
    __send__("on_#{name}", *args) unless name.to_s.index("@") == 0
  when String, nil
    # nothing
  end
end