123456789_123456789_123456789_123456789_123456789_

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

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

Constructor Details

.new(reporter) ⇒ Loader

[ GitHub ]

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

def initialize(reporter)
  @formatters = []
  @reporter = reporter
  self.default_formatter = 'progress'
end

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