puppet-lint-param_comment-check 0.1.4 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 760c2ecbb41952244ece53d7fddafcc91f322300b512a65dfc4d5ab7b5622636
4
- data.tar.gz: 187d476c9e3418c03935d00ddf84fd9c9618cd8ac4a14a391e0046f68f92221f
3
+ metadata.gz: 8c928aed3decd05d2876d4b37ecd564e069317d4b918bf49c36561bac2aa8878
4
+ data.tar.gz: 7122d1353312ff519d240c89e9e6e538cc7cd6453451ba8fa8c3cc2a90b86e64
5
5
  SHA512:
6
- metadata.gz: 8396f55b48c7cd1e82f66855eb950c2c1fd4e908423625a262e6ba11496d2cd3b9c90931c66deb97efba5d706502416e71ef4ae47f7d459b5c0fcf24d7b86ef4
7
- data.tar.gz: '08c1d478a70c0a204805844aa0ad1724ee7a371852c3f7059596204d3c62f89d9044fa2cf44b26b6df2731331f371765b3cdf86de148ecf5cab88216336dea93'
6
+ metadata.gz: 883d3841875fb24bc60cdf566a22e917a0a42c9f127739d82c22923eb092b39dbd3e804ec8d6392a04102b9f114142c48f9d98093f24d807c8177f3689b909c5
7
+ data.tar.gz: 4d76a9e6d9a79ed2989495a47456a8148661b3363cbf5d6c590e0f5ec028d8156995165f7991b5b21f5305441bdfd3e1d698bbe5c315ea64eeffeb03ef35b32a
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../../puppet-lint-param_comment-check/param_workflow'
4
3
  require_relative '../../puppet-lint-param_comment-check/param_comments'
4
+ require_relative '../../puppet-lint-param_comment-check/param'
5
5
 
6
6
  # The empty data of a parameter
7
7
  EMPTY_PARAM = {
@@ -18,52 +18,23 @@ EMPTY_PARAM = {
18
18
  # @return The head comments
19
19
  def get_comments(tokens, token_start)
20
20
  comments = []
21
- token_pointer = token_start
21
+ token_pointer = token_start - 1
22
22
  while token_pointer >= 0
23
- comments.append(tokens[token_pointer]) if tokens[token_pointer].type == :COMMENT
24
- token_pointer -= 1
25
- end
26
- comments.reverse
27
- end
23
+ break unless %i[COMMENT NEWLINE].include? tokens[token_pointer].type
28
24
 
29
- # Analyze a parameter token
30
- #
31
- # @param token The token to analyze
32
- # @param current_param the data object for the currently analyzed parameter
33
- def analyze_param_token(token, current_param)
34
- # noinspection RubyCaseWithoutElseBlockInspection
35
- case token.type
36
- when :VARIABLE
37
- current_param[:name] = token.value
38
- when :CLASSREF, :TYPE
39
- current_param[:type] = token.value
40
- when :EQUALS
41
- current_param[:has_default] = true
42
- current_param[:default] = token.next_token.value
25
+ comments.append(tokens[token_pointer])
26
+ token_pointer -= 1
43
27
  end
44
- current_param
28
+ comments.reject { |comment| comment.type == :NEWLINE }.reverse
45
29
  end
46
30
 
47
31
  # Analyze the parameters of a class or a defined type
48
32
  #
49
33
  # @param param_tokens The parameter tokens to analyze
50
- def analyze_params(param_tokens) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
51
- params = []
52
- current_param = EMPTY_PARAM.dup
53
- brackets = 0
54
- param_tokens.reject { |token| %i[WHITESPACE NEWLINE INDENT].include? token.type }.each do |token|
55
- brackets += 1 if %i[LBRACK LBRACE].include? token.type
56
- brackets -= 1 if %i[RBRACK RBRACE].include? token.type
57
- next unless brackets.zero?
58
-
59
- current_param = analyze_param_token(token, current_param) unless token.type == :COMMA
60
- if token.type == :COMMA
61
- params.append(current_param)
62
- current_param = EMPTY_PARAM.dup
63
- end
64
- end
65
- params.append(current_param) unless current_param[:name] == ''
66
- params
34
+ def analyze_params(param_tokens)
35
+ param_workflow = Param.new
36
+ param_workflow.process(param_tokens)
37
+ param_workflow.params
67
38
  end
68
39
 
69
40
  # Find, which parameters in the long list are missing in the short list and return their names
@@ -141,10 +112,14 @@ PuppetLint.new_check(:param_comment) do # rubocop:disable Metrics/BlockLength
141
112
  end
142
113
 
143
114
  # Check class or defined type indexes
144
- def check_indexes(indexes)
115
+ def check_indexes(indexes) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
145
116
  indexes.each do |index|
146
117
  comments = get_comments(tokens, index[:start])
147
- params = analyze_params(index[:param_tokens])
118
+ begin
119
+ params = analyze_params(index[:param_tokens])
120
+ rescue InvalidTokenForState, InvalidDefaultForOptional => e
121
+ return warn(e.message, e.token.line, e.token.column)
122
+ end
148
123
  return false unless check_comments(comments)
149
124
  return false unless check_parameters_count(params)
150
125
 
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'param_workflow'
4
+
5
+ PARAM_TYPE_ENUM = {
6
+ mandatory: 1,
7
+ with_default: 2,
8
+ optional: 3
9
+ }.freeze
10
+
11
+ # The empty data of a parameter
12
+ EMPTY_PARAM = {
13
+ name: '',
14
+ type: '',
15
+ default: [],
16
+ param_type: PARAM_TYPE_ENUM[:mandatory]
17
+ }.freeze
18
+
19
+ # Comment received in an invalid state
20
+ class InvalidTokenForState < StandardError
21
+ def initialize(token, state)
22
+ @token = token
23
+ @state = state
24
+ super "Can not process the token '#{@token.value.strip}' in the state #{@state}"
25
+ end
26
+
27
+ attr_reader :token
28
+ end
29
+
30
+ # An optional parameter does not have "undef" as the default
31
+ class InvalidDefaultForOptional < StandardError
32
+ def initialize(token, default_value)
33
+ @token = token
34
+ super "Invalid value '#{default_value}' for an parameter of type Optional. undef is required"
35
+ end
36
+
37
+ attr_reader :token
38
+ end
39
+
40
+ # A helper to analyze parameter comments using the ParamWorkflow fsm
41
+ class Param
42
+ def initialize
43
+ @workflow = ParamWorkflow.new(self)
44
+
45
+ reset
46
+ end
47
+
48
+ def reset
49
+ @params = []
50
+ @in_default = false
51
+ @default_tokens = []
52
+ @in_type = false
53
+ @type_tokens = []
54
+ @current_param = EMPTY_PARAM.dup
55
+ @current_token = nil
56
+ @workflow.restore!(:start)
57
+ end
58
+
59
+ # Walk through every parameter and transition the workflow fsm accordingly
60
+ #
61
+ # @param tokens A list of parameter tokens
62
+ def process(tokens) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
63
+ reset
64
+ brackets = 0
65
+ tokens.reject { |token| %i[NEWLINE INDENT].include? token.type }.each do |token| # rubocop:disable Metrics/BlockLength
66
+ @current_token = token
67
+ case token.type
68
+ when :TYPE
69
+ if @in_default
70
+ @default_tokens.append(token)
71
+ next
72
+ end
73
+ @workflow.got_type unless @in_type
74
+ @in_type = true
75
+ @type_tokens.append(token)
76
+ when :VARIABLE
77
+ @workflow.got_name(token, @type_tokens) unless @in_default
78
+ @in_type = false unless @in_default
79
+ @type_tokens = [] unless @in_default
80
+ @default_tokens.append(token) if @in_default
81
+ when :EQUALS
82
+ @in_default = true
83
+ when :COMMA
84
+ @workflow.got_end(@default_tokens) unless @in_type || brackets.positive?
85
+ @default_tokens = [] unless @in_type && brackets.positive?
86
+ @in_default = false unless @in_type && brackets.positive?
87
+ @type_tokens.append(token) if @in_type
88
+ when :LBRACE, :LBRACK
89
+ brackets += 1
90
+ @type_tokens.append(token) if @in_type
91
+ @default_tokens.append(token) if @in_default
92
+ when :RBRACE, :RBRACK
93
+ brackets -= 1
94
+ @type_tokens.append(token) if @in_type
95
+ @default_tokens.append(token) if @in_default
96
+ else
97
+ @type_tokens.append(token) if @in_type
98
+ @default_tokens.append(token) if @in_default
99
+ end
100
+ end
101
+ @workflow.got_end(@default_tokens) unless @workflow.current == :start
102
+ end
103
+
104
+ def got_name_trigger(_, token, type_tokens)
105
+ @current_param[:type] = type_tokens.map(&:value).join('')
106
+ if !@type_tokens.empty? && @type_tokens[0].value == 'OPTIONAL'
107
+ @current_param[:param_type] = PARAM_TYPE_ENUM[:optional]
108
+ end
109
+ @current_param[:name] = token.value
110
+ end
111
+
112
+ def got_end_trigger(_, default_tokens) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity
113
+ raise InvalidDefaultForOptional if @current_param[:param_type] == PARAM_TYPE_ENUM[:optional] &&
114
+ !default_tokens.empty? &&
115
+ default_tokens[0].value != 'undef'
116
+
117
+ @current_param[:default] = @default_tokens.map(&:value).join('') unless @default_tokens.empty?
118
+ @current_param[:param_type] = PARAM_TYPE_ENUM[:with_default] unless
119
+ @current_param[:param_type] == PARAM_TYPE_ENUM[:optional] || default_tokens.empty?
120
+ @params.append(@current_param)
121
+ @current_param = EMPTY_PARAM.dup
122
+ @in_default, @in_type = false
123
+ end
124
+
125
+ # Called when an invalid state transition would happen
126
+ def invalid_state
127
+ raise InvalidTokenForState.new(@current_token, @workflow.current)
128
+ end
129
+
130
+ # The list of analyzed parameters in the comments
131
+ attr_reader :params
132
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'param_comments_workflow'
4
+
3
5
  # The empty data of a parameter
4
6
  EMPTY_PARAM_COMMENT = {
5
7
  name: '',
@@ -56,19 +58,25 @@ end
56
58
  # A helper to analyze parameter comments using the ParamWorkflow fsm
57
59
  class ParamComments
58
60
  def initialize
59
- @workflow = ParamWorkflow.new(self)
61
+ @workflow = ParamCommentsWorkflow.new(self)
62
+
63
+ reset
64
+ end
60
65
 
66
+ def reset
61
67
  @current_param = nil
62
68
  @current_option = nil
63
69
  @in_option = false
64
70
  @params_have_started = false
65
71
  @params = []
72
+ @workflow.restore!(:start)
66
73
  end
67
74
 
68
75
  # Walk through every comment and transition the workflow fsm accordingly
69
76
  #
70
77
  # @param comments A list of Comment tokens appearing before the class/defined type header
71
- def process(comments) # rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
78
+ def process(comments) # rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/AbcSize
79
+ reset
72
80
  @current_comment = PuppetLint::Lexer::Token.new(:COMMENT, '', 1, 1)
73
81
  comments.each do |comment|
74
82
  @current_comment = comment
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'finite_machine'
4
+
5
+ # A finite state machine working through the expected parameter comments
6
+ class ParamCommentsWorkflow < FiniteMachine::Definition
7
+ initial :start
8
+
9
+ event :got_header, from: :start, to: :awaiting_description
10
+ event :got_header, from: :awaiting_header, to: :awaiting_description
11
+ event :got_description, from: :awaiting_description, to: :awaiting_separator
12
+ event :got_separator, from: :awaiting_separator, to: :awaiting_header
13
+
14
+ # for multi-line descriptions
15
+ event :got_description, from: :awaiting_separator, to: :awaiting_separator
16
+
17
+ # handling options
18
+ event :got_option_header, from: :awaiting_separator, to: :awaiting_option_description
19
+ event :got_option_description, from: :awaiting_option_description, to: :awaiting_separator
20
+
21
+ # for separators inside descriptions
22
+ event :got_description, from: :awaiting_header, to: :awaiting_separator
23
+ event :got_option_description, from: :awaiting_separator, to: :awaiting_separator
24
+
25
+ on_before(:got_header) { |event, comment| target.got_header_trigger(event, comment) }
26
+ on_before(:got_description) { |event, comment| target.got_description_trigger(event, comment) }
27
+ on_before(:got_option_description) { |event, comment| target.got_description_trigger(event, comment) }
28
+ on_before(:got_option_header) { |event, comment| target.got_option_header_trigger(event, comment) }
29
+
30
+ handle FiniteMachine::InvalidStateError, with: -> { target.invalid_state }
31
+ end
@@ -2,30 +2,22 @@
2
2
 
3
3
  require 'finite_machine'
4
4
 
5
- # A finite state machine working through the expected parameter comments
5
+ # A finite state machine working through the expected parameter tokens
6
6
  class ParamWorkflow < FiniteMachine::Definition
7
7
  initial :start
8
8
 
9
- event :got_header, from: :start, to: :awaiting_description
10
- event :got_header, from: :awaiting_header, to: :awaiting_description
11
- event :got_description, from: :awaiting_description, to: :awaiting_separator
12
- event :got_separator, from: :awaiting_separator, to: :awaiting_header
9
+ event :got_type, from: :start, to: :awaiting_name
10
+ event :got_name, from: :awaiting_name, to: :awaiting_default
13
11
 
14
- # for multi-line descriptions
15
- event :got_description, from: :awaiting_separator, to: :awaiting_separator
12
+ # For mandatory parameters
13
+ event :got_end, from: :awaiting_name, to: :start
14
+ event :got_end, from: :awaiting_default, to: :start
16
15
 
17
- # handling options
18
- event :got_option_header, from: :awaiting_separator, to: :awaiting_option_description
19
- event :got_option_description, from: :awaiting_option_description, to: :awaiting_separator
16
+ # For typeless parameters
17
+ event :got_name, from: :start, to: :awaiting_default
20
18
 
21
- # for separators inside descriptions
22
- event :got_description, from: :awaiting_header, to: :awaiting_separator
23
- event :got_option_description, from: :awaiting_separator, to: :awaiting_separator
24
-
25
- on_before(:got_header) { |event, comment| target.got_header_trigger(event, comment) }
26
- on_before(:got_description) { |event, comment| target.got_description_trigger(event, comment) }
27
- on_before(:got_option_description) { |event, comment| target.got_description_trigger(event, comment) }
28
- on_before(:got_option_header) { |event, comment| target.got_option_header_trigger(event, comment) }
19
+ on_before(:got_name) { |event, token, type_tokens| target.got_name_trigger(event, token, type_tokens) }
20
+ on_before(:got_end) { |event, default_tokens| target.got_end_trigger(event, default_tokens) }
29
21
 
30
22
  handle FiniteMachine::InvalidStateError, with: -> { target.invalid_state }
31
23
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require_relative '../../spec_helper'
4
4
 
5
+ # rubocop:disable Metrics/BlockLength
5
6
  describe 'param_comment' do
6
7
  context 'valid code' do
7
8
  let(:code) do
@@ -121,6 +122,38 @@ describe 'param_comment' do
121
122
  end
122
123
  end
123
124
 
125
+ context 'valid code with multiple classes' do
126
+ let(:code) do
127
+ <<~CODE
128
+ # @summary
129
+ # some class
130
+ #
131
+ # @param mandatory
132
+ # A mandatory parameter
133
+ # with two lines
134
+ class my_class (
135
+ String $mandatory,
136
+ ) {}
137
+
138
+ # @summary
139
+ # some other class
140
+ #
141
+ # @see something
142
+ #
143
+ # @param mandatory
144
+ # A mandatory parameter
145
+ # with two lines
146
+ class my_other_class (
147
+ String $mandatory,
148
+ ) {}
149
+ CODE
150
+ end
151
+
152
+ it 'should not detect any problems' do
153
+ expect(problems).to have(0).problems
154
+ end
155
+ end
156
+
124
157
  context 'code with missing parameter comment' do
125
158
  let(:code) do
126
159
  <<~CODE
@@ -223,9 +256,11 @@ describe 'param_comment' do
223
256
  end
224
257
 
225
258
  it 'should create a warning' do
226
- expect(problems).to contain_warning('Can not process the comment \'@param withdefault\' in the state awaiting_separator')
227
- .on_line(3)
228
- .in_column(1)
259
+ expect(problems).to contain_warning(
260
+ 'Can not process the comment \'@param withdefault\' in the state awaiting_separator'
261
+ )
262
+ .on_line(3)
263
+ .in_column(1)
229
264
  end
230
265
  end
231
266
 
@@ -244,9 +279,11 @@ describe 'param_comment' do
244
279
  end
245
280
 
246
281
  it 'should create a warning' do
247
- expect(problems).to contain_warning('Invalid param or hash option header: @param mandatory A mandatory parameter')
248
- .on_line(1)
249
- .in_column(1)
282
+ expect(problems).to contain_warning(
283
+ 'Invalid param or hash option header: @param mandatory A mandatory parameter'
284
+ )
285
+ .on_line(1)
286
+ .in_column(1)
250
287
  end
251
288
  end
252
289
 
@@ -289,9 +326,11 @@ describe 'param_comment' do
289
326
  end
290
327
 
291
328
  it 'should create a warning' do
292
- expect(problems).to contain_warning('Option references wrong hash @option mandatry [Boolean] :some_option')
293
- .on_line(3)
294
- .in_column(1)
329
+ expect(problems).to contain_warning(
330
+ 'Option references wrong hash @option mandatry [Boolean] :some_option'
331
+ )
332
+ .on_line(3)
333
+ .in_column(1)
295
334
  end
296
335
  end
297
336
 
@@ -315,10 +354,10 @@ describe 'param_comment' do
315
354
 
316
355
  it 'should create a warning' do
317
356
  expect(problems).to contain_warning(
318
- 'Can not process the comment \'@option mandatory [Boolean] :some_option\' in the state awaiting_header'
319
- )
320
- .on_line(4)
321
- .in_column(1)
357
+ 'Can not process the comment \'@option mandatory [Boolean] :some_option\' in the state awaiting_header'
358
+ )
359
+ .on_line(4)
360
+ .in_column(1)
322
361
  end
323
362
  end
324
363
 
@@ -340,10 +379,10 @@ describe 'param_comment' do
340
379
 
341
380
  it 'should create a warning' do
342
381
  expect(problems).to contain_warning(
343
- 'Invalid param or hash option header: @option mandatory [Boolean] :some_option An option'
344
- )
345
- .on_line(3)
346
- .in_column(1)
382
+ 'Invalid param or hash option header: @option mandatory [Boolean] :some_option An option'
383
+ )
384
+ .on_line(3)
385
+ .in_column(1)
347
386
  end
348
387
  end
349
388
 
@@ -369,10 +408,10 @@ describe 'param_comment' do
369
408
 
370
409
  it 'should create a warning' do
371
410
  expect(problems).to contain_warning(
372
- 'Can not process the comment \'@param second\' in the state awaiting_separator'
373
- )
374
- .on_line(5)
375
- .in_column(1)
411
+ 'Can not process the comment \'@param second\' in the state awaiting_separator'
412
+ )
413
+ .on_line(5)
414
+ .in_column(1)
376
415
  end
377
416
  end
378
417
 
@@ -394,3 +433,4 @@ describe 'param_comment' do
394
433
  end
395
434
  end
396
435
  end
436
+ # rubocop:enable Metrics/BlockLength
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppet-lint-param_comment-check
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dennis Ploeger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-31 00:00:00.000000000 Z
11
+ date: 2022-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: finite_machine
@@ -131,7 +131,9 @@ extra_rdoc_files: []
131
131
  files:
132
132
  - LICENSE
133
133
  - README.md
134
+ - lib/puppet-lint-param_comment-check/param.rb
134
135
  - lib/puppet-lint-param_comment-check/param_comments.rb
136
+ - lib/puppet-lint-param_comment-check/param_comments_workflow.rb
135
137
  - lib/puppet-lint-param_comment-check/param_workflow.rb
136
138
  - lib/puppet-lint/plugins/check_param_comment.rb
137
139
  - spec/puppet-lint/plugins/check_param_comment_spec.rb