Class: Chutney::Linter

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

Overview

base class for all linters

Defined Under Namespace

Classes: Lint

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename, content, configuration) ⇒ Linter

Returns a new instance of Linter.



17
18
19
20
21
22
# File 'lib/chutney/linter.rb', line 17

def initialize(filename, content, configuration)
  @content = content
  @filename = filename
  @issues = []
  @configuration = configuration
end

Instance Attribute Details

#configurationObject (readonly)

Returns the value of attribute configuration.



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

def configuration
  @configuration
end

#filenameObject (readonly)

Returns the value of attribute filename.



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

def filename
  @filename
end

#issuesObject

Returns the value of attribute issues.



8
9
10
# File 'lib/chutney/linter.rb', line 8

def issues
  @issues
end

Class Method Details

.descendantsObject



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

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

.linter_nameObject



184
185
186
# File 'lib/chutney/linter.rb', line 184

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

Instance Method Details

#add_issue(message, feature = nil, scenario = nil, item = nil) ⇒ Object



83
84
85
86
87
88
89
90
91
# File 'lib/chutney/linter.rb', line 83

def add_issue(message, feature = nil, scenario = nil, item = nil)
  issues << Lint.new(
    message:,
    gherkin_type: type(feature, scenario, item),
    location: location(feature, scenario, item),
    feature: feature&.name,
    scenario: scenario&.name
  ).to_h
end

#and_word?(word) ⇒ Boolean

Returns:

  • (Boolean)


28
29
30
# File 'lib/chutney/linter.rb', line 28

def and_word?(word)
  dialect_word(:and).include?(word)
end

#backgroundObject



138
139
140
141
142
143
144
145
146
147
# File 'lib/chutney/linter.rb', line 138

def background
  return unless feature&.background
  return if off_switch?(feature)

  if block_given?
    yield(feature, feature.background)
  else
    feature.background
  end
end

#background_word?(word) ⇒ Boolean

Returns:

  • (Boolean)


32
33
34
# File 'lib/chutney/linter.rb', line 32

def background_word?(word)
  dialect_word(:background).include?(word)
end

#but_word?(word) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/chutney/linter.rb', line 36

def but_word?(word)
  dialect_word(:but).include?(word)
end

#dialectObject



68
69
70
71
72
73
74
75
76
77
# File 'lib/chutney/linter.rb', line 68

def dialect
  parsing_data = @content.feature&.parsing_data
  if !parsing_data.nil? && parsing_data.respond_to?(:language)
    parsing_data.language
  elsif parsing_data
    parsing_data[:language]
  else
    raise UnsupportedCucumberError, 'This version of cucumber is unsupported (langauge detection)'
  end
end

#dialect_word(word) ⇒ Object



64
65
66
# File 'lib/chutney/linter.rb', line 64

def dialect_word(word)
  CukeModeler::Parsing.dialects[dialect][word.to_s].map(&:strip)
end

#elementsObject



113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/chutney/linter.rb', line 113

def elements
  return [] unless feature

  if block_given?
    feature.children.each do |child|
      next if off_switch?(child)

      yield(feature, child)
    end
  else
    feature.children
  end
end

#examples_word?(word) ⇒ Boolean

Returns:

  • (Boolean)


40
41
42
# File 'lib/chutney/linter.rb', line 40

def examples_word?(word)
  dialect_word(:examples).include?(word)
end

#featureObject



105
106
107
108
109
110
111
# File 'lib/chutney/linter.rb', line 105

def feature
  if block_given?
    yield(@content.feature) if @content.feature
  else
    @content.feature
  end
end

#feature_word?(word) ⇒ Boolean

Returns:

  • (Boolean)


44
45
46
# File 'lib/chutney/linter.rb', line 44

def feature_word?(word)
  dialect_word(:feature).include?(word)
end

#filled_scenariosObject



162
163
164
165
166
167
168
169
170
171
172
# File 'lib/chutney/linter.rb', line 162

def filled_scenarios
  if block_given?
    scenarios do |feature, scenario|
      next if scenario.steps.empty?

      yield(feature, scenario)
    end
  else
    scenarios ? scenarios.filter { |s| !s.steps.empty? } : []
  end
end

#given_word?(word) ⇒ Boolean

Returns:

  • (Boolean)


48
49
50
# File 'lib/chutney/linter.rb', line 48

def given_word?(word)
  dialect_word(:given).include?(word)
end

#lintObject



24
25
26
# File 'lib/chutney/linter.rb', line 24

def lint
  raise 'not implemented'
end

#linter_nameObject



188
189
190
# File 'lib/chutney/linter.rb', line 188

def linter_name
  self.class.linter_name
end

#location(feature, scenario, step) ⇒ Object



93
94
95
# File 'lib/chutney/linter.rb', line 93

def location(feature, scenario, step)
  Locator.locate(feature, scenario, step)
end

#off_switch?(element = feature) ⇒ Boolean

Returns:

  • (Boolean)


127
128
129
130
131
132
133
134
135
136
# File 'lib/chutney/linter.rb', line 127

def off_switch?(element = feature)
  off_switch = element.tags
                      .map(&:name)
                      .then { |tags| tags || [] }
                      .filter { |tag_name| tag_name == "@disable#{linter_name}" }
                      .count
                      .positive?
  off_switch ||= off_switch?(feature) unless element == feature
  off_switch
end

#render_step(step) ⇒ Object



192
193
194
195
196
# File 'lib/chutney/linter.rb', line 192

def render_step(step)
  value = "#{step.keyword} #{step.text}"
  value += render_step_argument(step.block) if step.block
  value
end

#render_step_argument(argument) ⇒ Object



198
199
200
201
202
203
204
205
# File 'lib/chutney/linter.rb', line 198

def render_step_argument(argument)
  return "\n#{argument.content}" if argument.is_a?(CukeModeler::DocString)

  result = argument.rows.map do |row|
    "|#{row.cells.map(&:value).join '|'}|"
  end.join "\n"
  "\n#{result}"
end

#scenario_outline_word?(word) ⇒ Boolean

Returns:

  • (Boolean)


52
53
54
# File 'lib/chutney/linter.rb', line 52

def scenario_outline_word?(word)
  dialect_word(:scenarioOutline).include?(word)
end

#scenariosObject



149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/chutney/linter.rb', line 149

def scenarios
  if block_given?
    feature&.tests&.each do |test|
      next if off_switch?(test)

      yield(feature, test)
    end

  else
    feature&.tests
  end
end

#stepsObject



174
175
176
177
178
179
180
181
182
# File 'lib/chutney/linter.rb', line 174

def steps
  feature&.tests&.each do |test|
    next if off_switch?(test)

    test.steps.each do |step|
      yield(feature, test, step)
    end
  end
end

#tags_for(element) ⇒ Object



79
80
81
# File 'lib/chutney/linter.rb', line 79

def tags_for(element)
  element.tags.map { |tag| tag.name[1..] }
end

#then_word?(word) ⇒ Boolean

Returns:

  • (Boolean)


56
57
58
# File 'lib/chutney/linter.rb', line 56

def then_word?(word)
  dialect_word(:then).include?(word)
end

#type(_feature, scenario, step) ⇒ Object



97
98
99
100
101
102
103
# File 'lib/chutney/linter.rb', line 97

def type(_feature, scenario, step)
  if step
    :step
  else
    scenario ? :scenario : :feature
  end
end

#when_word?(word) ⇒ Boolean

Returns:

  • (Boolean)


60
61
62
# File 'lib/chutney/linter.rb', line 60

def when_word?(word)
  dialect_word(:when).include?(word)
end