puppet-lint-param-docs 1.5.1 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14633dfc2336826ed35662bf1840e6ef992f0032146f2a932a988a42521b2006
4
- data.tar.gz: 9f7a4139402ebe4d390f07b38ed5013e4f10b42bf3e793d8b6a4e05c170d25c6
3
+ metadata.gz: 7b7f8ef3f161f032261f4785f2ef368e89ad583295f8d1af9e25fc2daad26e15
4
+ data.tar.gz: ff99f8a6a3c9ceb061c6b8397e928ab5871fc2da91fffb0c296efe0f340a2575
5
5
  SHA512:
6
- metadata.gz: 9c685fe25b7b03c9af645f2ff82ea4c86e3c820ce3343c16b4a8926be097a0e3fa4723910a7f5c71e555978101dc61a0739f6496abcae8eea2ca4296a8a3ec14
7
- data.tar.gz: d696ad85c260c8956787f27a3af8b37a8b26526b57d789f005881ae89de538241fbaa7daca6ad03abd6e0576db71a306c1227f8b3cecb226dc4cd44d18a7927e
6
+ metadata.gz: dad82fe8054ea2433eb4bfa7d2c4a39401de66308e4c2f5027e9da3c39fbc93284e2c501b48a175469bbc3f61d1c950ee5beb5153f871084a5d3361c4d0175c9
7
+ data.tar.gz: e321066d4a8fc4661a923f0d1ab1e06e986a021462b7411c2b66eb5ab06d2087cdea4cb4ce39c16f480cf2ea8195c0bdbdc19e07272727eb0ba30130b726b4d7
data/README.md CHANGED
@@ -19,18 +19,31 @@ gem 'puppet-lint-param-docs'
19
19
 
20
20
  This plugin provides a new check to `puppet-lint`.
21
21
 
22
- ### parameter_documentation
22
+ ### parameter\_documentation
23
23
 
24
24
  **--fix support: No**
25
25
 
26
26
  This check will raise a warning for any class or defined type parameters that
27
- don't have an RDoc description.
27
+ don't have a description.
28
28
 
29
29
  ```
30
30
  WARNING: missing documentation for class parameter foo::bar
31
31
  WARNING: missing documentation for defined type parameter foo::baz
32
32
  ```
33
33
 
34
+ It will also raise warnings for parameters documented more than once.
35
+
36
+ ```
37
+ WARNING Duplicate class parameter documentation for foo::bar on line 5
38
+ WARNING Duplicate class parameter documentation for foo::bar on line 6
39
+ ```
40
+
41
+ A warning will also be raised if you document a parameter that doesn't exist in the class or defined type.
42
+
43
+ ```
44
+ WARNING No matching class parameter for documentation of foo::bar
45
+ ```
46
+
34
47
  ### Documentation styles
35
48
 
36
49
  The check will accept any of the following styles:
@@ -39,36 +52,42 @@ The check will accept any of the following styles:
39
52
 
40
53
  Used by [Puppet Strings](https://github.com/puppetlabs/puppetlabs-strings).
41
54
 
42
- # Example class
43
- #
44
- # @param foo example
45
- define example($foo) { }
55
+ ```puppet
56
+ # @summary Example class
57
+ #
58
+ # @param foo example
59
+ define example($foo) { }
60
+ ```
46
61
 
47
62
  #### Puppet Doc style
48
63
 
49
- Used by the [puppet-doc](https://docs.puppetlabs.com/puppet/latest/reference/man/doc.html)
50
- command, generally deprecated in favour of Puppet Strings.
51
-
52
- # Example class
53
- #
54
- # === Parameters:
55
- #
56
- # [*foo*] example
57
- #
58
- class example($foo) { }
64
+ Used by the [puppet-doc](https://puppet.com/docs/puppet/6.18/man/doc.html)
65
+ command, deprecated in favour of Puppet Strings.
66
+
67
+ ```puppet
68
+ # Example class
69
+ #
70
+ # === Parameters:
71
+ #
72
+ # [*foo*] example
73
+ #
74
+ class example($foo) { }
75
+ ```
59
76
 
60
77
  #### Kafo rdoc style
61
78
 
62
79
  Used in [kafo](https://github.com/theforeman/kafo#documentation) following an
63
80
  rdoc style.
64
81
 
65
- # Example class
66
- #
67
- # === Parameters:
68
- #
69
- # $foo:: example
70
- #
71
- class example($foo) { }
82
+ ```puppet
83
+ # Example class
84
+ #
85
+ # === Parameters:
86
+ #
87
+ # $foo:: example
88
+ #
89
+ class example($foo) { }
90
+ ```
72
91
 
73
92
  ### Selective rake task
74
93
 
@@ -83,7 +102,7 @@ helper to customise the lint rake task:
83
102
  config.pattern = ['manifests/init.pp', 'manifests/other/**/*.pp']
84
103
  end
85
104
 
86
- This would disable the parameter_documentation check by default, but then
105
+ This would disable the parameter\_documentation check by default, but then
87
106
  defines a new rake task (which runs after `lint`) specifically for the files
88
107
  given in `config.pattern`.
89
108
 
@@ -1,17 +1,22 @@
1
1
  PuppetLint.new_check(:parameter_documentation) do
2
2
  def check
3
3
  class_indexes.concat(defined_type_indexes).each do |idx|
4
- next if idx[:param_tokens].nil?
5
-
6
- doc_params = []
4
+ doc_params = {}
5
+ doc_params_duplicates = Hash.new { |hash, key| hash[key] = [doc_params[key]] }
7
6
  is_private = false
8
7
  tokens[0..idx[:start]].reverse_each do |dtok|
9
8
  next if [:CLASS, :DEFINE, :NEWLINE, :WHITESPACE, :INDENT].include?(dtok.type)
10
- if [:COMMENT, :MLCOMMENT, :SLASH_COMMENT].include?(dtok.type)
9
+ if dtok.type == :COMMENT
11
10
  if dtok.value =~ /\A\s*\[\*([a-zA-Z0-9_]+)\*\]/ or
12
11
  dtok.value =~ /\A\s*\$([a-zA-Z0-9_]+):: +/ or
13
12
  dtok.value =~ /\A\s*@param (?:\[.+\] )?([a-zA-Z0-9_]+)(?: +|$)/
14
- doc_params << $1
13
+ parameter = $1
14
+ parameter = 'name/title' if idx[:type] == :DEFINE && ['name','title'].include?(parameter)
15
+ if doc_params.include? parameter
16
+ doc_params_duplicates[parameter] << dtok
17
+ else
18
+ doc_params[parameter] = dtok
19
+ end
15
20
  end
16
21
 
17
22
  is_private = true if dtok.value =~ /\A\s*@api +private\s*$/
@@ -20,40 +25,76 @@ PuppetLint.new_check(:parameter_documentation) do
20
25
  end
21
26
  end
22
27
 
23
- next if is_private
24
-
25
- params = []
26
- e = idx[:param_tokens].each
27
- begin
28
- while (ptok = e.next)
29
- if ptok.type == :VARIABLE
30
- params << ptok
31
- nesting = 0
32
- # skip to the next parameter to avoid finding default values of variables
33
- while true
34
- ptok = e.next
35
- case ptok.type
36
- when :LPAREN
37
- nesting += 1
38
- when :RPAREN
39
- nesting -= 1
40
- when :COMMA
41
- break unless nesting > 0
42
- end
43
- end
44
- end
28
+ params = extract_params(idx)
29
+
30
+ # warn about duplicates
31
+ doc_params_duplicates.each do |parameter, tokens|
32
+ tokens.each do |token|
33
+ notify :warning, {
34
+ :message => "Duplicate #{type_str(idx)} parameter documentation for #{idx[:name_token].value}::#{parameter}",
35
+ :line => token.line,
36
+ :column => token.column + token.value.match(/\A\s*(@param\s*)?/)[0].length + 1 # `+ 1` is to account for length of the `#` COMMENT token.
37
+ }
45
38
  end
46
- rescue StopIteration; end
39
+ end
40
+
41
+ # warn about documentation for parameters that don't exist
42
+ doc_params.each do |parameter, token|
43
+ next if parameter == 'name/title' && idx[:type] == :DEFINE
44
+ next if params.find { |p| p.value == parameter }
47
45
 
48
- params.each do |p|
49
- next if doc_params.include? p.value
50
- idx_type = idx[:type] == :CLASS ? "class" : "defined type"
51
46
  notify :warning, {
52
- :message => "missing documentation for #{idx_type} parameter #{idx[:name_token].value}::#{p.value}",
53
- :line => p.line,
54
- :column => p.column,
47
+ :message => "No matching #{type_str(idx)} parameter for documentation of #{idx[:name_token].value}::#{parameter}",
48
+ :line => token.line,
49
+ :column => token.column + token.value.match(/\A\s*(@param\s*)?/)[0].length + 1
55
50
  }
56
51
  end
52
+
53
+ unless is_private
54
+ params.each do |p|
55
+ next if doc_params.has_key? p.value
56
+ notify :warning, {
57
+ :message => "missing documentation for #{type_str(idx)} parameter #{idx[:name_token].value}::#{p.value}",
58
+ :line => p.line,
59
+ :column => p.column,
60
+ }
61
+ end
62
+ end
57
63
  end
58
64
  end
65
+
66
+ private
67
+
68
+ def type_str(idx)
69
+ idx[:type] == :CLASS ? "class" : "defined type"
70
+ end
71
+
72
+ def extract_params(idx)
73
+ params = []
74
+ return params if idx[:param_tokens].nil?
75
+
76
+ e = idx[:param_tokens].each
77
+ begin
78
+ while (ptok = e.next)
79
+ if ptok.type == :VARIABLE
80
+ params << ptok
81
+ nesting = 0
82
+ # skip to the next parameter to avoid finding default values of variables
83
+ while true
84
+ ptok = e.next
85
+ case ptok.type
86
+ when :LPAREN
87
+ nesting += 1
88
+ when :RPAREN
89
+ nesting -= 1
90
+ when :COMMA
91
+ break unless nesting > 0
92
+ end
93
+ end
94
+ end
95
+ end
96
+ rescue StopIteration; end
97
+
98
+ params
99
+ end
59
100
  end
@@ -544,4 +544,315 @@ define foreman (
544
544
  expect(problems).to contain_warning(class_msg % :foo).on_line(7).in_column(15)
545
545
  end
546
546
  end
547
+
548
+ describe 'Duplicated documentation' do
549
+ let(:class_msg) { 'Duplicate class parameter documentation for example::%s' }
550
+ let(:define_msg) { 'Duplicate defined type parameter documentation for example::%s' }
551
+
552
+ context 'class with parameters documented twice (@param)' do
553
+ let(:code) do
554
+ <<-EOS.gsub(/^\s+/, '')
555
+ # @summary Example class
556
+ #
557
+ # @param bar
558
+ # example
559
+ # @param foo example
560
+ # @param bar Duplicate/conflicting docs
561
+ #
562
+ class example($foo, $bar) { }
563
+ EOS
564
+ end
565
+
566
+ it 'should detect two problems' do
567
+ expect(problems).to have(2).problem
568
+ end
569
+
570
+ it 'should create a warning on line 3' do
571
+ expect(problems).to contain_warning(class_msg % :bar).on_line(3).in_column(10)
572
+ end
573
+
574
+ it 'should create a warning on line 6' do
575
+ expect(problems).to contain_warning(class_msg % :bar).on_line(6).in_column(10)
576
+ end
577
+ end
578
+
579
+ context 'define with parameters documented twice (@param)' do
580
+ let(:code) do
581
+ <<-EOS.gsub(/^\s+/, '')
582
+ # @summary Example define
583
+ #
584
+ # @param bar
585
+ # example
586
+ # @param foo example
587
+ # @param bar Duplicate/conflicting docs
588
+ #
589
+ define example($foo, $bar) { }
590
+ EOS
591
+ end
592
+
593
+ it 'should detect two problems' do
594
+ expect(problems).to have(2).problem
595
+ end
596
+
597
+ it 'should create a warning on line 3' do
598
+ expect(problems).to contain_warning(define_msg % :bar).on_line(3).in_column(10)
599
+ end
600
+
601
+ it 'should create a warning on line 6' do
602
+ expect(problems).to contain_warning(define_msg % :bar).on_line(6).in_column(10)
603
+ end
604
+ end
605
+
606
+ context 'class with parameters documented 3 times (@param)' do
607
+ let(:code) do
608
+ <<-EOS.gsub(/^\s+/, '')
609
+ # @summary Example class
610
+ #
611
+ # @param bar
612
+ # example
613
+ # @param foo example
614
+ # @param bar Duplicate/conflicting docs
615
+ #
616
+ # @param bar
617
+ # example
618
+ #
619
+ class example($foo, $bar) { }
620
+ EOS
621
+ end
622
+
623
+ it 'should detect three problems' do
624
+ expect(problems).to have(3).problem
625
+ end
626
+
627
+ it 'should create a warning on line 3' do
628
+ expect(problems).to contain_warning(class_msg % :bar).on_line(3).in_column(10)
629
+ end
630
+
631
+ it 'should create a warning on line 6' do
632
+ expect(problems).to contain_warning(class_msg % :bar).on_line(6).in_column(10)
633
+ end
634
+
635
+ it 'should create a warning on line 8' do
636
+ expect(problems).to contain_warning(class_msg % :bar).on_line(8).in_column(10)
637
+ end
638
+ end
639
+
640
+ context 'private class with parameters documented twice (@param)' do
641
+ let(:code) do
642
+ <<-EOS.gsub(/^\s+/, '')
643
+ # @summary Example class
644
+ #
645
+ # @param bar docs
646
+ # @param bar Duplicate/conflicting docs
647
+ #
648
+ # @api private
649
+ class example($bar) { }
650
+ EOS
651
+ end
652
+
653
+ it 'should detect two problems' do
654
+ expect(problems).to have(2).problem
655
+ end
656
+
657
+ it 'should create a warning on line 3' do
658
+ expect(problems).to contain_warning(class_msg % :bar).on_line(3).in_column(10)
659
+ end
660
+
661
+ it 'should create a warning on line 4' do
662
+ expect(problems).to contain_warning(class_msg % :bar).on_line(4).in_column(10)
663
+ end
664
+ end
665
+
666
+ context 'class with parameters documented twice ([*bar*])' do
667
+ let(:code) do
668
+ <<-EOS.gsub(/^\s+/, '')
669
+ # @summary Example class
670
+ #
671
+ # @param bar
672
+ # example
673
+ # @param foo example
674
+ # [*bar*] Duplicate/conflicting docs
675
+ #
676
+ class example($foo, $bar) { }
677
+ EOS
678
+ end
679
+
680
+ it 'should detect two problems' do
681
+ expect(problems).to have(2).problem
682
+ end
683
+
684
+ it 'should create a warning on line 3' do
685
+ expect(problems).to contain_warning(class_msg % :bar).on_line(3).in_column(10)
686
+ end
687
+
688
+ it 'should create a warning on line 6' do
689
+ expect(problems).to contain_warning(class_msg % :bar).on_line(6).in_column(3)
690
+ end
691
+ end
692
+ end
693
+
694
+ context 'class with documentation for parameters that don\'t exist' do
695
+ let(:code) do
696
+ <<-EOS.gsub(/^\s+/, '')
697
+ # @summary Example class
698
+ #
699
+ # @param foo
700
+ class example { }
701
+ EOS
702
+ end
703
+
704
+ it 'should detect a single problem' do
705
+ expect(problems).to have(1).problem
706
+ end
707
+
708
+ it 'should create a warning on line 3' do
709
+ expect(problems).to contain_warning('No matching class parameter for documentation of example::foo').on_line(3).in_column(10)
710
+ end
711
+ end
712
+
713
+ context 'private class with documentation for parameters that don\'t exist' do
714
+ let(:code) do
715
+ <<-EOS.gsub(/^\s+/, '')
716
+ # @summary Example class
717
+ #
718
+ # @param foo
719
+ # Example docs
720
+ #
721
+ # @api private
722
+ class example { }
723
+ EOS
724
+ end
725
+
726
+ it 'should detect a single problem' do
727
+ expect(problems).to have(1).problem
728
+ end
729
+
730
+ it 'should create a warning on line 3' do
731
+ expect(problems).to contain_warning('No matching class parameter for documentation of example::foo').on_line(3).in_column(10)
732
+ end
733
+ end
734
+
735
+ context 'define with documentation for parameters that don\'t exist' do
736
+ let(:code) do
737
+ <<-EOS.gsub(/^\s+/, '')
738
+ # @summary Example define
739
+ #
740
+ # @param bar Docs for bar
741
+ # @param foo
742
+ # Docs for foo
743
+ #
744
+ # @api private
745
+ define example::example(String[1] $bar) { }
746
+ EOS
747
+ end
748
+
749
+ it 'should detect a single problem' do
750
+ expect(problems).to have(1).problem
751
+ end
752
+
753
+ it 'should create a warning on line 4' do
754
+ expect(problems).to contain_warning('No matching defined type parameter for documentation of example::example::foo').on_line(4).in_column(10)
755
+ end
756
+ end
757
+
758
+ context 'define with documentation for parameter `name`' do
759
+ let(:code) do
760
+ <<-EOS.gsub(/^\s+/, '')
761
+ # @summary Example define
762
+ #
763
+ # @param name
764
+ # Docs for the $name
765
+ # @param bar Docs for bar
766
+ define example::example(String[1] $bar) { }
767
+ EOS
768
+ end
769
+
770
+ it 'should not detect any problems' do
771
+ expect(problems).to have(0).problems
772
+ end
773
+ end
774
+
775
+ context 'class with documentation for parameter `name`' do
776
+ let(:code) do
777
+ <<-EOS.gsub(/^\s+/, '')
778
+ # @summary Example class
779
+ #
780
+ # @param name
781
+ # Invalid docs
782
+ class example { }
783
+ EOS
784
+ end
785
+
786
+ it 'should detect a single problem' do
787
+ expect(problems).to have(1).problem
788
+ end
789
+
790
+ it 'should create a warning on line 3' do
791
+ expect(problems).to contain_warning('No matching class parameter for documentation of example::name').on_line(3).in_column(10)
792
+ end
793
+ end
794
+
795
+ context 'define with documentation for parameter `title`' do
796
+ let(:code) do
797
+ <<-EOS.gsub(/^\s+/, '')
798
+ # @summary Example define
799
+ #
800
+ # @param title
801
+ # Docs for the $title
802
+ # @param bar Docs for bar
803
+ define example::example(String[1] $bar) { }
804
+ EOS
805
+ end
806
+
807
+ it 'should not detect any problems' do
808
+ expect(problems).to have(0).problems
809
+ end
810
+ end
811
+
812
+ context 'class with documentation for parameter `title`' do
813
+ let(:code) do
814
+ <<-EOS.gsub(/^\s+/, '')
815
+ # @summary Example class
816
+ #
817
+ # @param title
818
+ # Invalid docs
819
+ class example { }
820
+ EOS
821
+ end
822
+
823
+ it 'should detect a single problem' do
824
+ expect(problems).to have(1).problem
825
+ end
826
+
827
+ it 'should create a warning on line 3' do
828
+ expect(problems).to contain_warning('No matching class parameter for documentation of example::title').on_line(3).in_column(10)
829
+ end
830
+ end
831
+
832
+ context 'define with documentation for both `title` and `name`' do
833
+ let(:code) do
834
+ <<-EOS.gsub(/^\s+/, '')
835
+ # @summary Example define
836
+ #
837
+ # @param title
838
+ # Docs for the $title
839
+ # @param name
840
+ # Docs for the $name
841
+ # @param bar Docs for bar
842
+ define example(String[1] $bar) { }
843
+ EOS
844
+ end
845
+
846
+ it 'should detect two problems' do
847
+ expect(problems).to have(2).problems
848
+ end
849
+
850
+ it 'should create a warning on line 3' do
851
+ expect(problems).to contain_warning('Duplicate defined type parameter documentation for example::name/title').on_line(3).in_column(10)
852
+ end
853
+
854
+ it 'should create a warning on line 5' do
855
+ expect(problems).to contain_warning('Duplicate defined type parameter documentation for example::name/title').on_line(5).in_column(10)
856
+ end
857
+ end
547
858
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppet-lint-param-docs
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.1
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vox Pupuli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-23 00:00:00.000000000 Z
11
+ date: 2020-10-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: puppet-lint
@@ -132,8 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
132
  - !ruby/object:Gem::Version
133
133
  version: '0'
134
134
  requirements: []
135
- rubyforge_project:
136
- rubygems_version: 2.7.7
135
+ rubygems_version: 3.0.8
137
136
  signing_key:
138
137
  specification_version: 4
139
138
  summary: puppet-lint check to validate all parameters are documented