Class: GherkinLint::Linter

Inherits:
Object
  • Object
show all
Defined in:
lib/gherkin_lint/linter.rb

Overview

base class for all linters

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeLinter

Returns a new instance of Linter.



13
14
15
16
# File 'lib/gherkin_lint/linter.rb', line 13

def initialize
  @issues = []
  @files = {}
end

Instance Attribute Details

#issuesObject (readonly)

Returns the value of attribute issues.



7
8
9
# File 'lib/gherkin_lint/linter.rb', line 7

def issues
  @issues
end

Class Method Details

.descendantsObject



9
10
11
# File 'lib/gherkin_lint/linter.rb', line 9

def self.descendants
  ObjectSpace.each_object(::Class).select { |klass| klass < self }
end

Instance Method Details

#add_error(references, description = nil) ⇒ Object



131
132
133
# File 'lib/gherkin_lint/linter.rb', line 131

def add_error(references, description = nil)
  @issues.push Error.new(name, references, description)
end

#add_warning(references, description = nil) ⇒ Object



135
136
137
# File 'lib/gherkin_lint/linter.rb', line 135

def add_warning(references, description = nil)
  @issues.push Warning.new(name, references, description)
end

#backgroundsObject



52
53
54
55
56
57
# File 'lib/gherkin_lint/linter.rb', line 52

def backgrounds
  elements do |file, feature, scenario|
    next unless scenario[:type] == :Background
    yield(file, feature, scenario)
  end
end

#elementsObject



59
60
61
62
63
64
65
66
67
68
# File 'lib/gherkin_lint/linter.rb', line 59

def elements
  @files.each do |file, content|
    feature = content[:feature]
    next if feature.nil?
    next unless feature.key? :children
    feature[:children].each do |scenario|
      yield(file, feature, scenario)
    end
  end
end

#featuresObject



18
19
20
21
22
23
24
# File 'lib/gherkin_lint/linter.rb', line 18

def features
  @files.each do |file, content|
    feature = content[:feature]
    next if feature.nil?
    yield(file, feature)
  end
end

#filesObject



26
27
28
# File 'lib/gherkin_lint/linter.rb', line 26

def files
  @files.keys.each { |file| yield file }
end

#filled_scenariosObject



37
38
39
40
41
42
43
# File 'lib/gherkin_lint/linter.rb', line 37

def filled_scenarios
  scenarios do |file, feature, scenario|
    next unless scenario.include? :steps
    next if scenario[:steps].empty?
    yield(file, feature, scenario)
  end
end

#filter_tag(data, tag) ⇒ Object



81
82
83
84
85
86
87
88
# File 'lib/gherkin_lint/linter.rb', line 81

def filter_tag(data, tag)
  return data.reject { |item| tag?(item, tag) }.map { |item| filter_tag(item, tag) } if data.class == Array
  return {} if (data.class == Hash) && (data.include? :feature) && tag?(data[:feature], tag)
  return data unless data.respond_to? :each_pair
  result = {}
  data.each_pair { |key, value| result[key] = filter_tag(value, tag) }
  result
end

#line(feature, scenario, step) ⇒ Object



124
125
126
127
128
129
# File 'lib/gherkin_lint/linter.rb', line 124

def line(feature, scenario, step)
  line = feature.nil? ? nil : feature[:location][:line]
  line = scenario[:location][:line] unless scenario.nil?
  line = step[:location][:line] unless step.nil?
  line
end

#lintObject



112
113
114
# File 'lib/gherkin_lint/linter.rb', line 112

def lint
  raise 'not implemented'
end

#lint_files(files, tags_to_suppress) ⇒ Object



74
75
76
77
78
79
# File 'lib/gherkin_lint/linter.rb', line 74

def lint_files(files, tags_to_suppress)
  @files = files
  @files = filter_tag(@files, "disable#{name}")
  @files = suppress_tags(@files, tags_to_suppress)
  lint
end

#nameObject



70
71
72
# File 'lib/gherkin_lint/linter.rb', line 70

def name
  self.class.name.split('::').last
end

#reference(file, feature = nil, scenario = nil, step = nil) ⇒ Object



116
117
118
119
120
121
122
# File 'lib/gherkin_lint/linter.rb', line 116

def reference(file, feature = nil, scenario = nil, step = nil)
  return file if feature.nil? || feature[:name].empty?
  result = "#{file} (#{line(feature, scenario, step)}): #{feature[:name]}"
  result += ".#{scenario[:name]}" unless scenario.nil? || scenario[:name].empty?
  result += " step: #{step[:text]}" unless step.nil?
  result
end

#render_step(step) ⇒ Object



139
140
141
142
143
# File 'lib/gherkin_lint/linter.rb', line 139

def render_step(step)
  value = "#{step[:keyword]}#{step[:text]}"
  value += render_step_argument step[:argument] if step.include? :argument
  value
end

#render_step_argument(argument) ⇒ Object



145
146
147
148
149
150
151
# File 'lib/gherkin_lint/linter.rb', line 145

def render_step_argument(argument)
  return "\n#{argument[:content]}" if argument[:type] == :DocString
  result = argument[:rows].map do |row|
    "|#{row[:cells].map { |cell| cell[:value] }.join '|'}|"
  end.join "\n"
  "\n#{result}"
end

#scenariosObject



30
31
32
33
34
35
# File 'lib/gherkin_lint/linter.rb', line 30

def scenarios
  elements do |file, feature, scenario|
    next if scenario[:type] == :Background
    yield(file, feature, scenario)
  end
end

#stepsObject



45
46
47
48
49
50
# File 'lib/gherkin_lint/linter.rb', line 45

def steps
  elements do |file, feature, scenario|
    next unless scenario.include? :steps
    scenario[:steps].each { |step| yield(file, feature, scenario, step) }
  end
end

#suppress(data, tags) ⇒ Object



108
109
110
# File 'lib/gherkin_lint/linter.rb', line 108

def suppress(data, tags)
  data.reject { |item| tags.map { |tag| "@#{tag}" }.include? item[:name] }
end

#suppress_tags(data, tags) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
# File 'lib/gherkin_lint/linter.rb', line 96

def suppress_tags(data, tags)
  return data.map { |item| suppress_tags(item, tags) } if data.class == Array
  return data unless data.class == Hash
  result = {}

  data.each_pair do |key, value|
    value = suppress(value, tags) if key == :tags
    result[key] = suppress_tags(value, tags)
  end
  result
end

#tag?(data, tag) ⇒ Boolean

Returns:

  • (Boolean)


90
91
92
93
94
# File 'lib/gherkin_lint/linter.rb', line 90

def tag?(data, tag)
  return false if data.class != Hash
  return false unless data.include? :tags
  data[:tags].map { |item| item[:name] }.include? "@#{tag}"
end