1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
require 'rdoc'
require 'rdoc/code_objects'
require 'rdoc/markup/preprocess'
require 'rdoc/stats'
##
# A parser is simple a class that implements
#
# #initialize(file_name, body, options)
#
# and
#
# #scan
#
# The initialize method takes a file name to be used, the body of the file,
# and an RDoc::Options object. The scan method is then called to return an
# appropriately parsed TopLevel code object.
#
# The ParseFactory is used to redirect to the correct parser given a
# filename extension. This magic works because individual parsers have to
# register themselves with us as they are loaded in. The do this using the
# following incantation
#
# require "rdoc/parser"
#
# class RDoc::Parser::Xyz < RDoc::Parser
# parse_files_matching /\.xyz$/ # <<<<
#
# def initialize(file_name, body, options)
# ...
# end
#
# def scan
# ...
# end
# end
#
# Just to make life interesting, if we suspect a plain text file, we also
# look for a shebang line just in case it's a potential shell script
class RDoc::Parser
@parsers = []
class << self
attr_reader :parsers
end
##
# Alias an extension to another extension. After this call, files ending
# "new_ext" will be parsed using the same parser as "old_ext"
def self.alias_extension(old_ext, new_ext)
old_ext = old_ext.sub(/^\.(.*)/, '\1')
new_ext = new_ext.sub(/^\.(.*)/, '\1')
parser = can_parse "xxx.#{old_ext}"
return false unless parser
RDoc::Parser.parsers.unshift [/\.#{new_ext}$/, parser]
true
end
##
# Return _true_ if the +file+ seems like binary.
def self.binary?(file)
s = File.read(file, 1024) or return false
s.count("^ -~\t\r\n").fdiv(s.size) > 0.3 || s.index("\x00")
end
private_class_method :binary?
##
# Return a parser that can handle a particular extension
def self.can_parse(file_name)
parser = RDoc::Parser.parsers.find { |regexp,| regexp =~ file_name }.last
#
# The default parser should *NOT* parse binary files.
#
if parser == RDoc::Parser::Simple then
if binary? file_name then
return nil
end
end
return parser
end
##
# Find the correct parser for a particular file name. Return a SimpleParser
# for ones that we don't know
def self.for(top_level, file_name, body, options, stats)
# If no extension, look for shebang
if file_name !~ /\.\w+$/ && body =~ %r{\A#!(.+)} then
shebang = $1
case shebang
when %r{env\s+ruby}, %r{/ruby}
file_name = "dummy.rb"
end
end
parser = can_parse file_name
#
# This method must return a parser.
#
if !parser then
parser = RDoc::Parser::Simple
end
parser.new top_level, file_name, body, options, stats
end
##
# Record which file types this parser can understand.
def self.parse_files_matching(regexp)
RDoc::Parser.parsers.unshift [regexp, self]
end
def initialize(top_level, file_name, content, options, stats)
@top_level = top_level
@file_name = file_name
@content = content
@options = options
@stats = stats
end
end
require 'rdoc/parser/simple'
|