lib/yard/server/library_version.rb in yard-0.9.5 vs lib/yard/server/library_version.rb in yard-0.9.6

- old
+ new

@@ -1,5 +1,6 @@ +# frozen_string_literal: true require 'fileutils' require 'thread' module YARD module Server @@ -47,41 +48,46 @@ # # == Implementing a Custom Library Source # YARD can be extended to support custom library sources in order to # build or retrieve a yardoc file at runtime from many different locations. # - # To implement this behaviour, two methods must be added to the +LibraryVersion+ - # class, +#load_yardoc_from_SOURCE+ and +#source_path_for_SOURCE+. In both - # cases, "SOURCE" represents the source type used in {#source} when creating - # the library object. The +#source_path_for_SOURCE+ method is called upon + # To implement this behaviour, 3 methods can be added to the +LibraryVersion+ + # class, +#load_yardoc_from_SOURCE+, +#yardoc_file_for_SOURCE+, and + # +#source_path_for_SOURCE+. In all cases, "SOURCE" represents the source + # type used in {#source} when creating the library object. The + # +#yardoc_file_for_SOURCE+ and +#source_path_for_SOURCE+ methods are called upon # creation and should return the location where the source code for the library # lives. The load method is called from {#prepare!} if there is no yardoc file # and should set {#yardoc_file}. Below is a full example for # implementing a custom library source, +:http+, which reads packaged .yardoc # databases from zipped archives off of an HTTP server. # + # Note that only +#load_yardoc_from_SOURCE+ is required. The other two + # methods are optional and can be set manually (via {#source_path=} and + # {#yardoc_file=}) on the object at any time. + # # @example Implementing a Custom Library Source # # Adds the source type "http" for .yardoc files zipped on HTTP servers # class LibraryVersion # def load_yardoc_from_http - # return if yardoc_file # we have the library - # - # # otherwise download it in a thread and return immediately # Thread.new do # # zip/unzip method implementations are not shown # download_zip_file("http://mysite.com/yardocs/#{self}.zip") # unzip_file_to("/path/to/yardocs/#{self}") - # self.yardoc_file = "/path/to/yardocs/#{self}/.yardoc" - # self.source_path = self.yardoc_file # end # # # tell the server it's not ready yet (but it might be next time) # raise LibraryNotPreparedError # end # - # # we set this later - # def source_path_for_http; nil end + # def yardoc_file_for_http + # "/path/to/yardocs/#{self}/.yardoc" + # end + # + # def source_path_for_http + # File.dirname(yardoc_file) + # end # end # # # Creating a library of this source type: # LibraryVersion.new('name', '1.0', nil, :http) # @@ -94,11 +100,15 @@ # @return [String] the location of the yardoc file used to load the object # information from. # @return [nil] if no yardoc file exists yet. In this case, {#prepare!} will # be called on this library to build the yardoc file. - attr_accessor :yardoc_file + # @note To implement a custom yardoc file getter, implement + def yardoc_file + @yardoc_file ||= load_yardoc_file + end + attr_writer :yardoc_file # @return [Symbol] the source type representing where the yardoc should be # loaded from. Defaults are +:disk+ and +:gem+, though custom sources # may be implemented. This value is used to inform {#prepare!} about how # to load the necessary data in order to display documentation for an object. @@ -107,11 +117,14 @@ # @return [String] the location of the source code for a library. This # value is filled by calling +#source_path_for_SOURCE+ on this class. # @return [nil] if there is no source code # @see LibraryVersion LibraryVersion documentation for "Implementing a Custom Library Source" - attr_accessor :source_path + def source_path + @source_path ||= load_source_path + end + attr_writer :source_path # @param [String] name the name of the library # @param [String] version the specific (usually, but not always, numeric) library # version # @param [String] yardoc the location of the yardoc file, or nil if it is @@ -121,19 +134,18 @@ def initialize(name, version = nil, yardoc = nil, source = :disk) self.name = name self.yardoc_file = yardoc self.version = version self.source = source - self.source_path = load_source_path end # @param [Boolean] url_format if true, returns the string in a URI-compatible # format (for appending to a URL). Otherwise, it is given in a more human # readable format. # @return [String] the string representation of the library. def to_s(url_format = true) - version ? "#{name}#{url_format ? '/' : '-'}#{version}" : "#{name}" + version ? "#{name}#{url_format ? '/' : '-'}#{version}" : name.to_s end # @return [Fixnum] used for Hash mapping. def hash; to_s.hash end @@ -176,11 +188,11 @@ # @return [Gem::Specification] a gemspec object for a given library. Used # for :gem source types. # @return [nil] if there is no installed gem for the library def gemspec ver = version ? "= #{version}" : ">= 0" - Gem.source_index.find_name(name, ver).last + YARD::GemIndex.find_all_by_name(name, ver).last end protected @@chdir_mutex = Mutex.new @@ -210,21 +222,19 @@ # the installed gem. The yardoc file is built if it has not been done. # # @raise [LibraryNotPreparedError] if the gem does not have an existing # yardoc file. def load_yardoc_from_gem - require 'rubygems' - ver = version ? "= #{version}" : ">= 0" - self.yardoc_file = Registry.yardoc_file_for_gem(name, ver) return if ready? + ver = version ? "= #{version}" : ">= 0" @@chdir_mutex.synchronize do Thread.new do # Build gem docs on demand log.debug "Building gem docs for #{to_s(false)}" CLI::Gems.run(name, ver) - self.yardoc_file = Registry.yardoc_file_for_gem(name, ver) + log.debug "Done building gem docs for #{to_s(false)}" end end raise LibraryNotPreparedError end @@ -237,19 +247,31 @@ # @return [String] the source path for a gem source def source_path_for_gem gemspec.full_gem_path if gemspec end + # @return [String] the yardoc file for a gem source + def yardoc_file_for_gem + require 'rubygems' + ver = version ? "= #{version}" : ">= 0" + Registry.yardoc_file_for_gem(name, ver) + end + private def load_source_path meth = "source_path_for_#{source}" send(meth) if respond_to?(meth, true) end + def load_yardoc_file + meth = "yardoc_file_for_#{source}" + send(meth) if respond_to?(meth, true) + end + def serializer return if yardoc_file.nil? - @serializer ||= Serializers::YardocSerializer.new(yardoc_file) + Serializers::YardocSerializer.new(yardoc_file) end end end -end \ No newline at end of file +end