123456789_123456789_123456789_123456789_123456789_

Class: RSpec::Core::Formatters::Loader Private

Do not use. This class is for internal use only.
Relationships & Source Files
Inherits: Object
Defined in: rspec-core/lib/rspec/core/formatters.rb

Overview

Loader is an internal class for managing formatters used by a particular configuration. It is not expected to be used directly, but only through the configuration interface.

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Class Method Details

.formatters

Internal formatters are stored here when loaded.

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 100

def self.formatters
  @formatters ||= {}
end

Instance Attribute Details

#default_formatterString (rw)

Returns:

  • (String)

    the default formatter to setup, defaults to ‘progress`

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 118

attr_accessor :default_formatter

#formattersArray (readonly)

Returns:

  • (Array)

    the loaded formatters

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 112

attr_reader :formatters

#reporterReporter (readonly)

Returns:

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 115

attr_reader :reporter

Instance Method Details

#add(formatter_to_use, *paths)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 144

def add(formatter_to_use, *paths)
  # If a formatter instance was passed, we can register it directly,
  # with no need for any of the further processing that happens below.
  if Loader.formatters.key?(formatter_to_use.class)
    register formatter_to_use, notifications_for(formatter_to_use.class)
    return
  end

  formatter_class = find_formatter(formatter_to_use)

  args = paths.map { |p| p.respond_to?(:puts) ? p : open_stream(p) }

  if !Loader.formatters[formatter_class].nil?
    formatter = formatter_class.new(*args)
    register formatter, notifications_for(formatter_class)
  elsif defined?(RSpec::LegacyFormatters)
    formatter = RSpec::LegacyFormatters.load_formatter formatter_class, *args
    register formatter, formatter.notifications
  else
    call_site = "Formatter added at: #{::RSpec::CallerFilter.first_non_rspec_line}"

    RSpec.warn_deprecation <<-WARNING.gsub(/\s*\|/, ' ')
      |The #{formatter_class} formatter uses the deprecated formatter
      |interface not supported directly by RSpec 3.
      |
      |To continue to use this formatter you must install the
      |`rspec-legacy_formatters` gem, which provides support
      |for legacy formatters or upgrade the formatter to a
      |compatible version.
      |
      |#{call_site}
    WARNING
  end
end

#built_in_formatter(key) (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 211

def built_in_formatter(key)
  case key.to_s
  when 'd', 'doc', 'documentation'
    DocumentationFormatter
  when 'h', 'html'
    HtmlFormatter
  when 'p', 'progress'
    ProgressFormatter
  when 'j', 'json'
    JsonFormatter
  when 'bisect-drb'
    BisectDRbFormatter
  when 'f', 'failures'
    FailureListFormatter
  end
end

#custom_formatter(formatter_ref) (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 234

def custom_formatter(formatter_ref)
  if Class === formatter_ref
    formatter_ref
  elsif string_const?(formatter_ref)
    begin
      formatter_ref.gsub(/^::/, '').split('::').inject(Object) { |a, e| a.const_get e }
    rescue NameError
      require(path_for(formatter_ref)) ? retry : raise
    end
  end
end

#duplicate_formatter_exists?(new_formatter) ⇒ Boolean (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 195

def duplicate_formatter_exists?(new_formatter)
  @formatters.any? do |formatter|
    formatter.class == new_formatter.class &&
      has_matching_output?(formatter, new_formatter)
  end
end

#existing_formatter_implements?(notification) ⇒ Boolean (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 207

def existing_formatter_implements?(notification)
  @reporter.registered_listeners(notification).any?
end

#find_formatter(formatter_to_use) (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 181

def find_formatter(formatter_to_use)
  built_in_formatter(formatter_to_use) ||
  custom_formatter(formatter_to_use)   ||
  (raise ArgumentError, "Formatter '#{formatter_to_use}' unknown - " \
                        "maybe you meant 'documentation' or 'progress'?.")
end

#has_matching_output?(formatter, new_formatter) ⇒ Boolean (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 202

def has_matching_output?(formatter, new_formatter)
  return true unless formatter.respond_to?(:output) && new_formatter.respond_to?(:output)
  formatter.output == new_formatter.output
end

#notifications_for(formatter_class) (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 228

def notifications_for(formatter_class)
  formatter_class.ancestors.inject(::RSpec::Core::Set.new) do |notifications, klass|
    notifications.merge Loader.formatters.fetch(klass) { ::RSpec::Core::Set.new }
  end
end

#open_stream(path_or_wrapper) (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 269

def open_stream(path_or_wrapper)
  if RSpec::Core::OutputWrapper === path_or_wrapper
    path_or_wrapper.output = open_stream(path_or_wrapper.output)
    path_or_wrapper
  else
    RSpec::Support::DirectoryMaker.mkdir_p(File.dirname(path_or_wrapper))
    File.new(path_or_wrapper, 'w')
  end
end

#path_for(const_ref) (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 250

def path_for(const_ref)
  underscore_with_fix_for_non_standard_rspec_naming(const_ref)
end

#prepare_default(output_stream, deprecation_stream)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 121

def prepare_default(output_stream, deprecation_stream)
  reporter.prepare_default(self, output_stream, deprecation_stream)
end

#register(formatter, notifications) (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 188

def register(formatter, notifications)
  return if duplicate_formatter_exists?(formatter)
  @reporter.register_listener formatter, *notifications
  @formatters << formatter
  formatter
end

#setup_default(output_stream, deprecation_stream)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 126

def setup_default(output_stream, deprecation_stream)
  add default_formatter, output_stream if @formatters.empty?

  unless @formatters.any? { |formatter| DeprecationFormatter === formatter }
    add DeprecationFormatter, deprecation_stream, output_stream
  end

  unless existing_formatter_implements?(:message)
    add FallbackMessageFormatter, output_stream
  end

  return unless RSpec.configuration.profile_examples?
  return if existing_formatter_implements?(:dump_profile)

  add RSpec::Core::Formatters::ProfileFormatter, output_stream
end

#string_const?(str) ⇒ Boolean (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 246

def string_const?(str)
  str.is_a?(String) && /\A[A-Z][a-zA-Z0-9_:]*\z/ =~ str
end

#underscore(camel_cased_word) (private)

activesupport/lib/active_support/inflector/methods.rb, line 48

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 259

def underscore(camel_cased_word)
  word = camel_cased_word.to_s.dup
  word.gsub!(/::/, '/')
  word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
  word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
  word.tr!("-", "_")
  word.downcase!
  word
end

#underscore_with_fix_for_non_standard_rspec_naming(string) (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters.rb', line 254

def underscore_with_fix_for_non_standard_rspec_naming(string)
  underscore(string).sub(%r{(^|/)r_spec($|/)}, '\\1rspec\\2')
end