yard 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of yard might be problematic. Click here for more details.

Files changed (204) hide show
  1. data/LICENSE +1 -1
  2. data/README.markdown +200 -0
  3. data/Rakefile +6 -1
  4. data/benchmarks/format_args.rb +46 -0
  5. data/benchmarks/parsing.rb +13 -1
  6. data/benchmarks/rdoc_vs_yardoc.rb +10 -0
  7. data/benchmarks/ripper_parser.rb +12 -0
  8. data/docs/CODE_OBJECTS.markdown +121 -0
  9. data/docs/FAQ.markdown +34 -0
  10. data/docs/GENERATORS.markdown +211 -0
  11. data/docs/GETTING_STARTED.markdown +263 -0
  12. data/docs/GLOSSARY.markdown +13 -0
  13. data/docs/HANDLERS.markdown +158 -0
  14. data/docs/OVERVIEW.markdown +64 -0
  15. data/docs/PARSER.markdown +180 -0
  16. data/docs/TAGS.markdown +181 -0
  17. data/docs/WHATSNEW.markdown +96 -0
  18. data/docs/images/code-objects-class-diagram.png +0 -0
  19. data/docs/images/handlers-class-diagram.png +0 -0
  20. data/docs/images/overview-class-diagram.png +0 -0
  21. data/docs/images/parser-class-diagram.png +0 -0
  22. data/docs/images/tags-class-diagram.png +0 -0
  23. data/lib/yard.rb +4 -1
  24. data/lib/yard/autoload.rb +79 -31
  25. data/lib/yard/cli/yard_graph.rb +8 -2
  26. data/lib/yard/cli/yardoc.rb +61 -8
  27. data/lib/yard/code_objects/base.rb +78 -135
  28. data/lib/yard/code_objects/class_object.rb +9 -8
  29. data/lib/yard/code_objects/constant_object.rb +1 -0
  30. data/lib/yard/code_objects/extended_method_object.rb +9 -0
  31. data/lib/yard/code_objects/method_object.rb +18 -5
  32. data/lib/yard/code_objects/module_object.rb +8 -1
  33. data/lib/yard/code_objects/namespace_object.rb +25 -16
  34. data/lib/yard/code_objects/proxy.rb +22 -22
  35. data/lib/yard/core_ext/file.rb +1 -1
  36. data/lib/yard/core_ext/string.rb +0 -4
  37. data/lib/yard/core_ext/symbol_hash.rb +3 -2
  38. data/lib/yard/docstring.rb +180 -0
  39. data/lib/yard/generators/base.rb +33 -13
  40. data/lib/yard/generators/class_generator.rb +4 -2
  41. data/lib/yard/generators/constants_generator.rb +3 -2
  42. data/lib/yard/generators/full_doc_generator.rb +76 -9
  43. data/lib/yard/generators/helpers/base_helper.rb +18 -1
  44. data/lib/yard/generators/helpers/filter_helper.rb +2 -2
  45. data/lib/yard/generators/helpers/html_helper.rb +94 -39
  46. data/lib/yard/generators/helpers/html_syntax_highlight_helper.rb +49 -0
  47. data/lib/yard/generators/helpers/markup_helper.rb +86 -0
  48. data/lib/yard/generators/helpers/method_helper.rb +23 -7
  49. data/lib/yard/generators/method_generator.rb +15 -3
  50. data/lib/yard/generators/method_listing_generator.rb +3 -3
  51. data/lib/yard/generators/mixins_generator.rb +8 -2
  52. data/lib/yard/generators/module_generator.rb +3 -2
  53. data/lib/yard/generators/overloads_generator.rb +20 -0
  54. data/lib/yard/generators/quick_doc_generator.rb +3 -9
  55. data/lib/yard/generators/root_generator.rb +32 -0
  56. data/lib/yard/generators/source_generator.rb +2 -17
  57. data/lib/yard/generators/tags_generator.rb +34 -6
  58. data/lib/yard/generators/uml_generator.rb +16 -6
  59. data/lib/yard/handlers/base.rb +88 -253
  60. data/lib/yard/handlers/processor.rb +72 -0
  61. data/lib/yard/handlers/ruby/alias_handler.rb +38 -0
  62. data/lib/yard/handlers/ruby/attribute_handler.rb +69 -0
  63. data/lib/yard/handlers/ruby/base.rb +72 -0
  64. data/lib/yard/handlers/ruby/class_condition_handler.rb +70 -0
  65. data/lib/yard/handlers/ruby/class_handler.rb +74 -0
  66. data/lib/yard/handlers/ruby/class_variable_handler.rb +11 -0
  67. data/lib/yard/handlers/ruby/constant_handler.rb +12 -0
  68. data/lib/yard/handlers/ruby/exception_handler.rb +22 -0
  69. data/lib/yard/handlers/ruby/extend_handler.rb +19 -0
  70. data/lib/yard/handlers/{alias_handler.rb → ruby/legacy/alias_handler.rb} +3 -4
  71. data/lib/yard/handlers/{attribute_handler.rb → ruby/legacy/attribute_handler.rb} +2 -2
  72. data/lib/yard/handlers/ruby/legacy/base.rb +198 -0
  73. data/lib/yard/handlers/{class_handler.rb → ruby/legacy/class_handler.rb} +18 -6
  74. data/lib/yard/handlers/{class_variable_handler.rb → ruby/legacy/class_variable_handler.rb} +1 -1
  75. data/lib/yard/handlers/{constant_handler.rb → ruby/legacy/constant_handler.rb} +2 -2
  76. data/lib/yard/handlers/{exception_handler.rb → ruby/legacy/exception_handler.rb} +3 -3
  77. data/lib/yard/handlers/ruby/legacy/extend_handler.rb +18 -0
  78. data/lib/yard/handlers/ruby/legacy/method_handler.rb +31 -0
  79. data/lib/yard/handlers/ruby/legacy/mixin_handler.rb +28 -0
  80. data/lib/yard/handlers/{module_handler.rb → ruby/legacy/module_handler.rb} +1 -1
  81. data/lib/yard/handlers/{visibility_handler.rb → ruby/legacy/visibility_handler.rb} +1 -1
  82. data/lib/yard/handlers/{yield_handler.rb → ruby/legacy/yield_handler.rb} +4 -4
  83. data/lib/yard/handlers/ruby/method_condition_handler.rb +7 -0
  84. data/lib/yard/handlers/ruby/method_handler.rb +48 -0
  85. data/lib/yard/handlers/ruby/mixin_handler.rb +25 -0
  86. data/lib/yard/handlers/ruby/module_handler.rb +9 -0
  87. data/lib/yard/handlers/ruby/visibility_handler.rb +18 -0
  88. data/lib/yard/handlers/ruby/yield_handler.rb +28 -0
  89. data/lib/yard/parser/ruby/ast_node.rb +263 -0
  90. data/lib/yard/parser/{ruby_lex.rb → ruby/legacy/ruby_lex.rb} +258 -259
  91. data/lib/yard/parser/{statement.rb → ruby/legacy/statement.rb} +8 -4
  92. data/lib/yard/parser/ruby/legacy/statement_list.rb +262 -0
  93. data/lib/yard/parser/{token_list.rb → ruby/legacy/token_list.rb} +1 -1
  94. data/lib/yard/parser/ruby/ruby_parser.rb +307 -0
  95. data/lib/yard/parser/source_parser.rb +76 -45
  96. data/lib/yard/rake/yardoc_task.rb +6 -1
  97. data/lib/yard/registry.rb +45 -19
  98. data/lib/yard/serializers/file_system_serializer.rb +8 -3
  99. data/lib/yard/tags/default_factory.rb +70 -10
  100. data/lib/yard/tags/default_tag.rb +12 -0
  101. data/lib/yard/tags/library.rb +65 -26
  102. data/lib/yard/tags/option_tag.rb +12 -0
  103. data/lib/yard/tags/overload_tag.rb +62 -0
  104. data/lib/yard/tags/ref_tag.rb +7 -0
  105. data/lib/yard/tags/ref_tag_list.rb +27 -0
  106. data/lib/yard/tags/tag.rb +1 -0
  107. data/lib/yard/tags/tag_format_error.rb +6 -0
  108. data/spec/cli/yardoc_spec.rb +43 -0
  109. data/spec/code_objects/base_spec.rb +56 -68
  110. data/spec/code_objects/class_object_spec.rb +18 -6
  111. data/spec/code_objects/constants_spec.rb +2 -0
  112. data/spec/code_objects/method_object_spec.rb +33 -5
  113. data/spec/code_objects/module_object_spec.rb +66 -8
  114. data/spec/code_objects/namespace_object_spec.rb +37 -17
  115. data/spec/code_objects/proxy_spec.rb +13 -2
  116. data/spec/core_ext/string_spec.rb +14 -2
  117. data/spec/core_ext/symbol_hash_spec.rb +9 -3
  118. data/spec/docstring_spec.rb +139 -0
  119. data/spec/generators/full_doc_generator_spec.rb +29 -0
  120. data/spec/generators/helpers/html_helper_spec.rb +74 -0
  121. data/spec/generators/helpers/markup_helper_spec.rb +95 -0
  122. data/spec/handlers/alias_handler_spec.rb +16 -3
  123. data/spec/handlers/attribute_handler_spec.rb +1 -1
  124. data/spec/handlers/base_spec.rb +15 -141
  125. data/spec/handlers/class_condition_handler_spec.rb +49 -0
  126. data/spec/handlers/class_handler_spec.rb +44 -3
  127. data/spec/handlers/class_variable_handler_spec.rb +1 -1
  128. data/spec/handlers/constant_handler_spec.rb +1 -1
  129. data/spec/handlers/examples/alias_handler_001.rb.txt +7 -3
  130. data/spec/handlers/examples/class_condition_handler_001.rb.txt +61 -0
  131. data/spec/handlers/examples/class_handler_001.rb.txt +33 -0
  132. data/spec/handlers/examples/exception_handler_001.rb.txt +1 -1
  133. data/spec/handlers/examples/extend_handler_001.rb.txt +8 -0
  134. data/spec/handlers/examples/method_condition_handler_001.rb.txt +10 -0
  135. data/spec/handlers/examples/method_handler_001.rb.txt +16 -4
  136. data/spec/handlers/examples/mixin_handler_001.rb.txt +10 -2
  137. data/spec/handlers/examples/module_handler_001.rb.txt +4 -0
  138. data/spec/handlers/examples/visibility_handler_001.rb.txt +1 -1
  139. data/spec/handlers/exception_handler_spec.rb +2 -2
  140. data/spec/handlers/extend_handler_spec.rb +15 -0
  141. data/spec/handlers/legacy_base_spec.rb +128 -0
  142. data/spec/handlers/method_condition_handler_spec.rb +14 -0
  143. data/spec/handlers/method_handler_spec.rb +38 -5
  144. data/spec/handlers/mixin_handler_spec.rb +15 -7
  145. data/spec/handlers/module_handler_spec.rb +5 -1
  146. data/spec/handlers/processor_spec.rb +19 -0
  147. data/spec/handlers/ruby/base_spec.rb +90 -0
  148. data/spec/handlers/ruby/legacy/base_spec.rb +53 -0
  149. data/spec/handlers/spec_helper.rb +22 -16
  150. data/spec/handlers/visibility_handler_spec.rb +4 -4
  151. data/spec/handlers/yield_handler_spec.rb +1 -1
  152. data/spec/parser/ruby/ast_node_spec.rb +15 -0
  153. data/spec/parser/ruby/legacy/statement_list_spec.rb +145 -0
  154. data/spec/parser/{token_list_spec.rb → ruby/legacy/token_list_spec.rb} +4 -4
  155. data/spec/parser/source_parser_spec.rb +0 -15
  156. data/spec/rake/yardoc_task_spec.rb +48 -0
  157. data/spec/registry_spec.rb +28 -2
  158. data/spec/serializers/file_system_serializer_spec.rb +7 -1
  159. data/spec/spec_helper.rb +1 -1
  160. data/spec/tags/default_factory_spec.rb +135 -0
  161. data/spec/tags/default_tag_spec.rb +11 -0
  162. data/spec/tags/overload_tag_spec.rb +35 -0
  163. data/spec/tags/ref_tag_list_spec.rb +53 -0
  164. data/templates/default/attributes/html/header.erb +17 -5
  165. data/templates/default/attributes/text/header.erb +1 -1
  166. data/templates/default/fulldoc/html/all_files.erb +19 -0
  167. data/templates/default/fulldoc/html/all_methods.erb +8 -7
  168. data/templates/default/fulldoc/html/all_namespaces.erb +4 -1
  169. data/templates/default/fulldoc/html/app.js +1 -1
  170. data/templates/default/fulldoc/html/{readme.erb → file.erb} +2 -2
  171. data/templates/default/fulldoc/html/header.erb +1 -1
  172. data/templates/default/fulldoc/html/index.erb +4 -3
  173. data/templates/default/fulldoc/html/style.css +13 -3
  174. data/templates/default/fulldoc/html/syntax_highlight.css +8 -5
  175. data/templates/default/method/text/header.erb +1 -0
  176. data/templates/default/method/text/title.erb +1 -0
  177. data/templates/default/methodsignature/html/main.erb +10 -8
  178. data/templates/default/methodsignature/text/main.erb +4 -1
  179. data/templates/default/methodsummary/html/summary.erb +8 -4
  180. data/templates/default/methodsummary/text/summary.erb +4 -1
  181. data/templates/default/mixins/html/header.erb +3 -3
  182. data/templates/default/overloads/html/header.erb +8 -0
  183. data/templates/default/overloads/text/header.erb +8 -0
  184. data/templates/default/root/html/header.erb +4 -0
  185. data/templates/default/tags/html/example.erb +20 -0
  186. data/templates/default/tags/html/option.erb +27 -0
  187. data/templates/default/tags/html/param.erb +21 -0
  188. data/templates/default/tags/html/tags.erb +4 -1
  189. data/templates/default/tags/html/todo.erb +8 -0
  190. data/templates/default/tags/text/example.erb +14 -0
  191. data/templates/default/tags/text/header.erb +3 -3
  192. data/templates/default/tags/text/option.erb +5 -0
  193. data/templates/default/tags/text/param.erb +9 -0
  194. data/templates/default/uml/dot/dependencies.erb +1 -1
  195. data/templates/default/uml/dot/info.erb +1 -1
  196. data/templates/default/uml/dot/superclasses.erb +2 -2
  197. data/templates/javadoc/methodsummary/html/summary.erb +2 -2
  198. data/templates/javadoc/mixins/html/header.erb +3 -3
  199. metadata +108 -139
  200. data/README +0 -211
  201. data/lib/yard/handlers/method_handler.rb +0 -27
  202. data/lib/yard/handlers/mixin_handler.rb +0 -16
  203. data/lib/yard/parser/statement_list.rb +0 -167
  204. data/lib/yard/tags/merbdoc_factory.rb +0 -47
@@ -1,13 +1,22 @@
1
1
  require 'stringio'
2
+ require 'continuation' unless RUBY18
2
3
 
3
4
  module YARD
4
5
  module Parser
6
+ class UndocumentableError < Exception; end
5
7
  class LoadOrderError < Exception; end
6
8
 
7
9
  # Responsible for parsing a source file into the namespace
8
10
  class SourceParser
9
11
  class << self
12
+ attr_accessor :parser_type
13
+
14
+ def parser_type=(value)
15
+ @parser_type = validated_parser_type(value)
16
+ end
17
+
10
18
  def parse(paths = "lib/**/*.rb", level = log.level)
19
+ log.debug("Parsing #{paths} with `#{parser_type}` parser")
11
20
  if paths.is_a?(Array)
12
21
  files = paths.map {|p| Dir[p] }.flatten
13
22
  else
@@ -19,8 +28,16 @@ module YARD
19
28
  end
20
29
  end
21
30
 
22
- def parse_string(content)
23
- new.parse(StringIO.new(content))
31
+ def parse_string(content, ptype = parser_type)
32
+ new(ptype).parse(StringIO.new(content))
33
+ end
34
+
35
+ def tokenize(content, ptype = parser_type)
36
+ new(ptype).tokenize(content)
37
+ end
38
+
39
+ def validated_parser_type(type)
40
+ RUBY18 && type == :ruby ? :ruby18 : type
24
41
  end
25
42
 
26
43
  private
@@ -33,7 +50,7 @@ module YARD
33
50
  file.last.call
34
51
  elsif file.is_a?(String)
35
52
  log.debug("Processing #{file}...")
36
- new(true).parse(file)
53
+ new(parser_type, true).parse(file)
37
54
  end
38
55
  rescue LoadOrderError => e
39
56
  # Out of order file. Push the context to the end and we'll call it
@@ -43,67 +60,81 @@ module YARD
43
60
  end
44
61
  end
45
62
 
46
- attr_reader :file
47
- attr_accessor :namespace, :visibility, :scope, :owner, :load_order_errors
63
+ self.parser_type = :ruby
64
+
65
+ attr_reader :file, :parser_type
48
66
 
49
- def initialize(load_order_errors = false)
50
- @file = "<STDIN>"
51
- @namespace = YARD::Registry.root
52
- @visibility = :public
53
- @scope = :instance
54
- @owner = @namespace
67
+ def initialize(parser_type = SourceParser.parser_type, load_order_errors = false)
55
68
  @load_order_errors = load_order_errors
69
+ @file = '(stdin)'
70
+ self.parser_type = parser_type
56
71
  end
57
72
 
58
73
  ##
59
74
  # Creates a new SourceParser that parses a file and returns
60
75
  # analysis information about it.
61
76
  #
62
- # @param [String, TokenList, StatementList, #read] content the source file to parse
77
+ # @param [String, #read, Object] content the source file to parse
63
78
  def parse(content = __FILE__)
64
79
  case content
65
80
  when String
66
81
  @file = content
67
- statements = StatementList.new(IO.read(content))
68
- when TokenList
69
- statements = StatementList.new(content)
70
- when StatementList
71
- statements = content
82
+ content = IO.read(content)
83
+ self.parser_type = parser_type_for_filename(file)
72
84
  else
73
- if content.respond_to? :read
74
- statements = StatementList.new(content.read)
75
- else
76
- raise ArgumentError, "Invalid argument for SourceParser::parse: #{content.inspect}:#{content.class}"
77
- end
85
+ content = content.read if content.respond_to? :read
86
+ end
87
+
88
+ @parser = parse_statements(content)
89
+ post_process
90
+ @parser
91
+ end
92
+
93
+ def tokenize(content)
94
+ case parser_type
95
+ when :c
96
+ raise NotImplementedError, "no support for C/C++ files"
97
+ when :ruby18
98
+ Ruby::Legacy::TokenList.new(content)
99
+ when :ruby
100
+ Ruby::RubyParser.parse(content).tokens
101
+ else
102
+ raise ArgumentError, "invalid parser type or unrecognized file"
78
103
  end
104
+ end
105
+
106
+ private
79
107
 
80
- top_level_parse(statements)
108
+ def post_process
109
+ post = Handlers::Processor.new(@file, @load_order_errors, @parser_type)
110
+ post.process(@parser.enumerator)
81
111
  end
82
112
 
83
- private
84
- def top_level_parse(statements)
85
- statements.each do |stmt|
86
- find_handlers(stmt).each do |handler|
87
- begin
88
- handler.new(self, stmt).process
89
- rescue LoadOrderError => loaderr
90
- raise # Pass this up
91
- rescue Handlers::UndocumentableError => undocerr
92
- log.warn "in #{handler.to_s}: Undocumentable #{undocerr.message}"
93
- log.warn "\tin file '#{file}':#{stmt.tokens.first.line_no}:\n\n" + stmt.inspect + "\n"
94
- rescue => e
95
- log.error "Unhandled exception in #{handler.to_s}:"
96
- log.error "#{e.class.class_name}: #{e.message}"
97
- log.error " in `#{file}`:#{stmt.tokens.first.line_no}:\n\n#{stmt.inspect}\n"
98
- log.error "Stack trace:" + e.backtrace[0..5].map {|x| "\n\t#{x}" }.join + "\n"
99
- end
100
- end
101
- end
113
+ def parser_type=(value)
114
+ @parser_type = self.class.validated_parser_type(value)
115
+ end
116
+
117
+ def parser_type_for_filename(filename)
118
+ case (File.extname(filename)[1..-1] || "").downcase
119
+ when "c", "cpp", "cxx"
120
+ :c
121
+ else # when "rb", "rbx", "erb"
122
+ parser_type == :ruby18 ? :ruby18 : :ruby
102
123
  end
103
-
104
- def find_handlers(stmt)
105
- Handlers::Base.subclasses.find_all {|sub| sub.handles? stmt.tokens }
124
+ end
125
+
126
+ def parse_statements(content)
127
+ case parser_type
128
+ when :c
129
+ raise NotImplementedError, "no support for C/C++ files"
130
+ when :ruby18
131
+ Ruby::Legacy::StatementList.new(content)
132
+ when :ruby
133
+ Ruby::RubyParser.parse(content, file)
134
+ else
135
+ raise ArgumentError, "invalid parser type or unrecognized file"
106
136
  end
137
+ end
107
138
  end
108
139
  end
109
140
  end
@@ -8,6 +8,7 @@ module YARD
8
8
  attr_accessor :name
9
9
  attr_accessor :options
10
10
  attr_accessor :files
11
+ attr_accessor :before, :after
11
12
 
12
13
  def initialize(name = :yardoc)
13
14
  @name = name
@@ -23,7 +24,11 @@ module YARD
23
24
 
24
25
  def define
25
26
  desc "Generate YARD Documentation"
26
- task(name) { YARD::CLI::Yardoc.run *(options + files) }
27
+ task(name) do
28
+ before.call if before.is_a?(Proc)
29
+ YARD::CLI::Yardoc.run *(options + files)
30
+ after.call if after.is_a?(Proc)
31
+ end
27
32
  end
28
33
  end
29
34
  end
data/lib/yard/registry.rb CHANGED
@@ -62,14 +62,14 @@ module YARD
62
62
  def all(*types)
63
63
  namespace.values.select do |obj|
64
64
  if types.empty?
65
- obj != Registry.root
65
+ obj != root
66
66
  else
67
- obj != Registry.root &&
67
+ obj != root &&
68
68
  types.any? do |type|
69
69
  type.is_a?(Symbol) ? obj.type == type : obj.is_a?(type)
70
70
  end
71
71
  end
72
- end
72
+ end + (types.include?(:root) ? [root] : [])
73
73
  end
74
74
 
75
75
  def paths
@@ -80,7 +80,11 @@ module YARD
80
80
  alias_method :[], :at
81
81
 
82
82
  def root; namespace[:root] end
83
- def delete(object) namespace.delete(object.path) end
83
+
84
+ def delete(object)
85
+ namespace.delete(object.path)
86
+ self.class.objects.delete(object.path)
87
+ end
84
88
 
85
89
  def clear
86
90
  @namespace = SymbolHash.new
@@ -94,43 +98,65 @@ module YARD
94
98
  end
95
99
 
96
100
  def register(object)
101
+ self.class.objects[object.path] = object
97
102
  return if object.is_a?(CodeObjects::Proxy)
98
103
  namespace[object.path] = object
99
104
  end
100
105
 
101
- def resolve(namespace, name, proxy_fallback = false)
102
- namespace = root if namespace == :root || !namespace
106
+ def resolve(namespace, name, inheritance = false, proxy_fallback = false)
107
+ if namespace.is_a?(CodeObjects::Proxy)
108
+ return proxy_fallback ? CodeObjects::Proxy.new(namespace, name) : nil
109
+ end
110
+
111
+ if namespace == :root || !namespace
112
+ namespace = root
113
+ else
114
+ namespace = namespace.parent until namespace.is_a?(CodeObjects::NamespaceObject)
115
+ end
116
+ orignamespace = namespace
103
117
 
104
- newname = name.to_s.gsub(/^#{CodeObjects::ISEP}/, '')
105
- if name =~ /^#{CodeObjects::NSEP}/
106
- [name, newname[2..-1]].each do |n|
118
+ name = name.to_s
119
+ if name =~ /^#{CodeObjects::NSEPQ}/
120
+ [name, name[2..-1]].each do |n|
107
121
  return at(n) if at(n)
108
122
  end
109
123
  else
110
124
  while namespace
111
- [CodeObjects::NSEP, CodeObjects::ISEP].each do |s|
112
- path = newname
113
- if namespace != root
114
- path = [namespace.path, newname].join(s)
125
+ if namespace.is_a?(CodeObjects::NamespaceObject)
126
+ nss = inheritance ? namespace.inheritance_tree(true) : [namespace]
127
+ nss.each do |ns|
128
+ next if ns.is_a?(CodeObjects::Proxy)
129
+ found = partial_resolve(ns, name)
130
+ return found if found
115
131
  end
116
- found = at(path)
117
- return found if found
118
132
  end
119
133
  namespace = namespace.parent
120
134
  end
121
135
 
122
136
  # Look for ::name or #name in the root space
123
- [CodeObjects::NSEP, CodeObjects::ISEP].each do |s|
124
- found = at(s + newname)
137
+ [CodeObjects::ISEP, CodeObjects::NSEP].each do |s|
138
+ found = at(s + name)
125
139
  return found if found
126
140
  end
127
141
  end
128
- proxy_fallback ? CodeObjects::Proxy.new(namespace, name) : nil
142
+ proxy_fallback ? CodeObjects::Proxy.new(orignamespace, name) : nil
129
143
  end
130
144
 
131
145
  private
132
146
 
133
147
  attr_accessor :namespace
134
-
148
+
149
+ def partial_resolve(namespace, name)
150
+ [CodeObjects::NSEP, CodeObjects::CSEP, ''].each do |s|
151
+ next if s.empty? && name =~ /^\w/
152
+ path = name
153
+ if namespace != root
154
+ path = [namespace.path, name].join(s)
155
+ end
156
+ found = at(path)
157
+ return found if found
158
+ end
159
+ nil
160
+ end
135
161
  end
136
162
  end
@@ -21,7 +21,7 @@ module YARD
21
21
  def serialized_path(object)
22
22
  return object if object.is_a?(String)
23
23
 
24
- objname = object.name.to_s
24
+ objname = object != YARD::Registry.root ? object.name.to_s : "top-level-namespace"
25
25
  objname += '_' + object.scope.to_s[0,1] if object.is_a?(CodeObjects::MethodObject)
26
26
  fspath = [objname + (extension.empty? ? '' : ".#{extension}")]
27
27
  if object.namespace && object.namespace.path != ""
@@ -38,11 +38,16 @@ module YARD
38
38
  # Windows disallows \ / : * ? " < > | but we will just remove any
39
39
  # non alphanumeric (plus period, underscore and dash).
40
40
  fspath.map! do |p|
41
- p.gsub(/[^\w\.-]/) {|x| '_' + x[0].to_s(16).upcase }
41
+ p.gsub(/[^\w\.-]/) do |x|
42
+ encoded = '_'
43
+
44
+ x.each_byte { |b| encoded << ("%X" % b) }
45
+ encoded
46
+ end
42
47
  end
43
48
 
44
49
  File.join(fspath)
45
50
  end
46
51
  end
47
52
  end
48
- end
53
+ end
@@ -1,6 +1,9 @@
1
1
  module YARD
2
2
  module Tags
3
3
  class DefaultFactory
4
+ TYPELIST_OPENING_CHARS = '[({<'
5
+ TYPELIST_CLOSING_CHARS = '>})]'
6
+
4
7
  ##
5
8
  # Parses tag text and creates a new tag with descriptive text
6
9
  #
@@ -30,7 +33,8 @@ module YARD
30
33
  # @param [String] text the raw tag text
31
34
  # @return [Tag] a tag object with the tag_name, types and text values filled
32
35
  def parse_tag_with_types(tag_name, text)
33
- types, text = *extract_types_from_text(text)
36
+ name, types, text = *extract_types_and_name_from_text(text)
37
+ raise TagFormatError, "cannot specify a name before type list for '@#{tag_name}'" if name
34
38
  Tag.new(tag_name, text, types)
35
39
  end
36
40
 
@@ -42,8 +46,8 @@ module YARD
42
46
  # @param [String] text the raw tag text
43
47
  # @return [Tag] a tag object with the tag_name, name, types and text values filled
44
48
  def parse_tag_with_types_and_name(tag_name, text)
45
- types, text = *extract_types_from_text(text)
46
- name, text = *extract_name_from_text(text)
49
+ name, types, text = *extract_types_and_name_from_text(text)
50
+ name, text = *extract_name_from_text(text) unless name
47
51
  Tag.new(tag_name, text, types, name)
48
52
  end
49
53
 
@@ -56,6 +60,24 @@ module YARD
56
60
  Tag.new(tag_name, desc, nil, title)
57
61
  end
58
62
 
63
+ def parse_tag_with_types_name_and_default(tag_name, text)
64
+ # Can't allow () in a default tag, otherwise the grammar is too ambiguous when types is omitted.
65
+ open, close = TYPELIST_OPENING_CHARS.gsub('(', ''), TYPELIST_CLOSING_CHARS.gsub(')', '')
66
+ name, types, text = *extract_types_and_name_from_text(text, open, close)
67
+ name, text = *extract_name_from_text(text) unless name
68
+ if text =~ /\A\(/
69
+ _, default, text = *extract_types_and_name_from_text(text, '(', ')')
70
+ DefaultTag.new(tag_name, text, types, name, default)
71
+ else
72
+ DefaultTag.new(tag_name, text, types, name, nil)
73
+ end
74
+ end
75
+
76
+ def parse_tag_with_options(tag_name, text)
77
+ name, text = *extract_name_from_text(text)
78
+ OptionTag.new(tag_name, name, parse_tag_with_types_name_and_default(tag_name, text))
79
+ end
80
+
59
81
  private
60
82
 
61
83
  ##
@@ -69,17 +91,15 @@ module YARD
69
91
  end
70
92
 
71
93
  ##
72
- # Extracts the type signatures from the raw tag text
94
+ # Extracts the type signatures and optional name from the raw tag text
73
95
  #
74
96
  # @param [String] text the raw tag text
75
97
  # @return [Array] an array holding the value as the first element and
76
98
  # the array of types as the second element
77
- def extract_types_from_text(text)
78
- types, text = [], text.strip
79
- if text =~ /^\s*\[(.+?)\]\s*(.*)/
80
- text, types = $2, $1.split(",").collect {|e| e.strip }
81
- end
82
- [types, text]
99
+ def extract_types_and_name_from_text(text)
100
+ text = text.strip
101
+ types, range, name = *parse_types(text)
102
+ [name, types, (range ? text[(range.end+1)..-1].strip : text)]
83
103
  end
84
104
 
85
105
  def extract_title_and_desc_from_raw_text(raw_text)
@@ -93,6 +113,46 @@ module YARD
93
113
  end
94
114
  [title, desc]
95
115
  end
116
+
117
+ # Parses a [], <>, {} or () block at the beginning of a line of text into a list of
118
+ # comma delimited values. Returns the text be
119
+ #
120
+ # @example
121
+ # obj.parse_types('[String, Array<Hash, String>, nil]') # => [nil, ['String', 'Array<Hash, String>', 'nil'], ""]
122
+ # obj.parse_types('b<String> A string') # => ['b', ['String'], 'A string']
123
+ #
124
+ # @return [String, Array<String>] the text before the type list (or nil), followed by the type list parsed
125
+ # into an array of strings, followed by the text following the type list.
126
+ # @return [nil] if no type list is present.
127
+ def extract_types_and_name_from_text(text, opening_types = TYPELIST_OPENING_CHARS, closing_types = TYPELIST_CLOSING_CHARS)
128
+ s, e = 0, 0
129
+ before = ''
130
+ list, level = [''], 0
131
+ text.split(//).each_with_index do |c, i|
132
+ if opening_types.include?(c)
133
+ list.last << c if level > 0
134
+ s = i if level == 0
135
+ level += 1
136
+ elsif closing_types.include?(c)
137
+ level -= 1 unless list.last[-1,1] == '='
138
+ break e = i if level == 0
139
+ list.last << c
140
+ elsif c == ',' && level == 1
141
+ list.push ''
142
+ elsif c =~ /\S/ && level == 0
143
+ before << c
144
+ elsif level >= 1
145
+ list.last << c
146
+ end
147
+ end
148
+
149
+ before = before.empty? ? nil : before.strip
150
+ if list.size == 1 && list.first == ''
151
+ [nil, nil, text.strip]
152
+ else
153
+ [before, list.map {|x| x.strip }, text[(e+1)..-1].strip]
154
+ end
155
+ end
96
156
  end
97
157
  end
98
158
  end