yard-lint 1.0.0 → 1.1.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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -0
  3. data/README.md +42 -265
  4. data/bin/yard-lint +20 -0
  5. data/lib/yard/lint/config.rb +0 -2
  6. data/lib/yard/lint/config_generator.rb +191 -0
  7. data/lib/yard/lint/validators/base.rb +36 -0
  8. data/lib/yard/lint/validators/documentation/markdown_syntax/config.rb +20 -0
  9. data/lib/yard/lint/validators/documentation/markdown_syntax/messages_builder.rb +44 -0
  10. data/lib/yard/lint/validators/documentation/markdown_syntax/parser.rb +53 -0
  11. data/lib/yard/lint/validators/documentation/markdown_syntax/result.rb +25 -0
  12. data/lib/yard/lint/validators/documentation/markdown_syntax/validator.rb +38 -0
  13. data/lib/yard/lint/validators/documentation/markdown_syntax.rb +37 -0
  14. data/lib/yard/lint/validators/documentation/undocumented_boolean_methods.rb +26 -1
  15. data/lib/yard/lint/validators/documentation/undocumented_method_arguments.rb +26 -1
  16. data/lib/yard/lint/validators/documentation/undocumented_objects.rb +131 -2
  17. data/lib/yard/lint/validators/documentation/undocumented_options/config.rb +20 -0
  18. data/lib/yard/lint/validators/documentation/undocumented_options/parser.rb +53 -0
  19. data/lib/yard/lint/validators/documentation/undocumented_options/result.rb +29 -0
  20. data/lib/yard/lint/validators/documentation/undocumented_options/validator.rb +38 -0
  21. data/lib/yard/lint/validators/documentation/undocumented_options.rb +40 -0
  22. data/lib/yard/lint/validators/semantic/abstract_methods.rb +31 -1
  23. data/lib/yard/lint/validators/tags/api_tags.rb +34 -1
  24. data/lib/yard/lint/validators/tags/collection_type/config.rb +2 -1
  25. data/lib/yard/lint/validators/tags/collection_type/messages_builder.rb +40 -11
  26. data/lib/yard/lint/validators/tags/collection_type/parser.rb +6 -5
  27. data/lib/yard/lint/validators/tags/collection_type/validator.rb +26 -7
  28. data/lib/yard/lint/validators/tags/collection_type.rb +38 -2
  29. data/lib/yard/lint/validators/tags/example_syntax/config.rb +20 -0
  30. data/lib/yard/lint/validators/tags/example_syntax/messages_builder.rb +28 -0
  31. data/lib/yard/lint/validators/tags/example_syntax/parser.rb +79 -0
  32. data/lib/yard/lint/validators/tags/example_syntax/result.rb +42 -0
  33. data/lib/yard/lint/validators/tags/example_syntax/validator.rb +88 -0
  34. data/lib/yard/lint/validators/tags/example_syntax.rb +42 -0
  35. data/lib/yard/lint/validators/tags/invalid_types/validator.rb +2 -2
  36. data/lib/yard/lint/validators/tags/invalid_types.rb +25 -1
  37. data/lib/yard/lint/validators/tags/meaningless_tag/validator.rb +2 -4
  38. data/lib/yard/lint/validators/tags/meaningless_tag.rb +31 -3
  39. data/lib/yard/lint/validators/tags/option_tags/validator.rb +7 -1
  40. data/lib/yard/lint/validators/tags/option_tags.rb +26 -1
  41. data/lib/yard/lint/validators/tags/order.rb +25 -1
  42. data/lib/yard/lint/validators/tags/redundant_param_description/config.rb +33 -0
  43. data/lib/yard/lint/validators/tags/redundant_param_description/messages_builder.rb +61 -0
  44. data/lib/yard/lint/validators/tags/redundant_param_description/parser.rb +67 -0
  45. data/lib/yard/lint/validators/tags/redundant_param_description/result.rb +25 -0
  46. data/lib/yard/lint/validators/tags/redundant_param_description/validator.rb +148 -0
  47. data/lib/yard/lint/validators/tags/redundant_param_description.rb +168 -0
  48. data/lib/yard/lint/validators/tags/tag_type_position/validator.rb +2 -4
  49. data/lib/yard/lint/validators/tags/tag_type_position.rb +39 -2
  50. data/lib/yard/lint/validators/tags/type_syntax.rb +26 -2
  51. data/lib/yard/lint/validators/warnings/duplicated_parameter_name.rb +26 -1
  52. data/lib/yard/lint/validators/warnings/invalid_directive_format.rb +26 -1
  53. data/lib/yard/lint/validators/warnings/invalid_tag_format.rb +25 -1
  54. data/lib/yard/lint/validators/warnings/unknown_directive.rb +26 -1
  55. data/lib/yard/lint/validators/warnings/unknown_parameter_name.rb +23 -1
  56. data/lib/yard/lint/validators/warnings/unknown_tag.rb +26 -1
  57. data/lib/yard/lint/version.rb +1 -1
  58. metadata +39 -1
@@ -4,7 +4,37 @@ module Yard
4
4
  module Lint
5
5
  module Validators
6
6
  module Semantic
7
- # AbstractMethods validator module
7
+ # AbstractMethods validator
8
+ #
9
+ # Ensures that methods marked with `@abstract` are actually abstract (not
10
+ # implemented). Abstract methods should either raise NotImplementedError or
11
+ # be empty stubs, not contain actual implementation logic. This validator
12
+ # is enabled by default.
13
+ #
14
+ # @example Bad - @abstract tag on implemented method
15
+ # # @abstract
16
+ # def process
17
+ # puts "This is actually implemented!"
18
+ # end
19
+ #
20
+ # @example Good - @abstract method raises NotImplementedError
21
+ # # @abstract
22
+ # def process
23
+ # raise NotImplementedError
24
+ # end
25
+ #
26
+ # @example Good - @abstract method is empty
27
+ # # @abstract
28
+ # def process
29
+ # end
30
+ #
31
+ # ## Configuration
32
+ #
33
+ # To disable this validator:
34
+ #
35
+ # Semantic/AbstractMethods:
36
+ # Enabled: false
37
+ #
8
38
  module AbstractMethods
9
39
  end
10
40
  end
@@ -4,7 +4,40 @@ module Yard
4
4
  module Lint
5
5
  module Validators
6
6
  module Tags
7
- # ApiTags validator module
7
+ # ApiTags validator
8
+ #
9
+ # Enforces that all public classes, modules, and methods have an `@api` tag
10
+ # to explicitly document their API visibility level. This validator is disabled
11
+ # by default and must be explicitly enabled.
12
+ #
13
+ # ## Configuration
14
+ #
15
+ # To enable this validator (it's disabled by default):
16
+ #
17
+ # Tags/ApiTags:
18
+ # Enabled: true
19
+ # AllowedApis:
20
+ # - public
21
+ # - private
22
+ #
23
+ # @example Good - Methods and classes have @api tags
24
+ # # @api public
25
+ # class MyClass
26
+ # # @api public
27
+ # def public_method
28
+ # end
29
+ #
30
+ # # @api private
31
+ # def internal_helper
32
+ # end
33
+ # end
34
+ #
35
+ # @example Bad - Missing @api tags
36
+ # class AnotherClass
37
+ # def some_method
38
+ # end
39
+ # end
40
+ #
8
41
  module ApiTags
9
42
  end
10
43
  end
@@ -11,7 +11,8 @@ module Yard
11
11
  self.defaults = {
12
12
  'Enabled' => true,
13
13
  'Severity' => 'convention',
14
- 'ValidatedTags' => %w[param option return yieldreturn]
14
+ 'ValidatedTags' => %w[param option return yieldreturn],
15
+ 'EnforcedStyle' => 'long' # 'long' (Hash{K => V}) or 'short' ({K => V})
15
16
  }.freeze
16
17
  end
17
18
  end
@@ -14,27 +14,56 @@ module Yard
14
14
  def call(offense)
15
15
  type_string = offense[:type_string]
16
16
  tag_name = offense[:tag_name]
17
+ detected_style = offense[:detected_style]
17
18
 
18
- # Extract the corrected version
19
- corrected = suggest_correction(type_string)
19
+ # Extract the corrected version based on detected style
20
+ corrected = suggest_correction(type_string, detected_style)
21
+ style_description = detected_style == 'short' ? 'long' : 'short'
20
22
 
21
- "Use YARD collection syntax #{corrected} instead of #{type_string} " \
22
- "in @#{tag_name} tag. YARD uses Hash{K => V} syntax for hashes."
23
+ "Use #{style_description} collection syntax #{corrected} instead of " \
24
+ "#{type_string} in @#{tag_name} tag."
23
25
  end
24
26
 
25
27
  private
26
28
 
27
- # Suggests the corrected YARD syntax
29
+ # Suggests the corrected YARD syntax based on detected style
28
30
  # @param type_string [String] the incorrect type string
31
+ # @param detected_style [String] the detected style ('short' or 'long')
29
32
  # @return [String] the suggested correction
30
- def suggest_correction(type_string)
31
- # Convert Hash<K, V> to Hash{K => V}
32
- type_string.gsub(/Hash<(.+?)>/) do
33
- types = ::Regexp.last_match(1)
34
- # Split on comma, handle nested types
35
- "Hash{#{types.sub(/,\s*/, ' => ')}}"
33
+ def suggest_correction(type_string, detected_style)
34
+ if detected_style == 'short'
35
+ # Convert short to long: Hash<K, V> -> Hash{K => V} or {K => V} -> Hash{K => V}
36
+ convert_to_long(type_string)
37
+ else
38
+ # Convert long to short: Hash{K => V} -> {K => V}
39
+ convert_to_short(type_string)
36
40
  end
37
41
  end
42
+
43
+ # Converts short syntax to long syntax
44
+ # @param type_string [String] the type string
45
+ # @return [String] the converted type string
46
+ def convert_to_long(type_string)
47
+ if type_string.start_with?('{')
48
+ # {K => V} -> Hash{K => V}
49
+ "Hash#{type_string}"
50
+ else
51
+ # Hash<K, V> -> Hash{K => V}
52
+ type_string.gsub(/Hash<(.+?)>/) do
53
+ types = ::Regexp.last_match(1)
54
+ # Split on comma, handle nested types
55
+ "Hash{#{types.sub(/,\s*/, ' => ')}}"
56
+ end
57
+ end
58
+ end
59
+
60
+ # Converts long syntax to short syntax
61
+ # @param type_string [String] the type string
62
+ # @return [String] the converted type string
63
+ def convert_to_short(type_string)
64
+ # Hash{K => V} -> {K => V}
65
+ type_string.sub(/^Hash/, '')
66
+ end
38
67
  end
39
68
  end
40
69
  end
@@ -24,18 +24,19 @@ module Yard
24
24
  location_match = location_line.match(/^(.+):(\d+): (.+)$/)
25
25
  next unless location_match
26
26
 
27
- # Parse details: "tag_name|type_string"
28
- details = details_line.split('|', 2)
29
- next unless details.size == 2
27
+ # Parse details: "tag_name|type_string|detected_style"
28
+ details = details_line.split('|', 3)
29
+ next unless details.size == 3
30
30
 
31
- tag_name, type_string = details
31
+ tag_name, type_string, detected_style = details
32
32
 
33
33
  violations << {
34
34
  location: location_match[1],
35
35
  line: location_match[2].to_i,
36
36
  object_name: location_match[3],
37
37
  tag_name: tag_name,
38
- type_string: type_string
38
+ type_string: type_string,
39
+ detected_style: detected_style
39
40
  }
40
41
  end
41
42
 
@@ -28,12 +28,14 @@ module Yard
28
28
  end
29
29
  end
30
30
 
31
- # YARD query that finds Hash<K, V> syntax in type annotations
31
+ # YARD query that finds incorrect collection syntax based on EnforcedStyle
32
32
  # Format output as two lines per violation:
33
33
  # Line 1: file.rb:LINE: ClassName#method_name
34
- # Line 2: tag_name|type_string
34
+ # Line 2: tag_name|type_string|detected_style
35
35
  # @return [String] YARD query string
36
36
  def query
37
+ style = enforced_style
38
+
37
39
  <<~QUERY.strip
38
40
  '
39
41
  docstring
@@ -43,10 +45,23 @@ module Yard
43
45
  next unless tag.types
44
46
 
45
47
  tag.types.each do |type_str|
46
- # Check for Hash<...> syntax (should be Hash{...})
48
+ detected_style = nil
49
+
50
+ # Check for Hash<...> syntax (angle brackets)
47
51
  if type_str =~ /Hash<.*>/
52
+ detected_style = "short"
53
+ # Check for Hash{...} syntax (curly braces)
54
+ elsif type_str =~ /Hash\\{.*\\}/
55
+ detected_style = "long"
56
+ # Check for {...} syntax without Hash prefix
57
+ elsif type_str =~ /^\\{.*\\}$/
58
+ detected_style = "short"
59
+ end
60
+
61
+ # Report violations based on enforced style
62
+ if detected_style && detected_style != "#{style}"
48
63
  puts object.file + ":" + object.line.to_s + ": " + object.title
49
- puts tag.tag_name + "|" + type_str
64
+ puts tag.tag_name + "|" + type_str + "|" + detected_style
50
65
  break
51
66
  end
52
67
  end
@@ -57,12 +72,16 @@ module Yard
57
72
  QUERY
58
73
  end
59
74
 
75
+ # Gets the enforced collection style from configuration
76
+ # @return [String] 'long' or 'short'
77
+ def enforced_style
78
+ config_or_default('EnforcedStyle')
79
+ end
80
+
60
81
  # Array of tag names to validate, formatted for YARD query
61
82
  # @return [String] Ruby array literal string
62
83
  def validated_tags_array
63
- tags = config.validator_config('Tags/CollectionType', 'ValidatedTags') || %w[
64
- param option return yieldreturn
65
- ]
84
+ tags = config_or_default('ValidatedTags')
66
85
  "[#{tags.map { |t| "\"#{t}\"" }.join(',')}]"
67
86
  end
68
87
  end
@@ -4,8 +4,44 @@ module Yard
4
4
  module Lint
5
5
  module Validators
6
6
  module Tags
7
- # CollectionType validator module
8
- # Detects incorrect Hash collection syntax (Hash<K, V> instead of Hash{K => V})
7
+ # CollectionType validator
8
+ #
9
+ # Enforces correct YARD collection type syntax for Hash types. YARD uses
10
+ # `Hash{K => V}` syntax with curly braces and hash rockets, not the generic
11
+ # `Hash<K, V>` syntax used in other languages and documentation tools.
12
+ # This validator is enabled by default.
13
+ #
14
+ # ## Why This Matters
15
+ #
16
+ # YARD has specific syntax conventions that differ from other documentation tools.
17
+ # Using the correct syntax ensures that YARD can properly parse and display your
18
+ # type annotations in generated documentation.
19
+ #
20
+ # @example Bad - Generic syntax with angle brackets
21
+ # # @param options [Hash<Symbol, String>] configuration options
22
+ # # @param mapping [Hash<String, Integer>] key to value mapping
23
+ # def configure(options, mapping)
24
+ # end
25
+ #
26
+ # @example Good - YARD syntax with curly braces
27
+ # # @param options [Hash{Symbol => String}] configuration options
28
+ # # @param mapping [Hash{String => Integer}] key to value mapping
29
+ # def configure(options, mapping)
30
+ # end
31
+ #
32
+ # @example Good - Arrays use angle brackets (correct for YARD)
33
+ # # @param items [Array<String>] list of items
34
+ # # @param numbers [Array<Integer>] list of numbers
35
+ # def process(items, numbers)
36
+ # end
37
+ #
38
+ # ## Configuration
39
+ #
40
+ # To disable this validator:
41
+ #
42
+ # Tags/CollectionType:
43
+ # Enabled: false
44
+ #
9
45
  module CollectionType
10
46
  end
11
47
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Tags
7
+ module ExampleSyntax
8
+ # Configuration for ExampleSyntax validator
9
+ class Config < ::Yard::Lint::Validators::Config
10
+ self.id = :example_syntax
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,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Tags
7
+ module ExampleSyntax
8
+ # Builds messages for example syntax offenses
9
+ class MessagesBuilder
10
+ class << self
11
+ # Build message for example syntax offense
12
+ # @param offense [Hash] offense data with :example_name and :error_message keys
13
+ # @return [String] formatted message
14
+ def call(offense)
15
+ example_name = offense[:example_name]
16
+ error_msg = offense[:error_message]
17
+ object_name = offense[:object_name]
18
+
19
+ "Object `#{object_name}` has syntax error in @example " \
20
+ "'#{example_name}': #{error_msg}"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Tags
7
+ module ExampleSyntax
8
+ # Parser for @example syntax validation results
9
+ class Parser < Parsers::Base
10
+ # @param yard_output [String] raw yard output with example syntax issues
11
+ # @return [Array<Hash>] array with example syntax 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
+ # Output format is variable lines per error:
19
+ # 1. file.rb:10: ClassName#method_name
20
+ # 2. syntax_error
21
+ # 3. Example name
22
+ # 4+. Error message (can be multiple lines)
23
+ # Next error starts with another file.rb:line: pattern
24
+
25
+ i = 0
26
+ while i < lines.length
27
+ location_line = lines[i]
28
+
29
+ # Parse location line: "file.rb:10: ClassName#method_name"
30
+ # File paths typically start with a letter or . or / or ~
31
+ match = location_line.match(%r{^([a-zA-Z./~].+):(\d+): (.+)$})
32
+ unless match
33
+ i += 1
34
+ next
35
+ end
36
+
37
+ file = match[1]
38
+ line = match[2].to_i
39
+ object_name = match[3]
40
+
41
+ # Next line should be status
42
+ i += 1
43
+ status_line = lines[i]
44
+ next unless status_line == 'syntax_error'
45
+
46
+ # Next line is example name
47
+ i += 1
48
+ example_name = lines[i]
49
+
50
+ # Collect all remaining lines until we hit the next location line or end
51
+ error_message_lines = []
52
+ i += 1
53
+ while i < lines.length
54
+ # Check if this line starts a new error (matches file:line: pattern)
55
+ # File paths typically start with a letter or . or / or ~
56
+ break if lines[i].match?(%r{^[a-zA-Z./~].+:\d+: .+$})
57
+
58
+ error_message_lines << lines[i]
59
+ i += 1
60
+ end
61
+
62
+ results << {
63
+ name: 'ExampleSyntax',
64
+ object_name: object_name,
65
+ example_name: example_name,
66
+ error_message: error_message_lines.join("\n"),
67
+ location: file,
68
+ line: line
69
+ }
70
+ end
71
+
72
+ results
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Tags
7
+ module ExampleSyntax
8
+ # Result object for example syntax validation
9
+ class Result < Results::Base
10
+ self.default_severity = 'warning'
11
+ self.offense_type = 'line'
12
+ self.offense_name = 'ExampleSyntaxError'
13
+
14
+ # Build human-readable message for example syntax offense
15
+ # @param offense [Hash] offense data with :example_name and :error_message keys
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
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Tags
7
+ module ExampleSyntax
8
+ # Validator to check syntax of code in @example tags
9
+ class Validator < Base
10
+ private
11
+
12
+ # Runs yard list query to find objects with invalid syntax in @example tags
13
+ # @param dir [String] dir where the yard db is (or where it should be generated)
14
+ # @param file_list_path [String] path to temp file containing file paths (one per line)
15
+ # @return [Hash] shell command execution hash results
16
+ def yard_cmd(dir, file_list_path)
17
+ cmd = <<~CMD
18
+ cat #{Shellwords.escape(file_list_path)} | xargs yard list \
19
+ --private \
20
+ --protected \
21
+ -b #{Shellwords.escape(dir)}
22
+ CMD
23
+ cmd = cmd.tr("\n", ' ')
24
+ cmd = cmd.gsub('yard list', "yard list --query #{query}")
25
+
26
+ shell(cmd)
27
+ end
28
+
29
+ # @return [String] yard query to find @example tags with syntax errors
30
+ def query
31
+ <<~QUERY
32
+ '
33
+ if object.has_tag?(:example)
34
+ example_tags = object.tags(:example)
35
+
36
+ example_tags.each_with_index do |example, index|
37
+ code = example.text
38
+ next if code.nil? || code.empty?
39
+
40
+ # Clean the code: strip output indicators (#=>) and everything after it
41
+ code_lines = code.split("\\n").map do |line|
42
+ line.sub(/\\s*#\\s*=>.*$/, "")
43
+ end
44
+
45
+ cleaned_code = code_lines.join("\\n").strip
46
+ next if cleaned_code.empty?
47
+
48
+ # Check if code looks incomplete (single expression without context)
49
+ # Skip validation for these cases
50
+ lines = cleaned_code.split("\\n").reject { |l| l.strip.empty? || l.strip.start_with?("#") }
51
+
52
+ # Skip if it is a single line that looks like an incomplete expression
53
+ if lines.size == 1
54
+ line = lines.first.strip
55
+ # Skip method calls, variable references, or simple expressions
56
+ # These are likely incomplete snippets showing usage
57
+ if line.match?(/^[a-z_][a-z0-9_]*(\\.| |$)/) || line.match?(/^[A-Z]/) && !line.match?(/^(class|module|def)\\s/)
58
+ next
59
+ end
60
+ end
61
+
62
+ # Try to parse the code
63
+ begin
64
+ RubyVM::InstructionSequence.compile(cleaned_code)
65
+ rescue SyntaxError => e
66
+ # Report syntax errors
67
+ example_name = example.name || "Example " + (index + 1).to_s
68
+ puts object.file + ":" + object.line.to_s + ": " + object.title
69
+ puts "syntax_error"
70
+ puts example_name
71
+ puts e.message
72
+ rescue => e
73
+ # Other errors (like NameError, ArgumentError) are fine
74
+ # We only check syntax, not semantics
75
+ next
76
+ end
77
+ end
78
+ end
79
+ false
80
+ '
81
+ QUERY
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ # Tags validators - validate YARD tag quality and consistency
7
+ module Tags
8
+ # ExampleSyntax validator
9
+ #
10
+ # Validates Ruby syntax in `@example` tags using RubyVM::InstructionSequence.compile().
11
+ # This validator ensures that code examples in documentation are syntactically valid.
12
+ # It automatically strips output indicators (`#=>`) and skips incomplete single-line
13
+ # snippets. This validator is enabled by default.
14
+ #
15
+ # @example Bad - Invalid Ruby syntax in example
16
+ # # @example
17
+ # # def broken(
18
+ # # # missing closing
19
+ # def my_method
20
+ # end
21
+ #
22
+ # @example Good - Valid Ruby syntax in example
23
+ # # @example
24
+ # # def my_method(name)
25
+ # # puts name
26
+ # # end
27
+ # def my_method(name)
28
+ # end
29
+ #
30
+ # ## Configuration
31
+ #
32
+ # To disable this validator:
33
+ #
34
+ # Tags/ExampleSyntax:
35
+ # Enabled: false
36
+ #
37
+ module ExampleSyntax
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -77,14 +77,14 @@ module Yard
77
77
  # @return [String] tags names for which we want to check the invalid tags
78
78
  # types definitions
79
79
  def checked_tags_names
80
- validated_tags = config.validator_config('Tags/InvalidTypes', 'ValidatedTags')
80
+ validated_tags = config_or_default('ValidatedTags')
81
81
  query_array(validated_tags)
82
82
  end
83
83
 
84
84
  # @return [String] extra names that we allow for types definitions in a yard
85
85
  # query acceptable form
86
86
  def allowed_types_code
87
- extra_types = config.validator_config('Tags/InvalidTypes', 'ExtraTypes') || []
87
+ extra_types = config_or_default('ExtraTypes')
88
88
  query_array(ALLOWED_DEFAULTS + extra_types)
89
89
  end
90
90
 
@@ -4,7 +4,31 @@ module Yard
4
4
  module Lint
5
5
  module Validators
6
6
  module Tags
7
- # InvalidTypes validator module
7
+ # InvalidTypes validator
8
+ #
9
+ # Detects invalid or malformed type annotations in YARD tags. This validator
10
+ # checks that type specifications follow YARD's type syntax rules and that
11
+ # type names are valid. This validator is enabled by default.
12
+ #
13
+ # @example Bad - Invalid type syntax
14
+ # # @param name [String | Integer] the name (wrong pipe syntax)
15
+ # # @return [Array[String]] invalid nested syntax
16
+ # def process(name)
17
+ # end
18
+ #
19
+ # @example Good - Valid type syntax
20
+ # # @param name [String, Integer] the name (comma-separated union)
21
+ # # @return [Array<String>] valid nested syntax
22
+ # def process(name)
23
+ # end
24
+ #
25
+ # ## Configuration
26
+ #
27
+ # To disable this validator:
28
+ #
29
+ # Tags/InvalidTypes:
30
+ # Enabled: false
31
+ #
8
32
  module InvalidTypes
9
33
  end
10
34
  end
@@ -67,14 +67,12 @@ module Yard
67
67
 
68
68
  # @return [Array<String>] tags that should only appear on methods
69
69
  def checked_tags
70
- config.validator_config('Tags/MeaninglessTag', 'CheckedTags') || %w[param option]
70
+ config_or_default('CheckedTags')
71
71
  end
72
72
 
73
73
  # @return [Array<String>] object types that shouldn't have method-only tags
74
74
  def invalid_object_types
75
- config.validator_config('Tags/MeaninglessTag', 'InvalidObjectTypes') || %w[
76
- class module constant
77
- ]
75
+ config_or_default('InvalidObjectTypes')
78
76
  end
79
77
  end
80
78
  end