lib/yard/code_objects/base.rb in yard-0.8.3 vs lib/yard/code_objects/base.rb in yard-0.8.4

- old
+ new

@@ -48,11 +48,11 @@ # Regular expression to match constant name CONSTANTMATCH = /[A-Z]\w*/ # Regular expression to match namespaces (const A or complex path A::B) - NAMESPACEMATCH = /(?:(?:#{NSEPQ})?#{CONSTANTMATCH})+/ + NAMESPACEMATCH = /(?:(?:#{NSEPQ}\s*)?#{CONSTANTMATCH})+/ # Regular expression to match a method name METHODNAMEMATCH = /[a-zA-Z_]\w*[!?=]?|[-+~]\@|<<|>>|=~|===?|<=>|[<>]=?|\*\*|[-\/+%^&*~`|]|\[\]=?/ # Regular expression to match a fully qualified method def (self.foo, Class.foo). @@ -134,13 +134,14 @@ # source line. # # @return [String] a line of source attr_accessor :signature - # The documentation string associated with the object + # The non-localized documentation string associated with the object # @return [Docstring] the documentation string - attr_reader :docstring + # @since 0.8.4 + attr_reader :base_docstring # Marks whether or not the method is conditionally defined at runtime # @return [Boolean] true if the method is conditionally defined at runtime attr_accessor :dynamic @@ -216,13 +217,12 @@ @current_file_has_comments = false @name = name.to_sym @source_type = :ruby @visibility = :public @tags = [] - @docstring = Docstring.new('', self) - @docstring_extra = nil - @docstring_extra_tags = nil + @docstrings = {} + @base_docstring = Docstring.new('', self) @namespace = nil self.namespace = namespace yield(self) if block_given? end @@ -235,11 +235,11 @@ def copy_to(other) copyable_attributes.each do |ivar| ivar = "@#{ivar}" other.instance_variable_set(ivar, instance_variable_get(ivar)) end - other.docstring = docstring.to_raw + other.docstring = @base_docstring.to_raw other end # The name of the object # @param [Boolean] prefix whether to show a prefix. Implement @@ -363,51 +363,52 @@ else @source = format_source(statement.to_s) end end - undef docstring - def docstring - return @docstring if !@docstring_extra - case @docstring - when Proxy - return @docstring_extra - when Base - @docstring = @docstring.docstring + @docstring_extra - @docstring.add_tag(*@docstring_extra_tags) - @docstring_extra = nil - @docstring_extra_tags = nil + # The documentation string associated with the object + # + # @param [String, I18n::Locale] locale (I18n::Locale.default) + # the locale of the documentation string. + # @return [Docstring] the documentation string + def docstring(locale = I18n::Locale.default) + if locale.nil? + @base_docstring.resolve_reference + return @base_docstring end - @docstring + + if locale.is_a?(String) + locale_name = locale + locale = nil + else + locale_name = locale.name + end + @docstrings[locale_name] ||= + translate_docstring(locale || Registry.locale(locale_name)) end # Attaches a docstring to a code object by parsing the comments attached to the statement # and filling the {#tags} and {#docstring} methods with the parsed information. # # @param [String, Array<String>, Docstring] comments # the comments attached to the code object to be parsed # into a docstring and meta tags. def docstring=(comments) - if comments =~ /\A\s*\(see (\S+)\s*\)(?:\s|$)/ - path, extra = $1, $' - @docstring_extra = Docstring.new(extra, self) - @docstring_extra_tags = Docstring === comments ? comments.tags : [] - @docstring_extra.add_tag(*@docstring_extra_tags) - @docstring = Proxy.new(namespace, path) + @docstrings.clear + if Docstring === comments + @base_docstring = comments else - @docstring_extra = nil - @docstring_extra_tags = nil - @docstring = Docstring === comments ? comments : Docstring.new(comments, self) + @base_docstring = Docstring.new(comments, self) end end # Default type is the lowercase class name without the "Object" suffix. # Override this method to provide a custom object type # # @return [Symbol] the type of code object this represents def type - self.class.name.split(/#{NSEPQ}/).last.gsub(/Object$/, '').downcase.to_sym + self.class.name.split('::').last.gsub(/Object$/, '').downcase.to_sym end # Represents the unique path of the object. The default implementation # joins the path of {#namespace} with {#name} via the value of {#sep}. # Custom code objects should ensure that the path is unique to the code @@ -424,10 +425,20 @@ name.to_s end end alias_method :to_s, :path + # @note + # Override this method if your object has a special title that does + # not match the {#path} attribute value. This title will be used + # when linking or displaying the object. + # @return [String] the display title for an object + # @see 0.8.4 + def title + path + end + # @param [Base, String] other another code object (or object path) # @return [String] the shortest relative path from this object to +other+ # @since 0.5.3 def relative_path(other) other = Registry.at(other) if String === other && Registry.at(other) @@ -507,10 +518,18 @@ # Tests if the {#docstring} has a tag # @see Docstring#has_tag? def has_tag?(name); docstring.has_tag?(name) end + # Add tags to the {#docstring} + # @see Docstring#add_tag + # @since 0.8.4 + def add_tag(*tags) + @docstrings.clear + @base_docstring.add_tag(*tags) + end + # @return whether or not this object is a RootObject def root?; false end # Override this method with a custom component separator. For instance, # {MethodObject} implements sep as '#' or '.' (depending on if the @@ -530,11 +549,11 @@ # "@" prefix) that should be copied when {#copy_to} is called # @see #copy_to # @since 0.8.0 def copyable_attributes vars = instance_variables.map {|ivar| ivar.to_s[1..-1] } - vars -= %w(docstring namespace name path) + vars -= %w(base_docstring docstrings namespace name path) vars end private @@ -545,9 +564,20 @@ def format_source(source) source.chomp! last = source.split(/\r?\n/).last indent = last ? last[/^([ \t]*)/, 1].length : 0 source.gsub(/^[ \t]{#{indent}}/, '') + end + + def translate_docstring(locale) + @base_docstring.resolve_reference + return @base_docstring if locale.nil? + + text = I18n::Text.new(@base_docstring) + localized_text = text.translate(locale) + docstring = Docstring.new(localized_text, self) + docstring.add_tag(*@base_docstring.tags) + docstring end end end end