yard-lint 0.2.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.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.coditsu/ci.yml +3 -0
  3. data/CHANGELOG.md +28 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +454 -0
  6. data/bin/console +11 -0
  7. data/bin/setup +8 -0
  8. data/bin/yard-lint +109 -0
  9. data/lib/yard/lint/command_cache.rb +77 -0
  10. data/lib/yard/lint/config.rb +255 -0
  11. data/lib/yard/lint/config_loader.rb +198 -0
  12. data/lib/yard/lint/errors.rb +17 -0
  13. data/lib/yard/lint/formatters/progress.rb +50 -0
  14. data/lib/yard/lint/parsers/base.rb +23 -0
  15. data/lib/yard/lint/parsers/one_line_base.rb +35 -0
  16. data/lib/yard/lint/parsers/two_line_base.rb +45 -0
  17. data/lib/yard/lint/result_builder.rb +130 -0
  18. data/lib/yard/lint/results/aggregate.rb +86 -0
  19. data/lib/yard/lint/results/base.rb +156 -0
  20. data/lib/yard/lint/runner.rb +125 -0
  21. data/lib/yard/lint/validators/base.rb +120 -0
  22. data/lib/yard/lint/validators/config.rb +30 -0
  23. data/lib/yard/lint/validators/documentation/undocumented_boolean_methods/config.rb +20 -0
  24. data/lib/yard/lint/validators/documentation/undocumented_boolean_methods/parser.rb +43 -0
  25. data/lib/yard/lint/validators/documentation/undocumented_boolean_methods/result.rb +26 -0
  26. data/lib/yard/lint/validators/documentation/undocumented_boolean_methods/validator.rb +48 -0
  27. data/lib/yard/lint/validators/documentation/undocumented_boolean_methods.rb +13 -0
  28. data/lib/yard/lint/validators/documentation/undocumented_method_arguments/config.rb +20 -0
  29. data/lib/yard/lint/validators/documentation/undocumented_method_arguments/messages_builder.rb +24 -0
  30. data/lib/yard/lint/validators/documentation/undocumented_method_arguments/parser.rb +45 -0
  31. data/lib/yard/lint/validators/documentation/undocumented_method_arguments/result.rb +25 -0
  32. data/lib/yard/lint/validators/documentation/undocumented_method_arguments/validator.rb +55 -0
  33. data/lib/yard/lint/validators/documentation/undocumented_method_arguments.rb +13 -0
  34. data/lib/yard/lint/validators/documentation/undocumented_objects/config.rb +21 -0
  35. data/lib/yard/lint/validators/documentation/undocumented_objects/messages_builder.rb +23 -0
  36. data/lib/yard/lint/validators/documentation/undocumented_objects/parser.rb +39 -0
  37. data/lib/yard/lint/validators/documentation/undocumented_objects/result.rb +25 -0
  38. data/lib/yard/lint/validators/documentation/undocumented_objects/validator.rb +39 -0
  39. data/lib/yard/lint/validators/documentation/undocumented_objects.rb +14 -0
  40. data/lib/yard/lint/validators/semantic/abstract_methods/config.rb +24 -0
  41. data/lib/yard/lint/validators/semantic/abstract_methods/messages_builder.rb +25 -0
  42. data/lib/yard/lint/validators/semantic/abstract_methods/parser.rb +45 -0
  43. data/lib/yard/lint/validators/semantic/abstract_methods/result.rb +42 -0
  44. data/lib/yard/lint/validators/semantic/abstract_methods/validator.rb +65 -0
  45. data/lib/yard/lint/validators/semantic/abstract_methods.rb +13 -0
  46. data/lib/yard/lint/validators/tags/api_tags/config.rb +21 -0
  47. data/lib/yard/lint/validators/tags/api_tags/messages_builder.rb +29 -0
  48. data/lib/yard/lint/validators/tags/api_tags/parser.rb +50 -0
  49. data/lib/yard/lint/validators/tags/api_tags/result.rb +42 -0
  50. data/lib/yard/lint/validators/tags/api_tags/validator.rb +69 -0
  51. data/lib/yard/lint/validators/tags/api_tags.rb +13 -0
  52. data/lib/yard/lint/validators/tags/invalid_types/config.rb +22 -0
  53. data/lib/yard/lint/validators/tags/invalid_types/messages_builder.rb +24 -0
  54. data/lib/yard/lint/validators/tags/invalid_types/parser.rb +16 -0
  55. data/lib/yard/lint/validators/tags/invalid_types/result.rb +25 -0
  56. data/lib/yard/lint/validators/tags/invalid_types/validator.rb +106 -0
  57. data/lib/yard/lint/validators/tags/invalid_types.rb +13 -0
  58. data/lib/yard/lint/validators/tags/option_tags/config.rb +21 -0
  59. data/lib/yard/lint/validators/tags/option_tags/messages_builder.rb +24 -0
  60. data/lib/yard/lint/validators/tags/option_tags/parser.rb +45 -0
  61. data/lib/yard/lint/validators/tags/option_tags/result.rb +42 -0
  62. data/lib/yard/lint/validators/tags/option_tags/validator.rb +61 -0
  63. data/lib/yard/lint/validators/tags/option_tags.rb +13 -0
  64. data/lib/yard/lint/validators/tags/order/config.rb +33 -0
  65. data/lib/yard/lint/validators/tags/order/messages_builder.rb +30 -0
  66. data/lib/yard/lint/validators/tags/order/parser.rb +66 -0
  67. data/lib/yard/lint/validators/tags/order/result.rb +26 -0
  68. data/lib/yard/lint/validators/tags/order/validator.rb +89 -0
  69. data/lib/yard/lint/validators/tags/order.rb +13 -0
  70. data/lib/yard/lint/validators/warnings/duplicated_parameter_name/config.rb +22 -0
  71. data/lib/yard/lint/validators/warnings/duplicated_parameter_name/parser.rb +22 -0
  72. data/lib/yard/lint/validators/warnings/duplicated_parameter_name/result.rb +25 -0
  73. data/lib/yard/lint/validators/warnings/duplicated_parameter_name/validator.rb +33 -0
  74. data/lib/yard/lint/validators/warnings/duplicated_parameter_name.rb +14 -0
  75. data/lib/yard/lint/validators/warnings/invalid_directive_format/config.rb +22 -0
  76. data/lib/yard/lint/validators/warnings/invalid_directive_format/parser.rb +22 -0
  77. data/lib/yard/lint/validators/warnings/invalid_directive_format/result.rb +25 -0
  78. data/lib/yard/lint/validators/warnings/invalid_directive_format/validator.rb +33 -0
  79. data/lib/yard/lint/validators/warnings/invalid_directive_format.rb +14 -0
  80. data/lib/yard/lint/validators/warnings/invalid_tag_format/config.rb +22 -0
  81. data/lib/yard/lint/validators/warnings/invalid_tag_format/parser.rb +22 -0
  82. data/lib/yard/lint/validators/warnings/invalid_tag_format/result.rb +25 -0
  83. data/lib/yard/lint/validators/warnings/invalid_tag_format/validator.rb +33 -0
  84. data/lib/yard/lint/validators/warnings/invalid_tag_format.rb +14 -0
  85. data/lib/yard/lint/validators/warnings/unknown_directive/config.rb +22 -0
  86. data/lib/yard/lint/validators/warnings/unknown_directive/parser.rb +22 -0
  87. data/lib/yard/lint/validators/warnings/unknown_directive/result.rb +25 -0
  88. data/lib/yard/lint/validators/warnings/unknown_directive/validator.rb +33 -0
  89. data/lib/yard/lint/validators/warnings/unknown_directive.rb +14 -0
  90. data/lib/yard/lint/validators/warnings/unknown_parameter_name/config.rb +22 -0
  91. data/lib/yard/lint/validators/warnings/unknown_parameter_name/parser.rb +22 -0
  92. data/lib/yard/lint/validators/warnings/unknown_parameter_name/result.rb +25 -0
  93. data/lib/yard/lint/validators/warnings/unknown_parameter_name/validator.rb +33 -0
  94. data/lib/yard/lint/validators/warnings/unknown_parameter_name.rb +14 -0
  95. data/lib/yard/lint/validators/warnings/unknown_tag/config.rb +22 -0
  96. data/lib/yard/lint/validators/warnings/unknown_tag/parser.rb +24 -0
  97. data/lib/yard/lint/validators/warnings/unknown_tag/result.rb +25 -0
  98. data/lib/yard/lint/validators/warnings/unknown_tag/validator.rb +33 -0
  99. data/lib/yard/lint/validators/warnings/unknown_tag.rb +14 -0
  100. data/lib/yard/lint/version.rb +8 -0
  101. data/lib/yard/lint.rb +76 -0
  102. data/lib/yard-lint.rb +11 -0
  103. data/renovate.json +22 -0
  104. metadata +178 -0
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ module UndocumentedBooleanMethods
8
+ # Configuration for UndocumentedBooleanMethods validator
9
+ class Config < ::Yard::Lint::Validators::Config
10
+ self.id = :undocumented_boolean_methods
11
+ self.defaults = {
12
+ 'Enabled' => true,
13
+ 'Severity' => 'warning'
14
+ }.freeze
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ # Documentation validators - check for missing or incomplete documentation
7
+ module Documentation
8
+ module UndocumentedBooleanMethods
9
+ # Class used to extract details about undocumented boolean methods
10
+ # @example
11
+ # Platform::Analysis::Authors#valid?
12
+ class Parser < Parsers::Base
13
+ # Regex to extract location and method name from yard list output
14
+ LOCATION_REGEX = /^(.+)#(.+)$|^(.+)\.(.+)$/
15
+
16
+ # @param yard_list [String] raw yard list results string
17
+ # @return [Array<Hash>] Array with undocumented boolean methods details
18
+ def call(yard_list)
19
+ yard_list
20
+ .split("\n")
21
+ .reject(&:empty?)
22
+ .filter_map do |line|
23
+ match_data = line.match(LOCATION_REGEX)
24
+ next unless match_data
25
+
26
+ # Handle both instance (#) and class (.) methods
27
+ location = match_data[1] || match_data[3]
28
+ method_name = match_data[2] || match_data[4]
29
+
30
+ {
31
+ location: location,
32
+ element: "#{location}##{method_name}",
33
+ method_name: method_name,
34
+ line: 0 # YARD list doesn't provide line numbers
35
+ }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ module UndocumentedBooleanMethods
8
+ # Result object for undocumented boolean methods validation
9
+ # Reuses UndocumentedObjects::MessagesBuilder
10
+ class Result < Results::Base
11
+ self.default_severity = 'warning'
12
+ self.offense_type = 'line'
13
+ self.offense_name = 'UndocumentedObject'
14
+
15
+ # Build human-readable message for undocumented boolean method offense
16
+ # @param offense [Hash] offense data
17
+ # @return [String] formatted message
18
+ def build_message(offense)
19
+ UndocumentedObjects::MessagesBuilder.call(offense)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ module UndocumentedBooleanMethods
8
+ # Runs a query that will pick all the boolean methods (ending with ?) that
9
+ # do not have a return type or return description documented
10
+ class Validator < Base
11
+ # Query to find all the boolean methods without proper return documentation
12
+ QUERY = <<~QUERY.tr("\n", ' ')
13
+ '
14
+ type == :method &&
15
+ !is_alias? &&
16
+ is_explicit? &&
17
+ name.to_s.end_with?("?") &&
18
+ (tag("return").nil? || tag("return").text.to_s.strip.empty?)
19
+ '
20
+ QUERY
21
+
22
+ private_constant :QUERY
23
+
24
+ private
25
+
26
+ # Runs yard list query with proper settings on a given dir and files
27
+ # @param dir [String] dir where we should generate the temp docs
28
+ # @param escaped_file_names [String] files for which we want to get the stats
29
+ # @return [Hash] shell command execution hash results
30
+ def yard_cmd(dir, escaped_file_names)
31
+ cmd = <<~CMD
32
+ yard list \
33
+ #{shell_arguments} \
34
+ --query #{QUERY} \
35
+ -q \
36
+ -b #{Shellwords.escape(dir)} \
37
+ #{escaped_file_names}
38
+ CMD
39
+ cmd = cmd.tr("\n", ' ')
40
+
41
+ shell(cmd)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ # UndocumentedBooleanMethods validator module
8
+ module UndocumentedBooleanMethods
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ module UndocumentedMethodArguments
8
+ # Configuration for UndocumentedMethodArguments validator
9
+ class Config < ::Yard::Lint::Validators::Config
10
+ self.id = :undocumented_method_arguments
11
+ self.defaults = {
12
+ 'Enabled' => true,
13
+ 'Severity' => 'warning'
14
+ }.freeze
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ module UndocumentedMethodArguments
8
+ # Builds messages for undocumented method arguments offenses
9
+ class MessagesBuilder
10
+ class << self
11
+ # Build message for undocumented method arguments
12
+ # @param offense [Hash] offense data with :method_name key
13
+ # @return [String] formatted message
14
+ def call(offense)
15
+ "The `#{offense[:method_name]}` method is missing documentation " \
16
+ 'for some of the arguments.'
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ module UndocumentedMethodArguments
8
+ # Class used to extract details about methods with undocumented arguments
9
+ # @example
10
+ # /path/to/file.rb:10: Platform::Analysis::Authors#initialize
11
+ class Parser < Parsers::Base
12
+ # Regex to extract file, line, and method name from yard list output
13
+ # Format: /path/to/file.rb:10: ClassName#method_name
14
+ LOCATION_REGEX = /^(.+):(\d+):\s+(.+)[#.](.+)$/
15
+
16
+ # @param yard_list [String] raw yard list results string
17
+ # @return [Array<Hash>] Array with undocumented method arguments details
18
+ def call(yard_list)
19
+ yard_list
20
+ .split("\n")
21
+ .reject(&:empty?)
22
+ .filter_map do |line|
23
+ match_data = line.match(LOCATION_REGEX)
24
+ next unless match_data
25
+
26
+ # Extract: file path, line number, class name, method name
27
+ file_path = match_data[1]
28
+ line_number = match_data[2].to_i
29
+ class_name = match_data[3]
30
+ method_name = match_data[4]
31
+
32
+ {
33
+ location: file_path,
34
+ method_name: method_name,
35
+ line: line_number,
36
+ class_name: class_name
37
+ }
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ module UndocumentedMethodArguments
8
+ # Result object for undocumented method arguments validation
9
+ class Result < Results::Base
10
+ self.default_severity = 'warning'
11
+ self.offense_type = 'method'
12
+ self.offense_name = 'UndocumentedMethodArgument'
13
+
14
+ # Build human-readable message for undocumented method argument offense
15
+ # @param offense [Hash] offense data
16
+ # @return [String] formatted message
17
+ def build_message(offense)
18
+ MessagesBuilder.call(offense)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ module UndocumentedMethodArguments
8
+ # Runs yard list to check for missing args docs on methods that were documented
9
+ class Validator < Base
10
+ # Options that stats supports but not list
11
+ UNWANTED_OPTIONS = %w[
12
+ --list-undoc
13
+ ].freeze
14
+
15
+ # Query to find all the documented methods that have some undocumented
16
+ # arguments
17
+ QUERY = <<~QUERY.tr("\n", ' ')
18
+ '
19
+ type == :method &&
20
+ !is_alias? &&
21
+ is_explicit? &&
22
+ (parameters.size > @@param.size)
23
+ '
24
+ QUERY
25
+
26
+ private_constant :UNWANTED_OPTIONS, :QUERY
27
+
28
+ private
29
+
30
+ # Runs yard list query with proper settings on a given dir and files
31
+ # @param dir [String] dir where we should generate the temp docs
32
+ # @param escaped_file_names [String] files for which we want to get the stats
33
+ # @return [Hash] shell command execution hash results
34
+ def yard_cmd(dir, escaped_file_names)
35
+ shell_args = shell_arguments
36
+ UNWANTED_OPTIONS.each { |opt| shell_args.gsub!(opt, '') }
37
+
38
+ cmd = <<~CMD
39
+ yard list \
40
+ #{shell_args} \
41
+ --query #{QUERY} \
42
+ -q \
43
+ -b #{Shellwords.escape(dir)} \
44
+ #{escaped_file_names}
45
+ CMD
46
+ cmd = cmd.tr("\n", ' ')
47
+
48
+ shell(cmd)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ # UndocumentedMethodArguments validator module
8
+ module UndocumentedMethodArguments
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ module UndocumentedObjects
8
+ # Configuration for UndocumentedObjects validator
9
+ class Config < ::Yard::Lint::Validators::Config
10
+ self.id = :undocumented_objects
11
+ self.defaults = {
12
+ 'Enabled' => true,
13
+ 'Severity' => 'warning'
14
+ }.freeze
15
+ self.combines_with = ['Documentation/UndocumentedBooleanMethods'].freeze
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ module UndocumentedObjects
8
+ # Builds messages for undocumented objects offenses
9
+ class MessagesBuilder
10
+ class << self
11
+ # Build message for an undocumented object
12
+ # @param offense [Hash] offense data with :element key
13
+ # @return [String] formatted message
14
+ def call(offense)
15
+ "Documentation required for `#{offense[:element]}`"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ module UndocumentedObjects
8
+ # Class used to extract details about undocumented objects from raw yard list output
9
+ # @example
10
+ # /path/to/file.rb:3: UndocumentedClass
11
+ # /path/to/file.rb:4: UndocumentedClass#method_one
12
+ class Parser < ::Yard::Lint::Parsers::Base
13
+ # Regex used to parse yard list output format: file.rb:LINE: ObjectName
14
+ LINE_REGEX = /^(.+):(\d+): (.+)$/
15
+
16
+ # @param yard_list_output [String] raw yard list results string
17
+ # @return [Array<Hash>] Array with undocumented objects details
18
+ def call(yard_list_output)
19
+ yard_list_output
20
+ .split("\n")
21
+ .map(&:strip)
22
+ .reject(&:empty?)
23
+ .filter_map do |line|
24
+ match = line.match(LINE_REGEX)
25
+ next unless match
26
+
27
+ {
28
+ location: match[1],
29
+ line: match[2].to_i,
30
+ element: match[3]
31
+ }
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ module UndocumentedObjects
8
+ # Result object for undocumented objects validation
9
+ class Result < Results::Base
10
+ self.default_severity = 'warning'
11
+ self.offense_type = 'line'
12
+ self.offense_name = 'UndocumentedObject'
13
+
14
+ # Build human-readable message for undocumented object offense
15
+ # @param offense [Hash] offense data
16
+ # @return [String] formatted message
17
+ def build_message(offense)
18
+ MessagesBuilder.call(offense)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ module UndocumentedObjects
8
+ # Runs yard list to check for undocumented objects
9
+ class Validator < Base
10
+ # Query to find all objects without documentation
11
+ QUERY = "'docstring.blank?'"
12
+
13
+ private_constant :QUERY
14
+
15
+ private
16
+
17
+ # Runs yard list query with proper settings on a given dir and files
18
+ # @param dir [String] dir where we should generate the temp docs
19
+ # @param escaped_file_names [String] files for which we want to get the stats
20
+ # @return [Hash] shell command execution hash results
21
+ def yard_cmd(dir, escaped_file_names)
22
+ cmd = <<~CMD
23
+ yard list \
24
+ #{shell_arguments} \
25
+ --query #{QUERY} \
26
+ -q \
27
+ -b #{Shellwords.escape(dir)} \
28
+ #{escaped_file_names}
29
+ CMD
30
+ cmd = cmd.tr("\n", ' ')
31
+
32
+ shell(cmd)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Documentation
7
+ # UndocumentedObjects validator module
8
+ # This validator checks for missing documentation on objects
9
+ module UndocumentedObjects
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Semantic
7
+ module AbstractMethods
8
+ # Configuration for AbstractMethods validator
9
+ class Config < ::Yard::Lint::Validators::Config
10
+ self.id = :abstract_methods
11
+ self.defaults = {
12
+ 'Enabled' => true,
13
+ 'Severity' => 'warning',
14
+ 'AllowedImplementations' => [
15
+ 'raise NotImplementedError',
16
+ 'raise NotImplementedError, ".+"'
17
+ ]
18
+ }.freeze
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ # Semantic validators - check code semantics and implementation correctness
7
+ module Semantic
8
+ module AbstractMethods
9
+ # Builds messages for abstract method offenses
10
+ class MessagesBuilder
11
+ class << self
12
+ # Build message for abstract method offense
13
+ # @param offense [Hash] offense data with :method_name key
14
+ # @return [String] formatted message
15
+ def call(offense)
16
+ "Abstract method `#{offense[:method_name]}` has implementation " \
17
+ '(should only raise NotImplementedError or be empty)'
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Semantic
7
+ module AbstractMethods
8
+ # Parser for @abstract method validation results
9
+ class Parser < Parsers::Base
10
+ # @param yard_output [String] raw yard output with abstract method issues
11
+ # @return [Array<Hash>] array with abstract method violation details
12
+ def call(yard_output)
13
+ return [] if yard_output.nil? || yard_output.empty?
14
+
15
+ lines = yard_output.split("\n").reject(&:empty?)
16
+ results = []
17
+
18
+ lines.each_slice(2) do |location_line, status_line|
19
+ next unless location_line && status_line
20
+ next unless status_line == 'has_implementation'
21
+
22
+ # Parse location line: "file.rb:10: ClassName#method_name"
23
+ match = location_line.match(/^(.+):(\d+): (.+)$/)
24
+ next unless match
25
+
26
+ file = match[1]
27
+ line = match[2].to_i
28
+ method_name = match[3]
29
+
30
+ results << {
31
+ name: 'AbstractMethod',
32
+ method_name: method_name,
33
+ location: file,
34
+ line: line
35
+ }
36
+ end
37
+
38
+ results
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Semantic
7
+ module AbstractMethods
8
+ # Result object for abstract methods validation
9
+ class Result < Results::Base
10
+ self.default_severity = 'warning'
11
+ self.offense_type = 'method'
12
+ self.offense_name = 'AbstractMethodViolation'
13
+
14
+ # Build human-readable message for abstract method offense
15
+ # @param offense [Hash] offense data with :name key
16
+ # @return [String] formatted message
17
+ def build_message(offense)
18
+ MessagesBuilder.call(offense)
19
+ end
20
+
21
+ private
22
+
23
+ # Override to build offenses with dynamic names from parsed data
24
+ # @return [Array<Hash>] array of offense hashes
25
+ def build_offenses
26
+ @parsed_data.map do |offense_data|
27
+ {
28
+ severity: configured_severity,
29
+ type: self.class.offense_type,
30
+ name: offense_data[:name] || self.class.offense_name,
31
+ message: build_message(offense_data),
32
+ location: offense_data[:location] || offense_data[:file],
33
+ location_line: offense_data[:line] || offense_data[:location_line] || 0
34
+ }
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end