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
|
require "yard"
module YARD
module Sinatra
def self.routes
YARD::Handlers::Sinatra::AbstractRouteHandler.routes
end
def self.error_handlers
YARD::Handlers::Sinatra::AbstractRouteHandler.error_handlers
end
end
module CodeObjects
class RouteObject < MethodObject
attr_accessor :http_verb, :http_path, :real_name
def name(prefix = false)
return super unless show_real_name?
prefix ? (sep == ISEP ? "#{sep}#{real_name}" : real_name.to_s) : real_name.to_sym
end
# @see YARD::Handlers::Sinatra::AbstractRouteHandler#register_route
# @see #name
def show_real_name?
real_name and caller[1] =~ /`signature'/
end
end
end
module Handlers
# Displays Sinatra routes in YARD documentation.
# Can also be used to parse routes from files without executing those files.
module Sinatra
# Logic both handlers have in common.
module AbstractRouteHandler
def self.routes
@routes ||= []
end
def self.error_handlers
@error_handlers ||= []
end
def process
case http_verb
when 'NOT_FOUND'
register_error_handler(http_verb)
else
path = http_path
path = $1 if path =~ /^"(.*)"$/
register_route(http_verb, path)
end
end
def register_route(verb, path, doc = nil)
# HACK: Removing some illegal letters.
method_name = "" << verb << "_" << path.gsub(/[^\w_]/, "_")
real_name = "" << verb << " " << path
route = register CodeObjects::RouteObject.new(namespace, method_name, :instance) do |o|
o.visibility = "public"
o.source = statement.source
o.signature = real_name
o.explicit = true
o.scope = scope
o.docstring = statement.comments
o.http_verb = verb
o.http_path = path
o.real_name = real_name
o.add_file(parser.file, statement.line)
end
AbstractRouteHandler.routes << route
yield(route) if block_given?
end
def register_error_handler(verb, doc = nil)
error_handler = register CodeObjects::RouteObject.new(namespace, verb, :instance) do |o|
o.visibility = "public"
o.source = statement.source
o.signature = verb
o.explicit = true
o.scope = scope
o.docstring = statement.comments
o.http_verb = verb
o.real_name = verb
o.add_file(parser.file, statement.line)
end
AbstractRouteHandler.error_handlers << error_handler
yield(error_handler) if block_given?
end
end
# Route handler for YARD's source parser.
class RouteHandler < Ruby::Base
include AbstractRouteHandler
handles method_call(:get)
handles method_call(:post)
handles method_call(:put)
handles method_call(:delete)
handles method_call(:head)
handles method_call(:not_found)
def http_verb
statement.method_name(true).to_s.upcase
end
def http_path
statement.parameters.first.source
end
end
# Route handler for YARD's legacy parser.
module Legacy
class RouteHandler < Ruby::Legacy::Base
include AbstractRouteHandler
handles /\A(get|post|put|delete|head|not_found)[\s\(].*/m
def http_verb
statement.tokens.first.text.upcase
end
def http_path
statement.tokens[2].text
end
end
end
end
end
end
|