puppet-lint-param_comment-check 0.1.5 → 0.1.6
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 +4 -4
- data/lib/puppet-lint/plugins/check_param_comment.rb +11 -38
- data/lib/puppet-lint-param_comment-check/param.rb +128 -0
- data/lib/puppet-lint-param_comment-check/param_comments.rb +4 -2
- data/lib/puppet-lint-param_comment-check/param_comments_workflow.rb +31 -0
- data/lib/puppet-lint-param_comment-check/param_workflow.rb +10 -18
- data/spec/puppet-lint/plugins/check_param_comment_spec.rb +30 -22
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb2381705a17c0af4eed37f55cd09a89fcaa0c14125c23437f3c664eb16cec37
|
4
|
+
data.tar.gz: 742a469983e7ccc5dd7c1779a313f9dbd16ed97a6f45d16f39c5c25d2038a510
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbe23d30e66a7bff997c0a757ea1ad22739284547ac0d4bcbb64a7a622f5b2b296399141fe2559fe0717c2b40563d72be50b526a41dbf179da855cfcb57c64ec
|
7
|
+
data.tar.gz: 85bf5c06abbaa3d3bfe4f57e0ba78f51622a439a3aa2c6c48df970419831e0d103fa838a3af80886e84548e968436a61a064cc72bff4dba932ef67f55d659db4
|
@@ -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 = {
|
@@ -28,44 +28,13 @@ def get_comments(tokens, token_start)
|
|
28
28
|
comments.reject { |comment| comment.type == :NEWLINE }.reverse
|
29
29
|
end
|
30
30
|
|
31
|
-
# Analyze a parameter token
|
32
|
-
#
|
33
|
-
# @param token The token to analyze
|
34
|
-
# @param current_param the data object for the currently analyzed parameter
|
35
|
-
def analyze_param_token(token, current_param)
|
36
|
-
# noinspection RubyCaseWithoutElseBlockInspection
|
37
|
-
case token.type
|
38
|
-
when :VARIABLE
|
39
|
-
current_param[:name] = token.value
|
40
|
-
when :CLASSREF, :TYPE
|
41
|
-
current_param[:type] = token.value
|
42
|
-
when :EQUALS
|
43
|
-
current_param[:has_default] = true
|
44
|
-
current_param[:default] = token.next_token.value
|
45
|
-
end
|
46
|
-
current_param
|
47
|
-
end
|
48
|
-
|
49
31
|
# Analyze the parameters of a class or a defined type
|
50
32
|
#
|
51
33
|
# @param param_tokens The parameter tokens to analyze
|
52
|
-
def analyze_params(param_tokens)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
param_tokens.reject { |token| %i[WHITESPACE NEWLINE INDENT].include? token.type }.each do |token|
|
57
|
-
brackets += 1 if %i[LBRACK LBRACE].include? token.type
|
58
|
-
brackets -= 1 if %i[RBRACK RBRACE].include? token.type
|
59
|
-
next unless brackets.zero?
|
60
|
-
|
61
|
-
current_param = analyze_param_token(token, current_param) unless token.type == :COMMA
|
62
|
-
if token.type == :COMMA
|
63
|
-
params.append(current_param)
|
64
|
-
current_param = EMPTY_PARAM.dup
|
65
|
-
end
|
66
|
-
end
|
67
|
-
params.append(current_param) unless current_param[:name] == ''
|
68
|
-
params
|
34
|
+
def analyze_params(param_tokens)
|
35
|
+
param_workflow = Param.new
|
36
|
+
param_workflow.process(param_tokens)
|
37
|
+
param_workflow.params
|
69
38
|
end
|
70
39
|
|
71
40
|
# Find, which parameters in the long list are missing in the short list and return their names
|
@@ -143,10 +112,14 @@ PuppetLint.new_check(:param_comment) do # rubocop:disable Metrics/BlockLength
|
|
143
112
|
end
|
144
113
|
|
145
114
|
# Check class or defined type indexes
|
146
|
-
def check_indexes(indexes)
|
115
|
+
def check_indexes(indexes) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
147
116
|
indexes.each do |index|
|
148
117
|
comments = get_comments(tokens, index[:start])
|
149
|
-
|
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
|
150
123
|
return false unless check_comments(comments)
|
151
124
|
return false unless check_parameters_count(params)
|
152
125
|
|
@@ -0,0 +1,128 @@
|
|
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
|
+
@workflow.got_type unless @in_type
|
70
|
+
@in_type = true
|
71
|
+
@type_tokens.append(token)
|
72
|
+
when :VARIABLE
|
73
|
+
@workflow.got_name(token, @type_tokens) unless @in_default
|
74
|
+
@in_type = false unless @in_default
|
75
|
+
@type_tokens = [] unless @in_default
|
76
|
+
@default_tokens.append(token) if @in_default
|
77
|
+
when :EQUALS
|
78
|
+
@in_default = true
|
79
|
+
when :COMMA
|
80
|
+
@workflow.got_end(@default_tokens) unless @in_type || brackets.positive?
|
81
|
+
@default_tokens = [] unless @in_type && brackets.positive?
|
82
|
+
@in_default = false unless @in_type && brackets.positive?
|
83
|
+
@type_tokens.append(token) if @in_type
|
84
|
+
when :LBRACE, :LBRACK
|
85
|
+
brackets += 1
|
86
|
+
@type_tokens.append(token) if @in_type
|
87
|
+
@default_tokens.append(token) if @in_default
|
88
|
+
when :RBRACE, :RBRACK
|
89
|
+
brackets -= 1
|
90
|
+
@type_tokens.append(token) if @in_type
|
91
|
+
@default_tokens.append(token) if @in_default
|
92
|
+
else
|
93
|
+
@type_tokens.append(token) if @in_type
|
94
|
+
@default_tokens.append(token) if @in_default
|
95
|
+
end
|
96
|
+
end
|
97
|
+
@workflow.got_end(@default_tokens) unless @workflow.current == :start
|
98
|
+
end
|
99
|
+
|
100
|
+
def got_name_trigger(_, token, type_tokens)
|
101
|
+
@current_param[:type] = type_tokens.map(&:value).join('')
|
102
|
+
if !@type_tokens.empty? && @type_tokens[0].value == 'OPTIONAL'
|
103
|
+
@current_param[:param_type] = PARAM_TYPE_ENUM[:optional]
|
104
|
+
end
|
105
|
+
@current_param[:name] = token.value
|
106
|
+
end
|
107
|
+
|
108
|
+
def got_end_trigger(_, default_tokens) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity
|
109
|
+
raise InvalidDefaultForOptional if @current_param[:param_type] == PARAM_TYPE_ENUM[:optional] &&
|
110
|
+
!default_tokens.empty? &&
|
111
|
+
default_tokens[0].value != 'undef'
|
112
|
+
|
113
|
+
@current_param[:default] = @default_tokens.map(&:value).join('') unless @default_tokens.empty?
|
114
|
+
@current_param[:param_type] = PARAM_TYPE_ENUM[:with_default] unless
|
115
|
+
@current_param[:param_type] == PARAM_TYPE_ENUM[:optional] || default_tokens.empty?
|
116
|
+
@params.append(@current_param)
|
117
|
+
@current_param = EMPTY_PARAM.dup
|
118
|
+
@in_default, @in_type = false
|
119
|
+
end
|
120
|
+
|
121
|
+
# Called when an invalid state transition would happen
|
122
|
+
def invalid_state
|
123
|
+
raise InvalidTokenForState.new(@current_token, @workflow.current)
|
124
|
+
end
|
125
|
+
|
126
|
+
# The list of analyzed parameters in the comments
|
127
|
+
attr_reader :params
|
128
|
+
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,7 +58,7 @@ end
|
|
56
58
|
# A helper to analyze parameter comments using the ParamWorkflow fsm
|
57
59
|
class ParamComments
|
58
60
|
def initialize
|
59
|
-
@workflow =
|
61
|
+
@workflow = ParamCommentsWorkflow.new(self)
|
60
62
|
|
61
63
|
reset
|
62
64
|
end
|
@@ -73,7 +75,7 @@ class ParamComments
|
|
73
75
|
# Walk through every comment and transition the workflow fsm accordingly
|
74
76
|
#
|
75
77
|
# @param comments A list of Comment tokens appearing before the class/defined type header
|
76
|
-
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
|
77
79
|
reset
|
78
80
|
@current_comment = PuppetLint::Lexer::Token.new(:COMMENT, '', 1, 1)
|
79
81
|
comments.each do |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
|
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 :
|
10
|
-
event :
|
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
|
-
#
|
15
|
-
event :
|
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
|
-
#
|
18
|
-
event :
|
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
|
-
|
22
|
-
event
|
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
|
-
|
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
|
@@ -255,9 +256,11 @@ describe 'param_comment' do
|
|
255
256
|
end
|
256
257
|
|
257
258
|
it 'should create a warning' do
|
258
|
-
expect(problems).to contain_warning(
|
259
|
-
|
260
|
-
|
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)
|
261
264
|
end
|
262
265
|
end
|
263
266
|
|
@@ -276,9 +279,11 @@ describe 'param_comment' do
|
|
276
279
|
end
|
277
280
|
|
278
281
|
it 'should create a warning' do
|
279
|
-
expect(problems).to contain_warning(
|
280
|
-
|
281
|
-
|
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)
|
282
287
|
end
|
283
288
|
end
|
284
289
|
|
@@ -321,9 +326,11 @@ describe 'param_comment' do
|
|
321
326
|
end
|
322
327
|
|
323
328
|
it 'should create a warning' do
|
324
|
-
expect(problems).to contain_warning(
|
325
|
-
|
326
|
-
|
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)
|
327
334
|
end
|
328
335
|
end
|
329
336
|
|
@@ -347,10 +354,10 @@ describe 'param_comment' do
|
|
347
354
|
|
348
355
|
it 'should create a warning' do
|
349
356
|
expect(problems).to contain_warning(
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
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)
|
354
361
|
end
|
355
362
|
end
|
356
363
|
|
@@ -372,10 +379,10 @@ describe 'param_comment' do
|
|
372
379
|
|
373
380
|
it 'should create a warning' do
|
374
381
|
expect(problems).to contain_warning(
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
382
|
+
'Invalid param or hash option header: @option mandatory [Boolean] :some_option An option'
|
383
|
+
)
|
384
|
+
.on_line(3)
|
385
|
+
.in_column(1)
|
379
386
|
end
|
380
387
|
end
|
381
388
|
|
@@ -401,10 +408,10 @@ describe 'param_comment' do
|
|
401
408
|
|
402
409
|
it 'should create a warning' do
|
403
410
|
expect(problems).to contain_warning(
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
411
|
+
'Can not process the comment \'@param second\' in the state awaiting_separator'
|
412
|
+
)
|
413
|
+
.on_line(5)
|
414
|
+
.in_column(1)
|
408
415
|
end
|
409
416
|
end
|
410
417
|
|
@@ -426,3 +433,4 @@ describe 'param_comment' do
|
|
426
433
|
end
|
427
434
|
end
|
428
435
|
end
|
436
|
+
# rubocop:enable Metrics/BlockLength
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dennis Ploeger
|
@@ -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
|