Module: CukeLinter

Defined in:
lib/cuke_linter.rb,
lib/cuke_linter/version.rb,
lib/cuke_linter/linters/linter.rb,
lib/cuke_linter/formatters/pretty_formatter.rb,
lib/cuke_linter/linters/test_with_no_name_linter.rb,
lib/cuke_linter/linters/test_with_bad_name_linter.rb,
lib/cuke_linter/linters/example_without_name_linter.rb,
lib/cuke_linter/linters/feature_without_name_linter.rb,
lib/cuke_linter/linters/step_with_end_period_linter.rb,
lib/cuke_linter/linters/single_test_background_linter.rb,
lib/cuke_linter/linters/test_with_no_action_step_linter.rb,
lib/cuke_linter/linters/test_with_too_many_steps_linter.rb,
lib/cuke_linter/linters/feature_without_scenarios_linter.rb,
lib/cuke_linter/linters/element_with_too_many_tags_linter.rb,
lib/cuke_linter/linters/test_should_use_background_linter.rb,
lib/cuke_linter/linters/feature_without_description_linter.rb,
lib/cuke_linter/linters/step_with_too_many_characters_linter.rb,
lib/cuke_linter/linters/feature_file_with_invalid_name_linter.rb,
lib/cuke_linter/linters/test_with_no_verification_step_linter.rb,
lib/cuke_linter/linters/background_does_more_than_setup_linter.rb,
lib/cuke_linter/linters/outline_with_single_example_row_linter.rb,
lib/cuke_linter/linters/test_with_setup_step_as_final_step_linter.rb,
lib/cuke_linter/linters/test_with_action_step_as_final_step_linter.rb,
lib/cuke_linter/linters/feature_with_too_many_different_tags_linter.rb,
lib/cuke_linter/linters/test_with_setup_step_after_action_step_linter.rb,
lib/cuke_linter/linters/test_with_setup_step_after_verification_step_linter.rb

Overview

The top level namespace used by this gem

Defined Under Namespace

Classes: BackgroundDoesMoreThanSetupLinter, ElementWithTooManyTagsLinter, ExampleWithoutNameLinter, FeatureFileWithInvalidNameLinter, FeatureWithTooManyDifferentTagsLinter, FeatureWithoutDescriptionLinter, FeatureWithoutNameLinter, FeatureWithoutScenariosLinter, Linter, OutlineWithSingleExampleRowLinter, PrettyFormatter, SingleTestBackgroundLinter, StepWithEndPeriodLinter, StepWithTooManyCharactersLinter, TestShouldUseBackgroundLinter, TestWithActionStepAsFinalStepLinter, TestWithBadNameLinter, TestWithNoActionStepLinter, TestWithNoNameLinter, TestWithNoVerificationStepLinter, TestWithSetupStepAfterActionStepLinter, TestWithSetupStepAfterVerificationStepLinter, TestWithSetupStepAsFinalStepLinter, TestWithTooManyStepsLinter

Constant Summary collapse

VERSION =

The release version of this gem

'0.11.0'

Class Method Summary collapse

Class Method Details

.clear_registered_lintersObject

Unregisters all currently registered linting objects



109
110
111
# File 'lib/cuke_linter.rb', line 109

def self.clear_registered_linters
  self.registered_linters.clear
end

.lint(file_paths: [], model_trees: [], linters: self.registered_linters.values, formatters: [[CukeLinter::PrettyFormatter.new]]) ⇒ Object

Lints the given model trees and file paths using the given linting objects and formatting the results with the given formatters and their respective output locations



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/cuke_linter.rb', line 114

def self.lint(file_paths: [], model_trees: [], linters: self.registered_linters.values, formatters: [[CukeLinter::PrettyFormatter.new]])

  # TODO: Test this?
  # Because directive memoization is based on a model's `#object_id` and Ruby reuses object IDs over the
  # life of a program as objects are garbage collected, it is not safe to remember the IDs forever. However,
  # models shouldn't get GC'd in the middle of the linting process and so the start of the linting process is
  # a good time to reset things
  @directives_for_feature_file = {}

  model_trees                  = [CukeModeler::Directory.new(Dir.pwd)] if model_trees.empty? && file_paths.empty?
  file_path_models             = file_paths.collect do |file_path|
    # TODO: raise exception unless path exists
    case
      when File.directory?(file_path)
        CukeModeler::Directory.new(file_path)
      when File.file?(file_path) && File.extname(file_path) == '.feature'
        CukeModeler::FeatureFile.new(file_path)
      else
        # Non-feature files are not modeled
    end
  end.compact # Compacting in order to get rid of any `nil` values left over from non-feature files

  linting_data = []
  model_sets   = model_trees + file_path_models

  model_sets.each do |model_tree|
    model_tree.each_model do |model|
      applicable_linters = relevant_linters_for_model(linters, model)
      applicable_linters.each do |linter|
        # TODO: have linters lint only certain types of models
        #         linting_data.concat(linter.lint(model)) if relevant_model?(linter, model)

        result = linter.lint(model)

        if result
          result[:linter] = linter.name
          linting_data << result
        end
      end
    end
  end

  formatters.each do |formatter_output_pair|
    formatter = formatter_output_pair[0]
    location  = formatter_output_pair[1]

    formatted_data = formatter.format(linting_data)

    if location
      File.write(location, formatted_data)
    else
      puts formatted_data
    end
  end

  # TODO: keep this or always format data?
  linting_data
end

.load_configuration(config_file_path: nil, config: nil) ⇒ Object

Configures linters based on the given options



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/cuke_linter.rb', line 60

def self.load_configuration(config_file_path: nil, config: nil)
  # TODO: define what happens if both a configuration file and a configuration are provided. Merge them or have direct config take precedence? Both?

  unless config || config_file_path
    config_file_path = "#{Dir.pwd}/.cuke_linter"
    raise 'No configuration or configuration file given and no .cuke_linter file found' unless File.exist?(config_file_path)
  end

  config = config || YAML.load_file(config_file_path)

  common_config = config['AllLinters'] || {}
  to_delete     = []

  registered_linters.each_pair do |name, linter|
    linter_config = config[name] || {}
    final_config  = common_config.merge(linter_config)

    disabled = (final_config.key?('Enabled') && !final_config['Enabled'])

    # Just save it for afterwards because modifying a collection while iterating through it is not a good idea
    to_delete << name if disabled

    linter.configure(final_config) if linter.respond_to?(:configure)
  end

  to_delete.each { |linter_name| unregister_linter(linter_name) }
end

.register_linter(linter:, name:) ⇒ Object

Registers for linting use the given linter object, tracked by the given name



94
95
96
# File 'lib/cuke_linter.rb', line 94

def self.register_linter(linter:, name:)
  self.registered_linters[name] = linter
end

.registered_lintersObject

Lists the names of the currently registered linting objects



104
105
106
# File 'lib/cuke_linter.rb', line 104

def self.registered_linters
  @registered_linters ||= Marshal.load(Marshal.dump(@original_linters))
end

.reset_lintersObject

Returns the registered linters to their default state



89
90
91
# File 'lib/cuke_linter.rb', line 89

def self.reset_linters
  @registered_linters = nil
end

.unregister_linter(name) ⇒ Object

Unregisters the linter object tracked by the given name so that it is not used for linting



99
100
101
# File 'lib/cuke_linter.rb', line 99

def self.unregister_linter(name)
  self.registered_linters.delete(name)
end