module CukeLinter
The top level namespace used by this gem
Constants
- DEFAULT_GIVEN_KEYWORD
The default keyword that is considered a 'Given' keyword
- DEFAULT_THEN_KEYWORD
The default keyword that is considered a 'Then' keyword
- DEFAULT_WHEN_KEYWORD
The default keyword that is considered a 'When' keyword
- VERSION
The release version of this gem
Public Class Methods
lint(file_paths: [], model_trees: [], linters: registered_linters.values, formatters: [[CukeLinter::PrettyFormatter.new]])
click to toggle source
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
# File lib/cuke_linter.rb, line 48 def lint(file_paths: [], model_trees: [], linters: registered_linters.values, formatters: [[CukeLinter::PrettyFormatter.new]]) # rubocop:disable Metrics/LineLength # 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 = collect_file_path_models(file_paths) model_sets = model_trees + file_path_models linting_data = lint_models(model_sets, linters) format_data(formatters, linting_data) linting_data end
Private Class Methods
collect_file_path_models(file_paths)
click to toggle source
# File lib/cuke_linter.rb, line 70 def collect_file_path_models(file_paths) file_paths.collect do |file_path| # TODO: raise exception unless path exists? if File.directory?(file_path) CukeModeler::Directory.new(file_path) elsif File.file?(file_path) && File.extname(file_path) == '.feature' CukeModeler::FeatureFile.new(file_path) end end.compact # Compacting in order to get rid of any `nil` values left over from non-feature files end
determine_final_linters(base_linters, disabled_linter_classes, enabled_linter_classes)
click to toggle source
# File lib/cuke_linter.rb, line 124 def determine_final_linters(base_linters, disabled_linter_classes, enabled_linter_classes) final_linters = base_linters.reject { |linter| disabled_linter_classes.include?(linter.class) } enabled_linter_classes.each do |clazz| final_linters << dynamic_linters[clazz] unless final_linters.map(&:class).include?(clazz) end final_linters end
dynamic_linters()
click to toggle source
# File lib/cuke_linter.rb, line 164 def dynamic_linters # No need to keep making new ones over and over... @dynamic_linters ||= Hash.new { |hash, key| hash[key] = key.new } # return @dynamic_linters if @dynamic_linters # # @dynamic_linters = {} end
format_data(formatters, linting_data)
click to toggle source
# File lib/cuke_linter.rb, line 172 def format_data(formatters, linting_data) 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 end
gather_directives_in_feature(feature_file_model)
click to toggle source
# File lib/cuke_linter.rb, line 148 def gather_directives_in_feature(feature_file_model) [].tap do |directives| feature_file_model.comments.each do |comment| pieces = comment.text.match(/#\s*cuke_linter:(disable|enable)\s+(.*)/) next unless pieces # Skipping non-directive file comments linter_classes = pieces[2].tr(',', ' ').split(' ') linter_classes.each do |clazz| directives << { linter_class: Kernel.const_get(clazz), enabled_status: pieces[1] != 'disable', source_line: comment.source_line } end end end end
lint_models(model_sets, linters)
click to toggle source
# File lib/cuke_linter.rb, line 81 def lint_models(model_sets, linters) [].tap do |linting_data| 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 end end
linter_directives_for_feature_file(feature_file_model)
click to toggle source
# File lib/cuke_linter.rb, line 134 def linter_directives_for_feature_file(feature_file_model) # IMPORTANT ASSUMPTION: Models never change during the life of a linting, so data only has to be gathered once existing_directives = @directives_for_feature_file[feature_file_model.object_id] return existing_directives if existing_directives directives = gather_directives_in_feature(feature_file_model) # Make sure that the directives are in the same order as they appear in the source file directives = directives.sort_by { |a| a[:source_line] } @directives_for_feature_file[feature_file_model.object_id] = directives end
relevant_linters_for_model(base_linters, model)
click to toggle source
# File lib/cuke_linter.rb, line 102 def relevant_linters_for_model(base_linters, model) feature_file_model = model.get_ancestor(:feature_file) # Linter directives are not applicable for directory and feature file models. Every other # model type should have a feature file ancestor from which to grab linter directive comments. return base_linters if feature_file_model.nil? linter_modifications_for_model = {} linter_directives_for_feature_file(feature_file_model).each do |directive| # Assuming that the directives are in the same order that they appear in the file break if directive[:source_line] > model.source_line linter_modifications_for_model[directive[:linter_class]] = directive[:enabled_status] end disabled_linter_classes = linter_modifications_for_model.reject { |_name, status| status }.keys enabled_linter_classes = linter_modifications_for_model.select { |_name, status| status }.keys determine_final_linters(base_linters, disabled_linter_classes, enabled_linter_classes) end