Skip to content

Commit 1ee355e

Browse files
committed
Backport new-style parser to 1.8 compatible syntax (and semantics) for ripper1.8
1 parent 96f50c2 commit 1ee355e

31 files changed

+299
-284
lines changed

Rakefile

+5-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ end
2121

2222
begin
2323
hide = '_spec\.rb$,spec_helper\.rb$,ruby_lex\.rb$,autoload\.rb$'
24-
hide += ',legacy\/.+_handler,html_syntax_highlight_helper18\.rb$' if RUBY19
25-
hide += ',ruby_parser\.rb$,ast_node\.rb$,handlers\/ruby\/[^\/]+\.rb$,html_syntax_highlight_helper\.rb$' if RUBY18
24+
if HAVE_RIPPER
25+
hide += ',legacy\/.+_handler,html_syntax_highlight_helper18\.rb$'
26+
else
27+
hide += ',ruby_parser\.rb$,ast_node\.rb$,handlers\/ruby\/[^\/]+\.rb$,html_syntax_highlight_helper\.rb$'
28+
end
2629

2730
require 'rspec'
2831
require 'rspec/core/rake_task'

lib/yard.rb

+8
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ def self.load_plugins; YARD::Config.load_plugins end
3232
# Keep track of Ruby version for compatibility code
3333
RUBY19, RUBY18 = *(RUBY_VERSION >= "1.9.1" ? [true, false] : [false, true])
3434

35+
begin
36+
require 'ripper'
37+
rescue LoadError
38+
ensure
39+
HAVE_RIPPER = defined?(::Ripper) ? true : false
40+
LEGACY_PARSER = !HAVE_RIPPER
41+
end
42+
3543
# Whether or not continuations are (properly) supported
3644
begin
3745
begin; require 'continuation'; rescue LoadError; end

lib/yard/autoload.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ module Helpers # Namespace for template helpers
198198
autoload :BaseHelper, __p('templates/helpers/base_helper')
199199
autoload :FilterHelper, __p('templates/helpers/filter_helper')
200200
autoload :HtmlHelper, __p('templates/helpers/html_helper')
201-
autoload :HtmlSyntaxHighlightHelper, __p('templates/helpers/html_syntax_highlight_helper' + (RUBY18 ? '18' : ''))
201+
autoload :HtmlSyntaxHighlightHelper, __p('templates/helpers/html_syntax_highlight_helper' + (LEGACY_PARSER ? '18' : ''))
202202
autoload :MarkupHelper, __p('templates/helpers/markup_helper')
203203
autoload :MethodHelper, __p('templates/helpers/method_helper')
204204
autoload :ModuleHelper, __p('templates/helpers/module_helper')

lib/yard/handlers/ruby/class_handler.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ class YARD::Handlers::Ruby::ClassHandler < YARD::Handlers::Ruby::Base
2323
elsif klass
2424
create_attributes(klass, members_from_tags(klass))
2525
end
26-
parse_block(statement[2], namespace: klass)
26+
parse_block(statement[2], :namespace => klass)
2727

2828
if undocsuper
2929
raise YARD::Parser::UndocumentableError, 'superclass (class was added without superclass)'
3030
end
3131
elsif statement.type == :sclass
3232
if statement[0] == s(:var_ref, s(:kw, "self"))
33-
parse_block(statement[1], namespace: namespace, scope: :class)
33+
parse_block(statement[1], :namespace => namespace, :scope => :class)
3434
else
3535
classname = statement[0].source
3636
proxy = Proxy.new(namespace, classname)
@@ -46,7 +46,7 @@ class YARD::Handlers::Ruby::ClassHandler < YARD::Handlers::Ruby::Base
4646

4747
if classname[0,1] =~ /[A-Z]/
4848
register ClassObject.new(namespace, classname) if Proxy === proxy
49-
parse_block(statement[1], namespace: proxy, scope: :class)
49+
parse_block(statement[1], :namespace => proxy, :scope => :class)
5050
else
5151
raise YARD::Parser::UndocumentableError, "class '#{classname}'"
5252
end

lib/yard/handlers/ruby/method_condition_handler.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ class YARD::Handlers::Ruby::MethodConditionHandler < YARD::Handlers::Ruby::Base
33
handles :if_mod, :unless_mod
44

55
process do
6-
parse_block(statement.then_block, owner: owner)
6+
parse_block(statement.then_block, :owner => owner)
77
end
88
end

lib/yard/handlers/ruby/private_constant_handler.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class YARD::Handlers::Ruby::PrivateConstantHandler < YARD::Handlers::Ruby::Base
66
process do
77
errors = []
88
statement.parameters.each do |param|
9-
next unless param.respond_to?(:type)
9+
next unless AstNode === param
1010
begin
1111
privatize_constant(param)
1212
rescue UndocumentableError => err

lib/yard/parser/ruby/ast_node.rb

+20-17
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,13 @@ def source
8787

8888
# List of all known keywords
8989
# @return [Hash]
90-
KEYWORDS = { class: true, alias: true, lambda: true, do_block: true,
91-
def: true, defs: true, begin: true, rescue: true, rescue_mod: true,
92-
if: true, if_mod: true, else: true, elsif: true, case: true,
93-
when: true, next: true, break: true, retry: true, redo: true,
94-
return: true, throw: true, catch: true, until: true, until_mod: true,
95-
while: true, while_mod: true, yield: true, yield0: true, zsuper: true,
96-
unless: true, unless_mod: true, for: true, super: true, return0: true }
90+
KEYWORDS = { :class => true, :alias => true, :lambda => true, :do_block => true,
91+
:def => true, :defs => true, :begin => true, :rescue => true, :rescue_mod => true,
92+
:if => true, :if_mod => true, :else => true, :elsif => true, :case => true,
93+
:when => true, :next => true, :break => true, :retry => true, :redo => true,
94+
:return => true, :throw => true, :catch => true, :until => true, :until_mod => true,
95+
:while => true, :while_mod => true, :yield => true, :yield0 => true, :zsuper => true,
96+
:unless => true, :unless_mod => true, :for => true, :super => true, :return0 => true }
9797

9898
# @group Creating an AstNode
9999

@@ -110,10 +110,12 @@ def self.node_class_for(type)
110110
MethodCallNode
111111
when :if, :elsif, :if_mod, :unless, :unless_mod
112112
ConditionalNode
113-
when /_ref\Z/
114-
ReferenceNode
115113
else
116-
AstNode
114+
if type.to_s =~ /_ref\Z/
115+
ReferenceNode
116+
else
117+
AstNode
118+
end
117119
end
118120
end
119121

@@ -251,26 +253,27 @@ def show
251253

252254
# @return [nil] pretty prints the node
253255
def pretty_print(q)
254-
objs = [*self.dup, :__last__]
256+
objs = self.dup + [:__last__]
255257
objs.unshift(type) if type && type != :list
256258

257-
options = {}
259+
options = []
258260
if @docstring
259-
options[:docstring] = docstring
261+
options << ['docstring', docstring]
260262
end
261263
if @source_range || @line_range
262-
options[:line] = line_range
263-
options[:source] = source_range
264+
options << ['line', line_range]
265+
options << ['source', source_range]
264266
end
265267
objs.pop if options.size == 0
266268

267269
q.group(3, 's(', ')') do
268270
q.seplist(objs, nil, :each) do |v|
269271
if v == :__last__
270-
q.seplist(options, nil, :each) do |k, v2|
272+
q.seplist(options, nil, :each) do |arr|
273+
k, v2 = *arr
271274
q.group(3) do
272275
q.text k
273-
q.group(3) do
276+
q.group(3) do
274277
q.text ': '
275278
q.pp v2
276279
end

lib/yard/parser/ruby/ruby_parser.rb

+31-25
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
require 'ripper'
1+
begin
2+
require 'ripper'
3+
rescue LoadError => e
4+
begin; require 'ripper18'; rescue LoadError; raise(e) end
5+
end
26

37
module YARD
48
module Parser
@@ -117,32 +121,32 @@ def enumerator
117121
PARSER_EVENT_TABLE.each do |event, arity|
118122
node_class = AstNode.node_class_for(event)
119123

120-
if /_new\z/ =~ event and arity == 0
124+
if /_new\z/ =~ event.to_s and arity == 0
121125
module_eval(<<-eof, __FILE__, __LINE__ + 1)
122126
def on_#{event}(*args)
123-
#{node_class}.new(:list, args, listchar: charno...charno, listline: lineno..lineno)
127+
#{node_class}.new(:list, args, :listchar => charno...charno, :listline => lineno..lineno)
124128
end
125129
eof
126-
elsif /_add(_.+)?\z/ =~ event
130+
elsif /_add(_.+)?\z/ =~ event.to_s
127131
module_eval(<<-eof, __FILE__, __LINE__ + 1)
128-
undef on_#{event} if instance_method(:on_#{event})
132+
begin; undef on_#{event}; rescue NameError; end
129133
def on_#{event}(list, item)
130134
list.push(item)
131135
list
132136
end
133137
eof
134138
elsif MAPPINGS.has_key?(event)
135139
module_eval(<<-eof, __FILE__, __LINE__ + 1)
136-
undef on_#{event} if instance_method(:on_#{event})
140+
begin; undef on_#{event}; rescue NameError; end
137141
def on_#{event}(*args)
138142
visit_event #{node_class}.new(:#{event}, args)
139143
end
140144
eof
141145
else
142146
module_eval(<<-eof, __FILE__, __LINE__ + 1)
143-
undef on_#{event} if instance_method(:on_#{event})
147+
begin; undef on_#{event}; rescue NameError; end
144148
def on_#{event}(*args)
145-
#{node_class}.new(:#{event}, args, listline: lineno..lineno, listchar: charno...charno)
149+
#{node_class}.new(:#{event}, args, :listline => lineno..lineno, :listchar => charno...charno)
146150
end
147151
eof
148152
end
@@ -151,17 +155,18 @@ def on_#{event}(*args)
151155
SCANNER_EVENTS.each do |event|
152156
ast_token = AST_TOKENS.include?(event)
153157
module_eval(<<-eof, __FILE__, __LINE__ + 1)
154-
undef on_#{event} if instance_method(:on_#{event})
158+
begin; undef on_#{event}; rescue NameError; end
155159
def on_#{event}(tok)
156160
visit_ns_token(:#{event}, tok, #{ast_token.inspect})
157161
end
158162
eof
159163
end
160164

161-
REV_MAPPINGS.select {|k| k.is_a?(Symbol) }.each do |event, value|
165+
REV_MAPPINGS.select {|k,v| k.is_a?(Symbol) }.each do |pair|
166+
event, value = *pair
162167
ast_token = AST_TOKENS.include?(event)
163168
module_eval(<<-eof, __FILE__, __LINE__ + 1)
164-
undef on_#{event} if instance_method(:on_#{event})
169+
begin; undef on_#{event}; rescue NameError; end
165170
def on_#{event}(tok)
166171
(@map[:#{event}] ||= []) << [lineno, charno]
167172
visit_ns_token(:#{event}, tok, #{ast_token.inspect})
@@ -171,7 +176,7 @@ def on_#{event}(tok)
171176

172177
[:kw, :op].each do |event|
173178
module_eval(<<-eof, __FILE__, __LINE__ + 1)
174-
undef on_#{event} if instance_method(:on_#{event})
179+
begin; undef on_#{event}; rescue NameError; end
175180
def on_#{event}(tok)
176181
unless @last_ns_token == [:kw, "def"] ||
177182
(@tokens.last && @tokens.last[0] == :symbeg)
@@ -184,7 +189,7 @@ def on_#{event}(tok)
184189

185190
[:sp, :nl, :ignored_nl].each do |event|
186191
module_eval(<<-eof, __FILE__, __LINE__ + 1)
187-
undef on_#{event} if instance_method(:on_#{event})
192+
begin; undef on_#{event}; rescue NameError; end
188193
def on_#{event}(tok)
189194
add_token(:#{event}, tok)
190195
@charno += tok.length
@@ -193,7 +198,8 @@ def on_#{event}(tok)
193198
end
194199

195200
def visit_event(node)
196-
lstart, sstart = *@map[MAPPINGS[node.type]].pop
201+
map = @map[MAPPINGS[node.type]]
202+
lstart, sstart = *(map ? map.pop : [lineno, lineno])
197203
node.source_range = Range.new(sstart, @ns_charno - 1)
198204
node.line_range = Range.new(lstart, lineno)
199205
node
@@ -214,7 +220,7 @@ def visit_ns_token(token, data, ast_token = false)
214220
@charno += data.length
215221
@ns_charno = charno
216222
if ast_token
217-
AstNode.new(token, [data], line: lineno..lineno, char: ch..charno-1, token: true)
223+
AstNode.new(token, [data], :line => lineno..lineno, :char => ch..charno-1, :token => true)
218224
end
219225
end
220226

@@ -281,7 +287,7 @@ def on_aref(*args)
281287
ll, lc = *@map[:aref].pop
282288
sr = args.first.source_range.first..lc
283289
lr = args.first.line_range.first..ll
284-
AstNode.new(:aref, args, char: sr, line: lr)
290+
AstNode.new(:aref, args, :char => sr, :line => lr)
285291
end
286292

287293
def on_rbracket(tok)
@@ -303,17 +309,17 @@ def on_top_const_ref(*args)
303309

304310
def on_const_path_ref(*args)
305311
klass = AstNode.node_class_for(:const_path_ref)
306-
klass.new(:const_path_ref, args, listline: lineno..lineno, listchar: charno..charno)
312+
klass.new(:const_path_ref, args, :listline => lineno..lineno, :listchar => charno..charno)
307313
end
308314

309315
[:if_mod, :unless_mod, :while_mod].each do |kw|
310316
node_class = AstNode.node_class_for(kw)
311317
module_eval(<<-eof, __FILE__, __LINE__ + 1)
312-
undef on_#{kw} if instance_method(:on_#{kw})
318+
begin; undef on_#{kw}; rescue NameError; end
313319
def on_#{kw}(*args)
314320
sr = args.last.source_range.first..args.first.source_range.last
315321
lr = args.last.line_range.first..args.first.line_range.last
316-
#{node_class}.new(:#{kw}, args, line: lr, char: sr)
322+
#{node_class}.new(:#{kw}, args, :line => lr, :char => sr)
317323
end
318324
eof
319325
end
@@ -336,7 +342,7 @@ def on_lambda(*args)
336342
end
337343

338344
def on_string_content(*args)
339-
AstNode.new(:string_content, args, listline: lineno..lineno, listchar: charno..charno)
345+
AstNode.new(:string_content, args, :listline => lineno..lineno, :listchar => charno..charno)
340346
end
341347

342348
def on_rescue(exc, *args)
@@ -345,7 +351,7 @@ def on_rescue(exc, *args)
345351
end
346352

347353
def on_void_stmt
348-
AstNode.new(:void_stmt, [], line: lineno..lineno, char: charno...charno)
354+
AstNode.new(:void_stmt, [], :line => lineno..lineno, :char => charno...charno)
349355
end
350356

351357
def on_params(*args)
@@ -354,26 +360,26 @@ def on_params(*args)
354360
if arg.first.class == Array
355361
arg.map! do |sub_arg|
356362
if sub_arg.class == Array
357-
AstNode.new(:default_arg, sub_arg, listline: lineno..lineno, listchar: charno..charno)
363+
AstNode.new(:default_arg, sub_arg, :listline => lineno..lineno, :listchar => charno..charno)
358364
else
359365
sub_arg
360366
end
361367
end
362368
end
363-
AstNode.new(:list, arg, listline: lineno..lineno, listchar: charno..charno)
369+
AstNode.new(:list, arg, :listline => lineno..lineno, :listchar => charno..charno)
364370
else
365371
arg
366372
end
367373
end
368-
ParameterNode.new(:params, args, listline: lineno..lineno, listchar: charno..charno)
374+
ParameterNode.new(:params, args, :listline => lineno..lineno, :listchar => charno..charno)
369375
end
370376

371377
def on_label(data)
372378
add_token(:label, data)
373379
ch = charno
374380
@charno += data.length
375381
@ns_charno = charno
376-
AstNode.new(:label, [data[0...-1]], line: lineno..lineno, char: ch..charno-1, token: true)
382+
AstNode.new(:label, [data[0...-1]], :line => lineno..lineno, :char => ch..charno-1, :token => true)
377383
end
378384

379385
def on_comment(comment)

lib/yard/parser/source_parser.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ def parser_type_for_extension(extension)
139139
# @return [Symbol] the validated parser type
140140
# @private
141141
def validated_parser_type(type)
142-
RUBY18 && type == :ruby ? :ruby18 : type
142+
!HAVE_RIPPER && type == :ruby ? :ruby18 : type
143143
end
144144

145145
private
@@ -171,7 +171,7 @@ def parse_in_order(*files)
171171

172172
self.parser_type = :ruby
173173

174-
register_parser_type :ruby, Ruby::RubyParser if RUBY19
174+
register_parser_type :ruby, Ruby::RubyParser if HAVE_RIPPER
175175
register_parser_type :ruby18, Ruby::Legacy::RubyParser
176176
register_parser_type :c, CParser, ['c', 'cc', 'cxx', 'cpp']
177177

spec/handlers/alias_handler_spec.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
require File.dirname(__FILE__) + '/spec_helper'
22

3-
describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}AliasHandler" do
3+
describe "YARD::Handlers::Ruby::#{LEGACY_PARSER ? "Legacy::" : ""}AliasHandler" do
44
before(:all) { parse_file :alias_handler_001, __FILE__ }
55

66
it "should throw alias into namespace object list" do

spec/handlers/attribute_handler_spec.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
require File.dirname(__FILE__) + '/spec_helper'
22

3-
describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}AttributeHandler" do
3+
describe "YARD::Handlers::Ruby::#{LEGACY_PARSER ? "Legacy::" : ""}AttributeHandler" do
44
before(:all) { parse_file :attribute_handler_001, __FILE__ }
55

66
def read_write(namespace, name, read, write, scope = :instance)

spec/handlers/base_spec.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def test_handler(file, stmts, creates = true)
138138
end
139139

140140
[:ruby, :ruby18].each do |parser_type|
141-
next if parser_type == :ruby && !RUBY19
141+
next if parser_type == :ruby && LEGACY_PARSER
142142
describe "Parser type = #{parser_type.inspect}" do
143143
Parser::SourceParser.parser_type = parser_type
144144
it "should allow handler to be specific to a file" do

spec/handlers/class_condition_handler_spec.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
require File.dirname(__FILE__) + '/spec_helper'
22

3-
describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}ClassConditionHandler" do
3+
describe "YARD::Handlers::Ruby::#{LEGACY_PARSER ? "Legacy::" : ""}ClassConditionHandler" do
44
before(:all) { parse_file :class_condition_handler_001, __FILE__ }
55

66
def verify_method(*names)

0 commit comments

Comments
 (0)