puppet-lint-param-docs 1.5.1 → 1.6.0

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: 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