PageRenderTime 29ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/jruby-1.7.3/test/externals/ruby1.9/rdoc/test_rdoc_parser_c.rb

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Ruby | 1436 lines | 1193 code | 200 blank | 43 comment | 18 complexity | ea4e98682b7ef362681889efc6f5ecd3 MD5 | raw file
  1. require 'stringio'
  2. require 'tempfile'
  3. require 'rubygems'
  4. require 'minitest/autorun'
  5. require 'rdoc/options'
  6. require 'rdoc/parser/c'
  7. =begin
  8. TODO: test call-seq parsing
  9. /*
  10. * call-seq:
  11. * ARGF.readlines(sep=$/) -> array
  12. * ARGF.readlines(limit) -> array
  13. * ARGF.readlines(sep, limit) -> array
  14. *
  15. * ARGF.to_a(sep=$/) -> array
  16. * ARGF.to_a(limit) -> array
  17. * ARGF.to_a(sep, limit) -> array
  18. *
  19. * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
  20. * lines, one line per element. Lines are assumed to be separated by _sep_.
  21. *
  22. * lines = ARGF.readlines
  23. * lines[0] #=> "This is line one\n"
  24. */
  25. assert call-seq did not stop at first empty line
  26. /*
  27. * call-seq:
  28. *
  29. * flt ** other -> float
  30. *
  31. * Raises <code>float</code> the <code>other</code> power.
  32. *
  33. * 2.0**3 #=> 8.0
  34. */
  35. assert call-seq correct (bug: was empty)
  36. /* call-seq: flt ** other -> float */
  37. assert call-seq correct
  38. =end
  39. class RDoc::Parser::C
  40. attr_accessor :classes
  41. public :do_classes, :do_constants
  42. end
  43. class TestRDocParserC < MiniTest::Unit::TestCase
  44. def setup
  45. @tempfile = Tempfile.new self.class.name
  46. filename = @tempfile.path
  47. @top_level = RDoc::TopLevel.new filename
  48. @fn = filename
  49. @options = RDoc::Options.new
  50. @stats = RDoc::Stats.new 0
  51. RDoc::Parser::C.reset
  52. RDoc::TopLevel.reset
  53. end
  54. def teardown
  55. @tempfile.close
  56. end
  57. def test_class_can_parse
  58. c_parser = RDoc::Parser::C
  59. assert_equal c_parser, c_parser.can_parse('file.C')
  60. assert_equal c_parser, c_parser.can_parse('file.CC')
  61. assert_equal c_parser, c_parser.can_parse('file.H')
  62. assert_equal c_parser, c_parser.can_parse('file.HH')
  63. assert_equal c_parser, c_parser.can_parse('file.c')
  64. assert_equal c_parser, c_parser.can_parse('file.cc')
  65. assert_equal c_parser, c_parser.can_parse('file.cpp')
  66. assert_equal c_parser, c_parser.can_parse('file.cxx')
  67. assert_equal c_parser, c_parser.can_parse('file.h')
  68. assert_equal c_parser, c_parser.can_parse('file.hh')
  69. assert_equal c_parser, c_parser.can_parse('file.y')
  70. end
  71. def test_do_attr_rb_attr
  72. content = <<-EOF
  73. void Init_Blah(void) {
  74. cBlah = rb_define_class("Blah", rb_cObject);
  75. /*
  76. * This is an accessor
  77. */
  78. rb_attr(cBlah, rb_intern("accessor"), 1, 1, Qfalse);
  79. /*
  80. * This is a reader
  81. */
  82. rb_attr(cBlah, rb_intern("reader"), 1, 0, Qfalse);
  83. /*
  84. * This is a writer
  85. */
  86. rb_attr(cBlah, rb_intern("writer"), 0, 1, Qfalse);
  87. }
  88. EOF
  89. klass = util_get_class content, 'cBlah'
  90. attrs = klass.attributes
  91. assert_equal 3, attrs.length, attrs.inspect
  92. accessor = attrs.shift
  93. assert_equal 'accessor', accessor.name
  94. assert_equal 'RW', accessor.rw
  95. assert_equal 'This is an accessor', accessor.comment
  96. assert_equal @top_level, accessor.file
  97. reader = attrs.shift
  98. assert_equal 'reader', reader.name
  99. assert_equal 'R', reader.rw
  100. assert_equal 'This is a reader', reader.comment
  101. writer = attrs.shift
  102. assert_equal 'writer', writer.name
  103. assert_equal 'W', writer.rw
  104. assert_equal 'This is a writer', writer.comment
  105. end
  106. def test_do_attr_rb_define_attr
  107. content = <<-EOF
  108. void Init_Blah(void) {
  109. cBlah = rb_define_class("Blah", rb_cObject);
  110. /*
  111. * This is an accessor
  112. */
  113. rb_define_attr(cBlah, "accessor", 1, 1);
  114. }
  115. EOF
  116. klass = util_get_class content, 'cBlah'
  117. attrs = klass.attributes
  118. assert_equal 1, attrs.length, attrs.inspect
  119. accessor = attrs.shift
  120. assert_equal 'accessor', accessor.name
  121. assert_equal 'RW', accessor.rw
  122. assert_equal 'This is an accessor', accessor.comment
  123. assert_equal @top_level, accessor.file
  124. end
  125. def test_do_aliases
  126. content = <<-EOF
  127. /*
  128. * This should show up as an alias with documentation
  129. */
  130. VALUE blah(VALUE klass, VALUE year) {
  131. }
  132. void Init_Blah(void) {
  133. cDate = rb_define_class("Date", rb_cObject);
  134. rb_define_method(cDate, "blah", blah, 1);
  135. rb_define_alias(cDate, "bleh", "blah");
  136. }
  137. EOF
  138. klass = util_get_class content, 'cDate'
  139. methods = klass.method_list
  140. assert_equal 2, methods.length
  141. assert_equal 'bleh', methods.last.name
  142. assert_equal 'blah', methods.last.is_alias_for.name
  143. assert_equal @top_level, methods.last.is_alias_for.file
  144. assert_equal @top_level, methods.last.file
  145. end
  146. def test_do_aliases_singleton
  147. content = <<-EOF
  148. /*
  149. * This should show up as a method with documentation
  150. */
  151. VALUE blah(VALUE klass, VALUE year) {
  152. }
  153. void Init_Blah(void) {
  154. cDate = rb_define_class("Date", rb_cObject);
  155. sDate = rb_singleton_class(cDate);
  156. rb_define_method(sDate, "blah", blah, 1);
  157. /*
  158. * This should show up as an alias
  159. */
  160. rb_define_alias(sDate, "bleh", "blah");
  161. }
  162. EOF
  163. klass = util_get_class content, 'cDate'
  164. methods = klass.method_list
  165. assert_equal 2, methods.length
  166. assert_equal 'bleh', methods.last.name
  167. assert methods.last.singleton
  168. assert_equal 'blah', methods.last.is_alias_for.name
  169. assert_equal 'This should show up as an alias', methods.last.comment
  170. end
  171. def test_do_classes_boot_class
  172. content = <<-EOF
  173. /* Document-class: Foo
  174. * this is the Foo boot class
  175. */
  176. VALUE cFoo = boot_defclass("Foo", rb_cObject);
  177. EOF
  178. klass = util_get_class content, 'cFoo'
  179. assert_equal "this is the Foo boot class", klass.comment
  180. assert_equal 'Object', klass.superclass
  181. end
  182. def test_do_classes_boot_class_nil
  183. content = <<-EOF
  184. /* Document-class: Foo
  185. * this is the Foo boot class
  186. */
  187. VALUE cFoo = boot_defclass("Foo", 0);
  188. EOF
  189. klass = util_get_class content, 'cFoo'
  190. assert_equal "this is the Foo boot class", klass.comment
  191. assert_equal nil, klass.superclass
  192. end
  193. def test_do_aliases_missing_class
  194. content = <<-EOF
  195. void Init_Blah(void) {
  196. rb_define_alias(cDate, "b", "a");
  197. }
  198. EOF
  199. _, err = capture_io do
  200. refute util_get_class(content, 'cDate')
  201. end
  202. assert_equal "Enclosing class/module \"cDate\" for alias b a not known\n",
  203. err
  204. end
  205. def test_do_classes_class
  206. content = <<-EOF
  207. /* Document-class: Foo
  208. * this is the Foo class
  209. */
  210. VALUE cFoo = rb_define_class("Foo", rb_cObject);
  211. EOF
  212. klass = util_get_class content, 'cFoo'
  213. assert_equal "this is the Foo class", klass.comment
  214. end
  215. def test_do_classes_class_under
  216. content = <<-EOF
  217. /* Document-class: Kernel::Foo
  218. * this is the Foo class under Kernel
  219. */
  220. VALUE cFoo = rb_define_class_under(rb_mKernel, "Foo", rb_cObject);
  221. EOF
  222. klass = util_get_class content, 'cFoo'
  223. assert_equal 'Kernel::Foo', klass.full_name
  224. assert_equal "this is the Foo class under Kernel", klass.comment
  225. end
  226. def test_do_classes_class_under_rb_path2class
  227. content = <<-EOF
  228. /* Document-class: Kernel::Foo
  229. * this is Kernel::Foo < A::B
  230. */
  231. VALUE cFoo = rb_define_class_under(rb_mKernel, "Foo", rb_path2class("A::B"));
  232. EOF
  233. klass = util_get_class content, 'cFoo'
  234. assert_equal 'Kernel::Foo', klass.full_name
  235. assert_equal 'A::B', klass.superclass
  236. assert_equal 'this is Kernel::Foo < A::B', klass.comment
  237. end
  238. def test_do_classes_singleton
  239. content = <<-EOF
  240. VALUE cFoo = rb_define_class("Foo", rb_cObject);
  241. VALUE cFooS = rb_singleton_class(cFoo);
  242. EOF
  243. util_get_class content, 'cFooS'
  244. assert_equal 'Foo', @parser.singleton_classes['cFooS']
  245. end
  246. def test_do_classes_module
  247. content = <<-EOF
  248. /* Document-module: Foo
  249. * this is the Foo module
  250. */
  251. VALUE mFoo = rb_define_module("Foo");
  252. EOF
  253. klass = util_get_class content, 'mFoo'
  254. assert_equal "this is the Foo module", klass.comment
  255. end
  256. def test_do_classes_module_under
  257. content = <<-EOF
  258. /* Document-module: Kernel::Foo
  259. * this is the Foo module under Kernel
  260. */
  261. VALUE mFoo = rb_define_module_under(rb_mKernel, "Foo");
  262. EOF
  263. klass = util_get_class content, 'mFoo'
  264. assert_equal "this is the Foo module under Kernel", klass.comment
  265. end
  266. def test_do_constants
  267. content = <<-EOF
  268. #include <ruby.h>
  269. void Init_foo(){
  270. VALUE cFoo = rb_define_class("Foo", rb_cObject);
  271. /* 300: The highest possible score in bowling */
  272. rb_define_const(cFoo, "PERFECT", INT2FIX(300));
  273. /* Huzzah!: What you cheer when you roll a perfect game */
  274. rb_define_const(cFoo, "CHEER", rb_str_new2("Huzzah!"));
  275. /* TEST\:TEST: Checking to see if escaped colon works */
  276. rb_define_const(cFoo, "TEST", rb_str_new2("TEST:TEST"));
  277. /* \\: The file separator on MS Windows */
  278. rb_define_const(cFoo, "MSEPARATOR", rb_str_new2("\\"));
  279. /* /: The file separator on Unix */
  280. rb_define_const(cFoo, "SEPARATOR", rb_str_new2("/"));
  281. /* C:\\Program Files\\Stuff: A directory on MS Windows */
  282. rb_define_const(cFoo, "STUFF", rb_str_new2("C:\\Program Files\\Stuff"));
  283. /* Default definition */
  284. rb_define_const(cFoo, "NOSEMI", INT2FIX(99));
  285. rb_define_const(cFoo, "NOCOMMENT", rb_str_new2("No comment"));
  286. /*
  287. * Multiline comment goes here because this comment spans multiple lines.
  288. * Multiline comment goes here because this comment spans multiple lines.
  289. */
  290. rb_define_const(cFoo, "MULTILINE", INT2FIX(1));
  291. /*
  292. * 1: Multiline comment goes here because this comment spans multiple lines.
  293. * Multiline comment goes here because this comment spans multiple lines.
  294. */
  295. rb_define_const(cFoo, "MULTILINE_VALUE", INT2FIX(1));
  296. /* Multiline comment goes here because this comment spans multiple lines.
  297. * Multiline comment goes here because this comment spans multiple lines.
  298. */
  299. rb_define_const(cFoo, "MULTILINE_NOT_EMPTY", INT2FIX(1));
  300. }
  301. EOF
  302. @parser = util_parser content
  303. @parser.do_classes
  304. @parser.do_constants
  305. klass = @parser.classes['cFoo']
  306. assert klass
  307. constants = klass.constants
  308. assert !klass.constants.empty?
  309. assert_equal @top_level, constants.first.file
  310. constants = constants.map { |c| [c.name, c.value, c.comment] }
  311. assert_equal ['PERFECT', '300', 'The highest possible score in bowling '],
  312. constants.shift
  313. assert_equal ['CHEER', 'Huzzah!',
  314. 'What you cheer when you roll a perfect game '],
  315. constants.shift
  316. assert_equal ['TEST', 'TEST:TEST',
  317. 'Checking to see if escaped colon works '],
  318. constants.shift
  319. assert_equal ['MSEPARATOR', '\\',
  320. 'The file separator on MS Windows '],
  321. constants.shift
  322. assert_equal ['SEPARATOR', '/',
  323. 'The file separator on Unix '],
  324. constants.shift
  325. assert_equal ['STUFF', 'C:\\Program Files\\Stuff',
  326. 'A directory on MS Windows '],
  327. constants.shift
  328. assert_equal ['NOSEMI', 'INT2FIX(99)',
  329. 'Default definition '],
  330. constants.shift
  331. assert_equal ['NOCOMMENT', 'rb_str_new2("No comment")', ''],
  332. constants.shift
  333. comment = <<-EOF.chomp
  334. Multiline comment goes here because this comment spans multiple lines.
  335. Multiline comment goes here because this comment spans multiple lines.
  336. EOF
  337. assert_equal ['MULTILINE', 'INT2FIX(1)', comment], constants.shift
  338. assert_equal ['MULTILINE_VALUE', '1', comment], constants.shift
  339. assert_equal ['MULTILINE_NOT_EMPTY', 'INT2FIX(1)', comment], constants.shift
  340. assert constants.empty?, constants.inspect
  341. end
  342. def test_do_constants_curses
  343. content = <<-EOF
  344. void Init_curses(){
  345. mCurses = rb_define_module("Curses");
  346. /*
  347. * Document-const: Curses::COLOR_BLACK
  348. *
  349. * Value of the color black
  350. */
  351. rb_curses_define_const(COLOR_BLACK);
  352. }
  353. EOF
  354. @parser = util_parser content
  355. @parser.do_classes
  356. @parser.do_constants
  357. klass = @parser.classes['mCurses']
  358. constants = klass.constants
  359. refute_empty klass.constants
  360. assert_equal 'COLOR_BLACK', constants.first.name
  361. assert_equal 'UINT2NUM(COLOR_BLACK)', constants.first.value
  362. assert_equal 'Value of the color black', constants.first.comment
  363. end
  364. def test_do_includes
  365. content = <<-EOF
  366. Init_foo() {
  367. VALUE cFoo = rb_define_class("Foo", rb_cObject);
  368. VALUE mInc = rb_define_module("Inc");
  369. rb_include_module(cFoo, mInc);
  370. }
  371. EOF
  372. klass = util_get_class content, 'cFoo'
  373. incl = klass.includes.first
  374. assert_equal 'Inc', incl.name
  375. assert_equal '', incl.comment
  376. assert_equal @top_level, incl.file
  377. end
  378. # HACK parsing warning instead of setting up in file
  379. def test_do_methods_in_c
  380. content = <<-EOF
  381. VALUE blah(VALUE klass, VALUE year) {
  382. }
  383. void Init_Blah(void) {
  384. cDate = rb_define_class("Date", rb_cObject);
  385. rb_define_method(cDate, "blah", blah, 1); /* in blah.c */
  386. }
  387. EOF
  388. klass = nil
  389. _, err = capture_io do
  390. klass = util_get_class content, 'cDate'
  391. end
  392. assert_match ' blah.c ', err
  393. end
  394. # HACK parsing warning instead of setting up in file
  395. def test_do_methods_in_cpp
  396. content = <<-EOF
  397. VALUE blah(VALUE klass, VALUE year) {
  398. }
  399. void Init_Blah(void) {
  400. cDate = rb_define_class("Date", rb_cObject);
  401. rb_define_method(cDate, "blah", blah, 1); /* in blah.cpp */
  402. }
  403. EOF
  404. klass = nil
  405. _, err = capture_io do
  406. klass = util_get_class content, 'cDate'
  407. end
  408. assert_match ' blah.cpp ', err
  409. end
  410. # HACK parsing warning instead of setting up in file
  411. def test_do_methods_in_y
  412. content = <<-EOF
  413. VALUE blah(VALUE klass, VALUE year) {
  414. }
  415. void Init_Blah(void) {
  416. cDate = rb_define_class("Date", rb_cObject);
  417. rb_define_method(cDate, "blah", blah, 1); /* in blah.y */
  418. }
  419. EOF
  420. klass = nil
  421. _, err = capture_io do
  422. klass = util_get_class content, 'cDate'
  423. end
  424. assert_match ' blah.y ', err
  425. end
  426. def test_do_methods_singleton_class
  427. content = <<-EOF
  428. VALUE blah(VALUE klass, VALUE year) {
  429. }
  430. void Init_Blah(void) {
  431. cDate = rb_define_class("Date", rb_cObject);
  432. sDate = rb_singleton_class(cDate);
  433. rb_define_method(sDate, "blah", blah, 1);
  434. }
  435. EOF
  436. klass = util_get_class content, 'cDate'
  437. methods = klass.method_list
  438. assert_equal 1, methods.length
  439. assert_equal 'blah', methods.first.name
  440. assert methods.first.singleton
  441. end
  442. def test_find_alias_comment
  443. parser = util_parser ''
  444. comment = parser.find_alias_comment 'C', '[]', 'index'
  445. assert_equal '', comment
  446. parser = util_parser <<-C
  447. /*
  448. * comment
  449. */
  450. rb_define_alias(C, "[]", "index");
  451. C
  452. comment = parser.find_alias_comment 'C', '[]', 'index'
  453. assert_equal "/*\n * comment\n */\n\n", comment
  454. end
  455. def test_find_class_comment_include
  456. @options.rdoc_include << File.dirname(__FILE__)
  457. content = <<-EOF
  458. /*
  459. * a comment for class Foo
  460. *
  461. * :include: test.txt
  462. */
  463. void
  464. Init_Foo(void) {
  465. VALUE foo = rb_define_class("Foo", rb_cObject);
  466. }
  467. EOF
  468. klass = util_get_class content, 'foo'
  469. assert_equal "a comment for class Foo\n\ntest file", klass.comment
  470. end
  471. def test_find_class_comment_init
  472. content = <<-EOF
  473. /*
  474. * a comment for class Foo
  475. */
  476. void
  477. Init_Foo(void) {
  478. VALUE foo = rb_define_class("Foo", rb_cObject);
  479. }
  480. EOF
  481. klass = util_get_class content, 'foo'
  482. assert_equal "a comment for class Foo", klass.comment
  483. end
  484. def test_find_class_comment_define_class
  485. content = <<-EOF
  486. /*
  487. * a comment for class Foo
  488. */
  489. VALUE foo = rb_define_class("Foo", rb_cObject);
  490. EOF
  491. klass = util_get_class content, 'foo'
  492. assert_equal "a comment for class Foo", klass.comment
  493. end
  494. def test_find_class_comment_define_class_Init_Foo
  495. content = <<-EOF
  496. /*
  497. * a comment for class Foo on Init
  498. */
  499. void
  500. Init_Foo(void) {
  501. /*
  502. * a comment for class Foo on rb_define_class
  503. */
  504. VALUE foo = rb_define_class("Foo", rb_cObject);
  505. }
  506. EOF
  507. klass = util_get_class content, 'foo'
  508. assert_equal "a comment for class Foo on Init", klass.comment
  509. end
  510. def test_find_class_comment_define_class_Init_Foo_no_void
  511. content = <<-EOF
  512. /*
  513. * a comment for class Foo on Init
  514. */
  515. void
  516. Init_Foo() {
  517. /*
  518. * a comment for class Foo on rb_define_class
  519. */
  520. VALUE foo = rb_define_class("Foo", rb_cObject);
  521. }
  522. EOF
  523. klass = util_get_class content, 'foo'
  524. assert_equal "a comment for class Foo on Init", klass.comment
  525. end
  526. def test_find_class_comment_define_class_bogus_comment
  527. content = <<-EOF
  528. /*
  529. * a comment for other_function
  530. */
  531. void
  532. other_function() {
  533. }
  534. void
  535. Init_Foo(void) {
  536. VALUE foo = rb_define_class("Foo", rb_cObject);
  537. }
  538. EOF
  539. klass = util_get_class content, 'foo'
  540. assert_equal '', klass.comment
  541. end
  542. def test_find_const_comment_rb_define
  543. content = <<-EOF
  544. /*
  545. * A comment
  546. */
  547. rb_define_const(cFoo, "CONST", value);
  548. EOF
  549. parser = util_parser content
  550. comment = parser.find_const_comment 'const', 'CONST'
  551. assert_equal "/*\n * A comment\n */\n", comment
  552. end
  553. def test_find_const_comment_document_const
  554. content = <<-EOF
  555. /*
  556. * Document-const: CONST
  557. *
  558. * A comment
  559. */
  560. EOF
  561. parser = util_parser content
  562. comment = parser.find_const_comment nil, 'CONST'
  563. assert_equal " *\n * A comment\n */", comment
  564. end
  565. def test_find_const_comment_document_const_full_name
  566. content = <<-EOF
  567. /*
  568. * Document-const: Foo::CONST
  569. *
  570. * A comment
  571. */
  572. EOF
  573. parser = util_parser content
  574. comment = parser.find_const_comment nil, 'CONST', 'Foo'
  575. assert_equal " *\n * A comment\n */", comment
  576. end
  577. def test_find_body
  578. content = <<-EOF
  579. /*
  580. * a comment for other_function
  581. */
  582. VALUE
  583. other_function() {
  584. }
  585. void
  586. Init_Foo(void) {
  587. VALUE foo = rb_define_class("Foo", rb_cObject);
  588. rb_define_method(foo, "my_method", other_function, 0);
  589. }
  590. EOF
  591. klass = util_get_class content, 'foo'
  592. other_function = klass.method_list.first
  593. assert_equal 'my_method', other_function.name
  594. assert_equal "a comment for other_function",
  595. other_function.comment
  596. assert_equal '()', other_function.params
  597. code = other_function.token_stream.first.text
  598. assert_equal "VALUE\nother_function() {\n}", code
  599. end
  600. def test_find_body_2
  601. content = <<-CONTENT
  602. /* Copyright (C) 2010 Sven Herzberg
  603. *
  604. * This file is free software; the author(s) gives unlimited
  605. * permission to copy and/or distribute it, with or without
  606. * modifications, as long as this notice is preserved.
  607. */
  608. #include <ruby.h>
  609. static VALUE
  610. wrap_initialize (VALUE self)
  611. {
  612. return self;
  613. }
  614. /* */
  615. static VALUE
  616. wrap_shift (VALUE self,
  617. VALUE arg)
  618. {
  619. return self;
  620. }
  621. void
  622. init_gi_repository (void)
  623. {
  624. VALUE mTest = rb_define_module ("Test");
  625. VALUE cTest = rb_define_class_under (mTest, "Test", rb_cObject);
  626. rb_define_method (cTest, "initialize", wrap_initialize, 0);
  627. rb_define_method (cTest, "shift", wrap_shift, 0);
  628. }
  629. CONTENT
  630. klass = util_get_class content, 'cTest'
  631. assert_equal 2, klass.method_list.length
  632. end
  633. def test_find_body_define
  634. content = <<-EOF
  635. #define something something_else
  636. #define other_function rb_other_function
  637. /*
  638. * a comment for rb_other_function
  639. */
  640. VALUE
  641. rb_other_function() {
  642. }
  643. void
  644. Init_Foo(void) {
  645. VALUE foo = rb_define_class("Foo", rb_cObject);
  646. rb_define_method(foo, "my_method", other_function, 0);
  647. }
  648. EOF
  649. klass = util_get_class content, 'foo'
  650. other_function = klass.method_list.first
  651. assert_equal 'my_method', other_function.name
  652. assert_equal 'a comment for rb_other_function', other_function.comment
  653. assert_equal '()', other_function.params
  654. assert_equal 118, other_function.offset
  655. assert_equal 8, other_function.line
  656. code = other_function.token_stream.first.text
  657. assert_equal "VALUE\nrb_other_function() {\n}", code
  658. end
  659. def test_find_body_define_comment
  660. content = <<-EOF
  661. /*
  662. * a comment for other_function
  663. */
  664. #define other_function rb_other_function
  665. /* */
  666. VALUE
  667. rb_other_function() {
  668. }
  669. void
  670. Init_Foo(void) {
  671. VALUE foo = rb_define_class("Foo", rb_cObject);
  672. rb_define_method(foo, "my_method", other_function, 0);
  673. }
  674. EOF
  675. klass = util_get_class content, 'foo'
  676. other_function = klass.method_list.first
  677. assert_equal 'my_method', other_function.name
  678. assert_equal 'a comment for other_function', other_function.comment
  679. assert_equal '()', other_function.params
  680. assert_equal 39, other_function.offset
  681. assert_equal 4, other_function.line
  682. code = other_function.token_stream.first.text
  683. assert_equal "#define other_function rb_other_function", code
  684. end
  685. def test_find_body_document_method
  686. content = <<-EOF
  687. /*
  688. * Document-method: bar
  689. * Document-method: baz
  690. *
  691. * a comment for bar
  692. */
  693. VALUE
  694. bar() {
  695. }
  696. void
  697. Init_Foo(void) {
  698. VALUE foo = rb_define_class("Foo", rb_cObject);
  699. rb_define_method(foo, "bar", bar, 0);
  700. rb_define_method(foo, "baz", bar, 0);
  701. }
  702. EOF
  703. klass = util_get_class content, 'foo'
  704. assert_equal 2, klass.method_list.length
  705. methods = klass.method_list.sort
  706. bar = methods.first
  707. assert_equal 'Foo#bar', bar.full_name
  708. assert_equal "a comment for bar", bar.comment
  709. baz = methods.last
  710. assert_equal 'Foo#baz', baz.full_name
  711. assert_equal "a comment for bar", baz.comment
  712. end
  713. def test_find_body_document_method_equals
  714. content = <<-EOF
  715. /*
  716. * Document-method: Zlib::GzipFile#mtime=
  717. *
  718. * A comment
  719. */
  720. static VALUE
  721. rb_gzfile_set_mtime(VALUE obj, VALUE mtime)
  722. {
  723. void
  724. Init_zlib() {
  725. mZlib = rb_define_module("Zlib");
  726. cGzipFile = rb_define_class_under(mZlib, "GzipFile", rb_cObject);
  727. cGzipWriter = rb_define_class_under(mZlib, "GzipWriter", cGzipFile);
  728. rb_define_method(cGzipWriter, "mtime=", rb_gzfile_set_mtime, 1);
  729. }
  730. EOF
  731. klass = util_get_class content, 'cGzipWriter'
  732. assert_equal 1, klass.method_list.length
  733. methods = klass.method_list.sort
  734. bar = methods.first
  735. assert_equal 'Zlib::GzipWriter#mtime=', bar.full_name
  736. assert_equal 'A comment', bar.comment
  737. end
  738. def test_find_body_document_method_same
  739. content = <<-EOF
  740. VALUE
  741. s_bar() {
  742. }
  743. VALUE
  744. bar() {
  745. }
  746. /*
  747. * Document-method: Foo::bar
  748. *
  749. * a comment for Foo::bar
  750. */
  751. /*
  752. * Document-method: Foo#bar
  753. *
  754. * a comment for Foo#bar
  755. */
  756. void
  757. Init_Foo(void) {
  758. VALUE foo = rb_define_class("Foo", rb_cObject);
  759. rb_define_singleton_method(foo, "bar", s_bar, 0);
  760. rb_define_method(foo, "bar", bar, 0);
  761. }
  762. EOF
  763. klass = util_get_class content, 'foo'
  764. assert_equal 2, klass.method_list.length
  765. methods = klass.method_list.sort
  766. s_bar = methods.first
  767. assert_equal 'Foo::bar', s_bar.full_name
  768. assert_equal "a comment for Foo::bar", s_bar.comment
  769. bar = methods.last
  770. assert_equal 'Foo#bar', bar.full_name
  771. assert_equal "a comment for Foo#bar", bar.comment
  772. end
  773. def test_find_modifiers_call_seq
  774. comment = <<-COMMENT
  775. /* call-seq:
  776. * commercial() -> Date <br />
  777. * commercial(cwyear, cweek=41, cwday=5, sg=nil) -> Date [ruby 1.8] <br />
  778. * commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9]
  779. *
  780. * If no arguments are given:
  781. * * ruby 1.8: returns a +Date+ for 1582-10-15 (the Day of Calendar Reform in
  782. * Italy)
  783. * * ruby 1.9: returns a +Date+ for julian day 0
  784. *
  785. * Otherwise, returns a +Date+ for the commercial week year, commercial week,
  786. * and commercial week day given. Ignores the 4th argument.
  787. */
  788. COMMENT
  789. parser = util_parser ''
  790. method_obj = RDoc::AnyMethod.new nil, 'blah'
  791. parser.find_modifiers comment, method_obj
  792. expected = <<-CALL_SEQ.chomp
  793. commercial() -> Date <br />
  794. commercial(cwyear, cweek=41, cwday=5, sg=nil) -> Date [ruby 1.8] <br />
  795. commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9]
  796. CALL_SEQ
  797. assert_equal expected, method_obj.call_seq
  798. end
  799. def test_find_modifiers_call_seq_no_blank
  800. comment = <<-COMMENT
  801. /* call-seq:
  802. * commercial() -> Date <br />
  803. * commercial(cwyear, cweek=41, cwday=5, sg=nil) -> Date [ruby 1.8] <br />
  804. * commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9]
  805. */
  806. COMMENT
  807. parser = util_parser ''
  808. method_obj = RDoc::AnyMethod.new nil, 'blah'
  809. parser.find_modifiers comment, method_obj
  810. expected = <<-CALL_SEQ.chomp
  811. commercial() -> Date <br />
  812. commercial(cwyear, cweek=41, cwday=5, sg=nil) -> Date [ruby 1.8] <br />
  813. commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9]
  814. CALL_SEQ
  815. assert_equal expected, method_obj.call_seq
  816. end
  817. def test_find_modifiers_nodoc
  818. comment = <<-COMMENT
  819. /* :nodoc:
  820. *
  821. * Blah
  822. */
  823. COMMENT
  824. parser = util_parser ''
  825. method_obj = RDoc::AnyMethod.new nil, 'blah'
  826. parser.find_modifiers comment, method_obj
  827. assert_equal nil, method_obj.document_self
  828. end
  829. def test_find_modifiers_yields
  830. comment = <<-COMMENT
  831. /* :yields: a, b
  832. *
  833. * Blah
  834. */
  835. COMMENT
  836. parser = util_parser ''
  837. method_obj = RDoc::AnyMethod.new nil, 'blah'
  838. parser.find_modifiers comment, method_obj
  839. assert_equal 'a, b', method_obj.block_params
  840. expected = <<-EXPECTED
  841. /*
  842. *
  843. * Blah
  844. */
  845. EXPECTED
  846. assert_equal expected, comment
  847. end
  848. def test_handle_method_args_minus_1
  849. parser = util_parser "Document-method: Object#m\n blah */"
  850. parser.content = <<-BODY
  851. VALUE
  852. rb_other(VALUE obj) {
  853. rb_funcall(obj, rb_intern("other"), 0);
  854. return rb_str_new2("blah, blah, blah");
  855. }
  856. VALUE
  857. rb_m(int argc, VALUE *argv, VALUE obj) {
  858. VALUE o1, o2;
  859. rb_scan_args(argc, argv, "1", &o1, &o2);
  860. }
  861. BODY
  862. parser.handle_method 'method', 'rb_cObject', 'm', 'rb_m', -1
  863. m = @top_level.find_module_named('Object').method_list.first
  864. assert_equal 'm', m.name
  865. assert_equal @top_level, m.file
  866. assert_equal 115, m.offset
  867. assert_equal 7, m.line
  868. assert_equal '(p1)', m.params
  869. end
  870. def test_handle_method_args_0
  871. parser = util_parser "Document-method: BasicObject#==\n blah */"
  872. parser.handle_method 'method', 'rb_cBasicObject', '==', 'rb_obj_equal', 0
  873. bo = @top_level.find_module_named 'BasicObject'
  874. assert_equal 1, bo.method_list.length
  875. equals2 = bo.method_list.first
  876. assert_equal '()', equals2.params
  877. end
  878. def test_handle_method_args_1
  879. parser = util_parser "Document-method: BasicObject#==\n blah */"
  880. parser.handle_method 'method', 'rb_cBasicObject', '==', 'rb_obj_equal', 1
  881. bo = @top_level.find_module_named 'BasicObject'
  882. assert_equal 1, bo.method_list.length
  883. equals2 = bo.method_list.first
  884. assert_equal '(p1)', equals2.params
  885. end
  886. def test_handle_method_args_2
  887. parser = util_parser "Document-method: BasicObject#==\n blah */"
  888. parser.handle_method 'method', 'rb_cBasicObject', '==', 'rb_obj_equal', 2
  889. bo = @top_level.find_module_named 'BasicObject'
  890. assert_equal 1, bo.method_list.length
  891. equals2 = bo.method_list.first
  892. assert_equal '(p1, p2)', equals2.params
  893. end
  894. # test_handle_args_minus_1 handled by test_handle_method
  895. def test_handle_method_args_minus_2
  896. parser = util_parser "Document-method: BasicObject#==\n blah */"
  897. parser.handle_method 'method', 'rb_cBasicObject', '==', 'rb_obj_equal', -2
  898. bo = @top_level.find_module_named 'BasicObject'
  899. assert_equal 1, bo.method_list.length
  900. equals2 = bo.method_list.first
  901. assert_equal '(*args)', equals2.params
  902. end
  903. def test_handle_method_initialize
  904. parser = util_parser "Document-method: BasicObject::new\n blah */"
  905. parser.handle_method('private_method', 'rb_cBasicObject',
  906. 'initialize', 'rb_obj_dummy', -1)
  907. bo = @top_level.find_module_named 'BasicObject'
  908. assert_equal 1, bo.method_list.length
  909. new = bo.method_list.first
  910. assert_equal 'new', new.name
  911. assert_equal :public, new.visibility
  912. end
  913. def test_handle_singleton
  914. parser = util_parser <<-SINGLE
  915. void Init_Blah(void) {
  916. cDate = rb_define_class("Date", rb_cObject);
  917. sDate = rb_singleton_class(cDate);
  918. }
  919. SINGLE
  920. parser.scan
  921. assert_equal 'Date', parser.known_classes['sDate']
  922. assert_equal 'Date', parser.singleton_classes['sDate']
  923. end
  924. def test_look_for_directives_in
  925. parser = util_parser ''
  926. comment = "# :markup: not_rdoc\n"
  927. parser.look_for_directives_in @top_level, comment
  928. assert_equal "# :markup: not_rdoc\n", comment
  929. assert_equal 'not_rdoc', @top_level.metadata['markup']
  930. end
  931. def test_define_method
  932. content = <<-EOF
  933. /*Method Comment! */
  934. static VALUE
  935. rb_io_s_read(argc, argv, io)
  936. int argc;
  937. VALUE *argv;
  938. VALUE io;
  939. {
  940. }
  941. void
  942. Init_IO(void) {
  943. /*
  944. * a comment for class Foo on rb_define_class
  945. */
  946. VALUE rb_cIO = rb_define_class("IO", rb_cObject);
  947. rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
  948. }
  949. EOF
  950. klass = util_get_class content, 'rb_cIO'
  951. read_method = klass.method_list.first
  952. assert_equal "read", read_method.name
  953. assert_equal "Method Comment! ", read_method.comment
  954. assert_equal "rb_io_s_read", read_method.c_function
  955. assert read_method.singleton
  956. end
  957. def test_define_method_with_prototype
  958. content = <<-EOF
  959. static VALUE rb_io_s_read(int, VALUE*, VALUE);
  960. /* Method Comment! */
  961. static VALUE
  962. rb_io_s_read(argc, argv, io)
  963. int argc;
  964. VALUE *argv;
  965. VALUE io;
  966. {
  967. }
  968. void
  969. Init_IO(void) {
  970. /*
  971. * a comment for class Foo on rb_define_class
  972. */
  973. VALUE rb_cIO = rb_define_class("IO", rb_cObject);
  974. rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
  975. }
  976. EOF
  977. klass = util_get_class content, 'rb_cIO'
  978. read_method = klass.method_list.first
  979. assert_equal "read", read_method.name
  980. assert_equal "Method Comment! ", read_method.comment
  981. assert_equal "rb_io_s_read", read_method.c_function
  982. assert read_method.singleton
  983. end
  984. def test_define_method_private
  985. content = <<-EOF
  986. /*Method Comment! */
  987. static VALUE
  988. rb_io_s_read(argc, argv, io)
  989. int argc;
  990. VALUE *argv;
  991. VALUE io;
  992. {
  993. }
  994. void
  995. Init_IO(void) {
  996. /*
  997. * a comment for class Foo on rb_define_class
  998. */
  999. VALUE rb_cIO = rb_define_class("IO", rb_cObject);
  1000. rb_define_private_method(rb_cIO, "read", rb_io_s_read, -1);
  1001. }
  1002. EOF
  1003. klass = util_get_class content, 'rb_cIO'
  1004. read_method = klass.method_list.first
  1005. assert_equal 'IO#read', read_method.full_name
  1006. assert_equal :private, read_method.visibility
  1007. assert_equal "Method Comment! ", read_method.comment
  1008. end
  1009. def test_define_method_private_singleton
  1010. content = <<-EOF
  1011. /*Method Comment! */
  1012. static VALUE
  1013. rb_io_s_read(argc, argv, io)
  1014. int argc;
  1015. VALUE *argv;
  1016. VALUE io;
  1017. {
  1018. }
  1019. void
  1020. Init_IO(void) {
  1021. /*
  1022. * a comment for class Foo on rb_define_class
  1023. */
  1024. VALUE rb_cIO = rb_define_class("IO", rb_cObject);
  1025. VALUE rb_cIO_s = rb_singleton_class(rb_cIO);
  1026. rb_define_private_method(rb_cIO_s, "read", rb_io_s_read, -1);
  1027. }
  1028. EOF
  1029. klass = util_get_class content, 'rb_cIO'
  1030. read_method = klass.method_list.first
  1031. assert_equal "read", read_method.name
  1032. assert_equal "Method Comment! ", read_method.comment
  1033. assert_equal :private, read_method.visibility
  1034. assert read_method.singleton
  1035. end
  1036. def test_define_method_singleton
  1037. content = <<-EOF
  1038. /*Method Comment! */
  1039. static VALUE
  1040. rb_io_s_read(argc, argv, io)
  1041. int argc;
  1042. VALUE *argv;
  1043. VALUE io;
  1044. {
  1045. }
  1046. void
  1047. Init_IO(void) {
  1048. /*
  1049. * a comment for class Foo on rb_define_class
  1050. */
  1051. VALUE rb_cIO = rb_define_class("IO", rb_cObject);
  1052. VALUE rb_cIO_s = rb_singleton_class(rb_cIO);
  1053. rb_define_method(rb_cIO_s, "read", rb_io_s_read, -1);
  1054. }
  1055. EOF
  1056. klass = util_get_class content, 'rb_cIO'
  1057. read_method = klass.method_list.first
  1058. assert_equal "read", read_method.name
  1059. assert_equal "Method Comment! ", read_method.comment
  1060. assert read_method.singleton
  1061. end
  1062. def test_rb_scan_args
  1063. parser = util_parser ''
  1064. assert_equal '(p1)',
  1065. parser.rb_scan_args('rb_scan_args(a, b, "1",)')
  1066. assert_equal '(p1, p2)',
  1067. parser.rb_scan_args('rb_scan_args(a, b, "2",)')
  1068. assert_equal '(p1 = v1)',
  1069. parser.rb_scan_args('rb_scan_args(a, b, "01",)')
  1070. assert_equal '(p1 = v1, p2 = v2)',
  1071. parser.rb_scan_args('rb_scan_args(a, b, "02",)')
  1072. assert_equal '(p1, p2 = v2)',
  1073. parser.rb_scan_args('rb_scan_args(a, b, "11",)')
  1074. assert_equal '(p1, *args)',
  1075. parser.rb_scan_args('rb_scan_args(a, b, "1*",)')
  1076. assert_equal '(p1, p2 = {})',
  1077. parser.rb_scan_args('rb_scan_args(a, b, "1:",)')
  1078. assert_equal '(p1, &block)',
  1079. parser.rb_scan_args('rb_scan_args(a, b, "1&",)')
  1080. assert_equal '(p1, p2)',
  1081. parser.rb_scan_args('rb_scan_args(a, b, "101",)')
  1082. assert_equal '(p1, p2 = v2, p3)',
  1083. parser.rb_scan_args('rb_scan_args(a, b, "111",)')
  1084. assert_equal '(p1, *args, p3)',
  1085. parser.rb_scan_args('rb_scan_args(a, b, "1*1",)')
  1086. assert_equal '(p1, p2 = v2, *args)',
  1087. parser.rb_scan_args('rb_scan_args(a, b, "11*",)')
  1088. assert_equal '(p1, p2 = v2, p3 = {})',
  1089. parser.rb_scan_args('rb_scan_args(a, b, "11:",)')
  1090. assert_equal '(p1, p2 = v2, &block)',
  1091. parser.rb_scan_args('rb_scan_args(a, b, "11&",)')
  1092. assert_equal '(p1, p2 = v2, *args, p4, p5 = {}, &block)',
  1093. parser.rb_scan_args('rb_scan_args(a, b, "11*1:&",)')
  1094. # The following aren't valid according to spec but are according to the
  1095. # implementation.
  1096. assert_equal '(*args)',
  1097. parser.rb_scan_args('rb_scan_args(a, b, "*",)')
  1098. assert_equal '(p1 = {})',
  1099. parser.rb_scan_args('rb_scan_args(a, b, ":",)')
  1100. assert_equal '(&block)',
  1101. parser.rb_scan_args('rb_scan_args(a, b, "&",)')
  1102. assert_equal '(*args, p2 = {})',
  1103. parser.rb_scan_args('rb_scan_args(a, b, "*:",)')
  1104. assert_equal '(p1 = {}, &block)',
  1105. parser.rb_scan_args('rb_scan_args(a, b, ":&",)')
  1106. assert_equal '(*args, p2 = {}, &block)',
  1107. parser.rb_scan_args('rb_scan_args(a, b, "*:&",)')
  1108. end
  1109. def util_get_class(content, name)
  1110. @parser = util_parser content
  1111. @parser.scan
  1112. @parser.classes[name]
  1113. end
  1114. def util_parser(content)
  1115. RDoc::Parser::C.new @top_level, @fn, content, @options, @stats
  1116. end
  1117. end