yard-lint 1.2.3 → 1.3.0.rc1

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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +150 -1
  3. data/README.md +98 -4
  4. data/Rakefile +20 -0
  5. data/bin/yard-lint +71 -38
  6. data/lib/yard/lint/config.rb +5 -0
  7. data/lib/yard/lint/config_updater.rb +222 -0
  8. data/lib/yard/lint/errors.rb +6 -0
  9. data/lib/yard/lint/executor/in_process_registry.rb +130 -0
  10. data/lib/yard/lint/executor/query_executor.rb +109 -0
  11. data/lib/yard/lint/executor/result_collector.rb +55 -0
  12. data/lib/yard/lint/executor/warning_dispatcher.rb +79 -0
  13. data/lib/yard/lint/results/base.rb +2 -1
  14. data/lib/yard/lint/runner.rb +50 -38
  15. data/lib/yard/lint/templates/default_config.yml +105 -0
  16. data/lib/yard/lint/templates/strict_config.yml +105 -0
  17. data/lib/yard/lint/validators/base.rb +52 -118
  18. data/lib/yard/lint/validators/documentation/blank_line_before_definition/config.rb +25 -0
  19. data/lib/yard/lint/validators/documentation/blank_line_before_definition/messages_builder.rb +39 -0
  20. data/lib/yard/lint/validators/documentation/blank_line_before_definition/parser.rb +59 -0
  21. data/lib/yard/lint/validators/documentation/blank_line_before_definition/result.rb +61 -0
  22. data/lib/yard/lint/validators/documentation/blank_line_before_definition/validator.rb +94 -0
  23. data/lib/yard/lint/validators/documentation/blank_line_before_definition.rb +63 -0
  24. data/lib/yard/lint/validators/documentation/empty_comment_line/config.rb +24 -0
  25. data/lib/yard/lint/validators/documentation/empty_comment_line/messages_builder.rb +34 -0
  26. data/lib/yard/lint/validators/documentation/empty_comment_line/parser.rb +60 -0
  27. data/lib/yard/lint/validators/documentation/empty_comment_line/result.rb +25 -0
  28. data/lib/yard/lint/validators/documentation/empty_comment_line/validator.rb +109 -0
  29. data/lib/yard/lint/validators/documentation/empty_comment_line.rb +58 -0
  30. data/lib/yard/lint/validators/documentation/markdown_syntax/validator.rb +36 -21
  31. data/lib/yard/lint/validators/documentation/markdown_syntax.rb +0 -1
  32. data/lib/yard/lint/validators/documentation/undocumented_boolean_methods/validator.rb +19 -29
  33. data/lib/yard/lint/validators/documentation/undocumented_boolean_methods.rb +0 -1
  34. data/lib/yard/lint/validators/documentation/undocumented_method_arguments/validator.rb +18 -34
  35. data/lib/yard/lint/validators/documentation/undocumented_method_arguments.rb +0 -1
  36. data/lib/yard/lint/validators/documentation/undocumented_objects/validator.rb +17 -25
  37. data/lib/yard/lint/validators/documentation/undocumented_objects.rb +4 -5
  38. data/lib/yard/lint/validators/documentation/undocumented_options/validator.rb +30 -21
  39. data/lib/yard/lint/validators/documentation/undocumented_options.rb +0 -1
  40. data/lib/yard/lint/validators/semantic/abstract_methods/result.rb +2 -2
  41. data/lib/yard/lint/validators/semantic/abstract_methods/validator.rb +31 -43
  42. data/lib/yard/lint/validators/semantic/abstract_methods.rb +0 -1
  43. data/lib/yard/lint/validators/tags/api_tags/validator.rb +24 -39
  44. data/lib/yard/lint/validators/tags/api_tags.rb +0 -1
  45. data/lib/yard/lint/validators/tags/collection_type/validator.rb +37 -66
  46. data/lib/yard/lint/validators/tags/collection_type.rb +0 -1
  47. data/lib/yard/lint/validators/tags/example_syntax/validator.rb +51 -64
  48. data/lib/yard/lint/validators/tags/example_syntax.rb +0 -1
  49. data/lib/yard/lint/validators/tags/informal_notation/config.rb +40 -0
  50. data/lib/yard/lint/validators/tags/informal_notation/messages_builder.rb +35 -0
  51. data/lib/yard/lint/validators/tags/informal_notation/parser.rb +55 -0
  52. data/lib/yard/lint/validators/tags/informal_notation/result.rb +26 -0
  53. data/lib/yard/lint/validators/tags/informal_notation/validator.rb +133 -0
  54. data/lib/yard/lint/validators/tags/informal_notation.rb +45 -0
  55. data/lib/yard/lint/validators/tags/invalid_types/validator.rb +57 -70
  56. data/lib/yard/lint/validators/tags/invalid_types.rb +0 -1
  57. data/lib/yard/lint/validators/tags/meaningless_tag/validator.rb +22 -54
  58. data/lib/yard/lint/validators/tags/meaningless_tag.rb +0 -1
  59. data/lib/yard/lint/validators/tags/non_ascii_type/config.rb +21 -0
  60. data/lib/yard/lint/validators/tags/non_ascii_type/messages_builder.rb +29 -0
  61. data/lib/yard/lint/validators/tags/non_ascii_type/parser.rb +59 -0
  62. data/lib/yard/lint/validators/tags/non_ascii_type/result.rb +25 -0
  63. data/lib/yard/lint/validators/tags/non_ascii_type/validator.rb +50 -0
  64. data/lib/yard/lint/validators/tags/non_ascii_type.rb +39 -0
  65. data/lib/yard/lint/validators/tags/option_tags/result.rb +2 -2
  66. data/lib/yard/lint/validators/tags/option_tags/validator.rb +25 -40
  67. data/lib/yard/lint/validators/tags/option_tags.rb +0 -1
  68. data/lib/yard/lint/validators/tags/order/validator.rb +28 -55
  69. data/lib/yard/lint/validators/tags/order.rb +0 -1
  70. data/lib/yard/lint/validators/tags/redundant_param_description/config.rb +15 -1
  71. data/lib/yard/lint/validators/tags/redundant_param_description/messages_builder.rb +5 -0
  72. data/lib/yard/lint/validators/tags/redundant_param_description/validator.rb +134 -100
  73. data/lib/yard/lint/validators/tags/redundant_param_description.rb +0 -1
  74. data/lib/yard/lint/validators/tags/tag_group_separator/config.rb +29 -0
  75. data/lib/yard/lint/validators/tags/tag_group_separator/messages_builder.rb +49 -0
  76. data/lib/yard/lint/validators/tags/tag_group_separator/parser.rb +67 -0
  77. data/lib/yard/lint/validators/tags/tag_group_separator/result.rb +28 -0
  78. data/lib/yard/lint/validators/tags/tag_group_separator/validator.rb +117 -0
  79. data/lib/yard/lint/validators/tags/tag_group_separator.rb +49 -0
  80. data/lib/yard/lint/validators/tags/tag_type_position/validator.rb +53 -84
  81. data/lib/yard/lint/validators/tags/tag_type_position.rb +0 -1
  82. data/lib/yard/lint/validators/tags/type_syntax/parser.rb +7 -2
  83. data/lib/yard/lint/validators/tags/type_syntax/validator.rb +29 -59
  84. data/lib/yard/lint/validators/tags/type_syntax.rb +0 -1
  85. data/lib/yard/lint/validators/warnings/duplicated_parameter_name/validator.rb +1 -18
  86. data/lib/yard/lint/validators/warnings/invalid_directive_format/validator.rb +1 -18
  87. data/lib/yard/lint/validators/warnings/invalid_tag_format/validator.rb +1 -18
  88. data/lib/yard/lint/validators/warnings/unknown_directive/validator.rb +1 -18
  89. data/lib/yard/lint/validators/warnings/unknown_parameter_name/messages_builder.rb +243 -0
  90. data/lib/yard/lint/validators/warnings/unknown_parameter_name/result.rb +4 -3
  91. data/lib/yard/lint/validators/warnings/unknown_parameter_name/validator.rb +1 -18
  92. data/lib/yard/lint/validators/warnings/unknown_tag/messages_builder.rb +144 -0
  93. data/lib/yard/lint/validators/warnings/unknown_tag/result.rb +4 -3
  94. data/lib/yard/lint/validators/warnings/unknown_tag/validator.rb +1 -18
  95. data/lib/yard/lint/validators/warnings/unknown_tag.rb +10 -0
  96. data/lib/yard/lint/version.rb +1 -1
  97. data/lib/yard/lint.rb +81 -13
  98. data/renovate.json +1 -8
  99. metadata +38 -2
  100. data/lib/yard/lint/command_cache.rb +0 -93
@@ -8,38 +8,28 @@ module Yard
8
8
  # Runs a query that will pick all the boolean methods (ending with ?) that
9
9
  # do not have a return type or return description documented
10
10
  class Validator < Base
11
- # Query to find all the boolean methods without proper return documentation
12
- # Requires either: no @return tag, OR @return tag with no types specified
13
- # Accepts @return [Boolean] without description text as valid documentation
14
- QUERY = <<~QUERY.tr("\n", ' ')
15
- '
16
- type == :method &&
17
- !is_alias? &&
18
- is_explicit? &&
19
- name.to_s.end_with?("?") &&
20
- (tag("return").nil? || tag("return").types.to_a.empty?)
21
- '
22
- QUERY
11
+ # Enable in-process execution for this validator
12
+ in_process visibility: :public
23
13
 
24
- private_constant :QUERY
14
+ # Execute query for a single object during in-process execution.
15
+ # Finds boolean methods (ending with ?) without @return tag or return types.
16
+ # @param object [YARD::CodeObjects::Base] the code object to query
17
+ # @param collector [Executor::ResultCollector] collector for output
18
+ # @return [void]
19
+ def in_process_query(object, collector)
20
+ # Only check methods
21
+ return unless object.type == :method
22
+ # Skip aliases and implicit methods
23
+ return if object.is_alias?
24
+ return unless object.is_explicit?
25
+ # Only check boolean methods (ending with ?)
26
+ return unless object.name.to_s.end_with?('?')
25
27
 
26
- private
28
+ # Check if @return tag is missing or has no types
29
+ return_tag = object.tag(:return)
30
+ return unless return_tag.nil? || return_tag.types.to_a.empty?
27
31
 
28
- # Runs yard list query with proper settings on a given dir and files
29
- # @param dir [String] dir where we should generate the temp docs
30
- # @param file_list_path [String] path to temp file containing file paths (one per line)
31
- # @return [Hash] shell command execution hash results
32
- def yard_cmd(dir, file_list_path)
33
- cmd = <<~CMD
34
- cat #{Shellwords.escape(file_list_path)} | xargs yard list \
35
- #{shell_arguments} \
36
- --query #{QUERY} \
37
- -q \
38
- -b #{Shellwords.escape(dir)}
39
- CMD
40
- cmd = cmd.tr("\n", ' ')
41
-
42
- shell(cmd)
32
+ collector.puts "#{object.file}:#{object.line}: #{object.title}"
43
33
  end
44
34
  end
45
35
  end
@@ -29,7 +29,6 @@ module Yard
29
29
  #
30
30
  # Documentation/UndocumentedBooleanMethods:
31
31
  # Enabled: false
32
- #
33
32
  module UndocumentedBooleanMethods
34
33
  end
35
34
  end
@@ -7,44 +7,28 @@ module Yard
7
7
  module UndocumentedMethodArguments
8
8
  # Runs yard list to check for missing args docs on methods that were documented
9
9
  class Validator < Base
10
- # Options that stats supports but not list
11
- UNWANTED_OPTIONS = %w[
12
- --list-undoc
13
- ].freeze
10
+ # Enable in-process execution for this validator
11
+ in_process visibility: :public
14
12
 
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
13
+ # Execute query for a single object during in-process execution.
14
+ # Finds methods where parameters.size > @param tags count.
15
+ # @param object [YARD::CodeObjects::Base] the code object to query
16
+ # @param collector [Executor::ResultCollector] collector for output
17
+ # @return [void]
18
+ def in_process_query(object, collector)
19
+ # Only check methods
20
+ return unless object.type == :method
21
+ # Skip aliases and implicit methods
22
+ return if object.is_alias?
23
+ return unless object.is_explicit?
25
24
 
26
- private_constant :UNWANTED_OPTIONS, :QUERY
25
+ # Check if parameters count exceeds @param tags count
26
+ param_count = object.parameters.size
27
+ param_tags_count = object.tags(:param).size
27
28
 
28
- private
29
+ return unless param_count > param_tags_count
29
30
 
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 file_list_path [String] path to temp file containing file paths (one per line)
33
- # @return [Hash] shell command execution hash results
34
- def yard_cmd(dir, file_list_path)
35
- shell_args = shell_arguments
36
- UNWANTED_OPTIONS.each { |opt| shell_args.gsub!(opt, '') }
37
-
38
- cmd = <<~CMD
39
- cat #{Shellwords.escape(file_list_path)} | xargs yard list \
40
- #{shell_args} \
41
- --query #{QUERY} \
42
- -q \
43
- -b #{Shellwords.escape(dir)}
44
- CMD
45
- cmd = cmd.tr("\n", ' ')
46
-
47
- shell(cmd)
31
+ collector.puts "#{object.file}:#{object.line}: #{object.title}"
48
32
  end
49
33
  end
50
34
  end
@@ -29,7 +29,6 @@ module Yard
29
29
  #
30
30
  # Documentation/UndocumentedMethodArguments:
31
31
  # Enabled: false
32
- #
33
32
  module UndocumentedMethodArguments
34
33
  end
35
34
  end
@@ -7,33 +7,25 @@ module Yard
7
7
  module UndocumentedObjects
8
8
  # Runs yard list to check for undocumented objects
9
9
  class Validator < Base
10
- private
10
+ # Enable in-process execution for this validator
11
+ in_process visibility: :public
11
12
 
12
- # Runs yard list query with proper settings on a given dir and files
13
- # @param dir [String] dir where we should generate the temp docs
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
- #{shell_arguments} \
20
- --query #{query} \
21
- -q \
22
- -b #{Shellwords.escape(dir)}
23
- CMD
24
- cmd = cmd.tr("\n", ' ')
13
+ # Execute query for a single object during in-process execution.
14
+ # Checks for empty docstrings and outputs location with arity for methods.
15
+ # @param object [YARD::CodeObjects::Base] the code object to query
16
+ # @param collector [Executor::ResultCollector] collector for output
17
+ # @return [void]
18
+ def in_process_query(object, collector)
19
+ # Check if docstring is empty
20
+ return unless object.docstring.all.empty?
25
21
 
26
- shell(cmd)
27
- end
28
-
29
- # Custom query that outputs parameter count for methods
30
- # Format: file.rb:LINE: ElementName|ARITY
31
- # Arity counts all parameters (required + optional) excluding splat and block
32
- # @return [String] YARD query string
33
- def query
34
- <<~QUERY.chomp
35
- "if docstring.all.empty? then if object.is_a?(YARD::CodeObjects::MethodObject) then arity = object.parameters.reject { |p| p[0].start_with?('*', '&') }.size; puts object.file + ':' + object.line.to_s + ': ' + object.title + '|' + arity.to_s; else puts object.file + ':' + object.line.to_s + ': ' + object.title; end; false; end"
36
- QUERY
22
+ if object.is_a?(YARD::CodeObjects::MethodObject)
23
+ # For methods, include arity (excluding splat and block params)
24
+ arity = object.parameters.reject { |p| p[0].to_s.start_with?('*', '&') }.size
25
+ collector.puts "#{object.file}:#{object.line}: #{object.title}|#{arity}"
26
+ else
27
+ collector.puts "#{object.file}:#{object.line}: #{object.title}"
28
+ end
37
29
  end
38
30
  end
39
31
  end
@@ -22,8 +22,8 @@ module Yard
22
22
  # - 'to_s' # Excludes ALL to_s methods regardless of parameters
23
23
  # - 'inspect' # Excludes ALL inspect methods
24
24
  #
25
- # Note: Exact name matching excludes the method with **any arity**. If you need
26
- # arity-specific exclusions, use arity notation instead.
25
+ # @note Exact name matching excludes the method with **any arity**. If you need
26
+ # arity-specific exclusions, use arity notation instead.
27
27
  #
28
28
  # ### 2. Arity Notation (method_name/N)
29
29
  #
@@ -34,8 +34,8 @@ module Yard
34
34
  # - 'call/1' # Only excludes call methods with exactly 1 parameter
35
35
  # - 'initialize/2' # Only excludes initialize with exactly 2 parameters
36
36
  #
37
- # Note: Arity counts total parameters (required + optional) excluding splat (*)
38
- # and block (&) parameters.
37
+ # @note Arity counts total parameters (required + optional) excluding splat (*)
38
+ # and block (&) parameters.
39
39
  #
40
40
  # ### 3. Regex Patterns
41
41
  #
@@ -134,7 +134,6 @@ module Yard
134
134
  # 2. Splat parameters don't count: `def method(a, *rest)` has arity 1
135
135
  # 3. Block parameters don't count: `def method(a, &block)` has arity 1
136
136
  # 4. Keyword arguments count as individual parameters: `def method(a:, b:)` has arity 2
137
- #
138
137
  module UndocumentedObjects
139
138
  end
140
139
  end
@@ -7,28 +7,37 @@ module Yard
7
7
  module UndocumentedOptions
8
8
  # Validates that methods with options hash parameters have @option tags
9
9
  class Validator < Validators::Base
10
- # YARD query to detect methods with options parameters but no @option tags
11
- # @return [String] YARD Ruby query code
12
- def query
13
- <<~QUERY.strip
14
- 'if object.is_a?(YARD::CodeObjects::MethodObject); params = object.parameters || []; has_options_param = params.any? { |p| p[0] =~ /^(options?|opts?|kwargs)$/ || p[0] =~ /^\\*\\*/ || (p[0] =~ /^(options?|opts?|kwargs)$/ && p[1] =~ /^\\{\\}/) }; if has_options_param; option_tags = object.tags(:option); if option_tags.empty?; puts object.file + ":" + object.line.to_s + ": " + object.title; puts params.map { |p| p.join(" ") }.join(", "); end; end; end; false'
15
- QUERY
16
- end
10
+ # Enable in-process execution for this validator
11
+ in_process visibility: :public
12
+
13
+ # Execute query for a single object during in-process execution.
14
+ # Finds methods with options parameters but no @option tags.
15
+ # @param object [YARD::CodeObjects::Base] the code object to query
16
+ # @param collector [Executor::ResultCollector] collector for output
17
+ # @return [void]
18
+ def in_process_query(object, collector)
19
+ # Only check method objects
20
+ return unless object.is_a?(YARD::CodeObjects::MethodObject)
21
+
22
+ params = object.parameters || []
23
+
24
+ # Check for options-style parameters
25
+ has_options_param = params.any? do |p|
26
+ param_name = p[0].to_s
27
+ # Match options, option, opts, opt, kwargs or double-splat (**)
28
+ param_name.match?(/^(options?|opts?|kwargs)$/) ||
29
+ param_name.start_with?('**')
30
+ end
31
+
32
+ return unless has_options_param
33
+
34
+ # Check if @option tags are missing
35
+ option_tags = object.tags(:option)
36
+ return unless option_tags.empty?
17
37
 
18
- # Builds and executes the YARD command to detect undocumented options
19
- # @param dir [String] the directory containing the .yardoc database
20
- # @param file_list_path [String] path to file containing list of files to analyze
21
- # @return [String] command output
22
- def yard_cmd(dir, file_list_path)
23
- cmd = <<~CMD
24
- cat #{Shellwords.escape(file_list_path)} | xargs yard list \
25
- #{shell_arguments} \
26
- --query #{query} \
27
- -q \
28
- -b #{Shellwords.escape(dir)}
29
- CMD
30
- cmd = cmd.tr("\n", ' ')
31
- shell(cmd)
38
+ # Output method location and parameter info
39
+ collector.puts "#{object.file}:#{object.line}: #{object.title}"
40
+ collector.puts params.map { |p| p.join(' ') }.join(', ')
32
41
  end
33
42
  end
34
43
  end
@@ -31,7 +31,6 @@ module Yard
31
31
  #
32
32
  # Documentation/UndocumentedOptions:
33
33
  # Enabled: false
34
- #
35
34
  module UndocumentedOptions
36
35
  end
37
36
  end
@@ -24,14 +24,14 @@ module Yard
24
24
  # @return [Array<Hash>] array of offense hashes
25
25
  def build_offenses
26
26
  @parsed_data.map do |offense_data|
27
- {
27
+ offense_data.merge(
28
28
  severity: configured_severity,
29
29
  type: self.class.offense_type,
30
30
  name: offense_data[:name] || self.class.offense_name,
31
31
  message: build_message(offense_data),
32
32
  location: offense_data[:location] || offense_data[:file],
33
33
  location_line: offense_data[:line] || offense_data[:location_line] || 0
34
- }
34
+ )
35
35
  end
36
36
  end
37
37
  end
@@ -7,54 +7,42 @@ module Yard
7
7
  module AbstractMethods
8
8
  # Validator to check @abstract methods have proper implementation
9
9
  class Validator < Base
10
- private
10
+ # Enable in-process execution with all visibility
11
+ in_process visibility: :all
11
12
 
12
- # Runs YARD list query to find abstract methods with implementation
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}")
13
+ # Execute query for a single object during in-process execution.
14
+ # Checks if @abstract methods have implementation.
15
+ # @param object [YARD::CodeObjects::Base] the code object to query
16
+ # @param collector [Executor::ResultCollector] collector for output
17
+ # @return [void]
18
+ def in_process_query(object, collector)
19
+ return unless object.has_tag?(:abstract)
20
+ return unless object.is_a?(YARD::CodeObjects::MethodObject)
25
21
 
26
- shell(cmd)
27
- end
22
+ # Check if method has actual implementation (not just NotImplementedError)
23
+ source = begin
24
+ object.source
25
+ rescue StandardError
26
+ nil
27
+ end
28
+ return unless source && !source.empty?
29
+
30
+ # Simple heuristic: abstract methods should be empty or raise NotImplementedError
31
+ lines = source.split("\n").map(&:strip).reject(&:empty?)
32
+ # Skip def line and end
33
+ body_lines = lines[1...-1] || []
28
34
 
29
- # @return [String] yard query to find abstract methods with implementation
30
- def query
31
- <<~QUERY
32
- '
33
- if object.has_tag?(:abstract) && object.is_a?(YARD::CodeObjects::MethodObject)
34
- # Check if method has actual implementation (not just NotImplementedError)
35
- source = object.source rescue nil
36
- if source && !source.empty?
37
- # Simple heuristic: abstract methods should be empty or raise NotImplementedError
38
- lines = source.split("\\n").map(&:strip).reject(&:empty?)
39
- # Skip def line and end
40
- body_lines = lines[1...-1] || []
35
+ has_real_implementation = body_lines.any? do |line|
36
+ !line.start_with?('#') &&
37
+ !line.include?('NotImplementedError') &&
38
+ !line.include?('raise') &&
39
+ line != 'end'
40
+ end
41
41
 
42
- has_real_implementation = body_lines.any? do |line|
43
- !line.start_with?('#') &&
44
- !line.include?('NotImplementedError') &&
45
- !line.include?('raise') &&
46
- line != 'end'
47
- end
42
+ return unless has_real_implementation
48
43
 
49
- if has_real_implementation
50
- puts object.file + ':' + object.line.to_s + ': ' + object.title
51
- puts 'has_implementation'
52
- end
53
- end
54
- end
55
- false
56
- '
57
- QUERY
44
+ collector.puts "#{object.file}:#{object.line}: #{object.title}"
45
+ collector.puts 'has_implementation'
58
46
  end
59
47
  end
60
48
  end
@@ -34,7 +34,6 @@ module Yard
34
34
  #
35
35
  # Semantic/AbstractMethods:
36
36
  # Enabled: false
37
- #
38
37
  module AbstractMethods
39
38
  end
40
39
  end
@@ -7,49 +7,34 @@ module Yard
7
7
  module ApiTags
8
8
  # Validator to check for @api tag presence and validity
9
9
  class Validator < Base
10
- private
10
+ # Enable in-process execution with all visibility
11
+ in_process visibility: :all
11
12
 
12
- # Runs yard list query to find objects missing or with invalid @api 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}")
13
+ # Execute query for a single object during in-process execution.
14
+ # Checks for @api tag presence and validity.
15
+ # @param object [YARD::CodeObjects::Base] the code object to query
16
+ # @param collector [Executor::ResultCollector] collector for output
17
+ # @return [void]
18
+ def in_process_query(object, collector)
19
+ allowed_list = allowed_apis
25
20
 
26
- shell(cmd)
21
+ if object.has_tag?(:api)
22
+ api_value = object.tag(:api).text
23
+ unless allowed_list.include?(api_value)
24
+ collector.puts "#{object.file}:#{object.line}: #{object.title}"
25
+ collector.puts "invalid:#{api_value}"
26
+ end
27
+ elsif require_api_tags?
28
+ # Only check public methods/classes if require_api_tags is enabled
29
+ visibility = object.visibility.to_s
30
+ if visibility == 'public' && !object.root?
31
+ collector.puts "#{object.file}:#{object.line}: #{object.title}"
32
+ collector.puts 'missing'
33
+ end
34
+ end
27
35
  end
28
36
 
29
- # @return [String] yard query to find objects with missing or invalid @api tags
30
- def query
31
- allowed_list = allowed_apis.map { |api| "'#{api}'" }.join(', ')
32
-
33
- <<~QUERY
34
- '
35
- if object.has_tag?(:api)
36
- api_value = object.tag(:api).text
37
- unless [#{allowed_list}].include?(api_value)
38
- puts object.file + ':' + object.line.to_s + ': ' + object.title
39
- puts 'invalid:' + api_value
40
- end
41
- elsif #{require_api_tags?}
42
- # Only check public methods/classes if require_api_tags is enabled
43
- visibility = object.visibility.to_s
44
- if visibility == 'public' && !object.root?
45
- puts object.file + ':' + object.line.to_s + ': ' + object.title
46
- puts 'missing'
47
- end
48
- end
49
- false
50
- '
51
- QUERY
52
- end
37
+ private
53
38
 
54
39
  # @return [Array<String>] list of allowed API values
55
40
  def allowed_apis
@@ -37,7 +37,6 @@ module Yard
37
37
  # def some_method
38
38
  # end
39
39
  # end
40
- #
41
40
  module ApiTags
42
41
  end
43
42
  end
@@ -7,83 +7,54 @@ module Yard
7
7
  module CollectionType
8
8
  # Validates Hash collection type syntax in YARD tags
9
9
  class Validator < Base
10
- private
11
-
12
- # Runs YARD query to find incorrect Hash<K, V> syntax
13
- # @param dir [String] directory where YARD database is stored
14
- # @param file_list_path [String] path to temp file containing file paths (one per line)
15
- # @return [Hash] shell command execution results
16
- def yard_cmd(dir, file_list_path)
17
- # Write query to a temporary file to avoid shell escaping issues
18
- cmd = "cat #{Shellwords.escape(file_list_path)} | xargs yard list --query #{query} "
19
-
20
- Tempfile.create(['yard_query', '.sh']) do |f|
21
- f.write("#!/bin/bash\n")
22
- f.write(cmd)
23
- f.write("#{shell_arguments} -b #{Shellwords.escape(dir)}\n")
24
- f.flush
25
- f.chmod(0o755)
26
-
27
- shell("bash #{Shellwords.escape(f.path)}")
28
- end
29
- end
30
-
31
- # YARD query that finds incorrect collection syntax based on EnforcedStyle
32
- # Format output as two lines per violation:
33
- # Line 1: file.rb:LINE: ClassName#method_name
34
- # Line 2: tag_name|type_string|detected_style
35
- # @return [String] YARD query string
36
- def query
10
+ # Enable in-process execution
11
+ in_process visibility: :public
12
+
13
+ # Execute query for a single object during in-process execution.
14
+ # Validates Hash collection type syntax based on EnforcedStyle.
15
+ # @param object [YARD::CodeObjects::Base] the code object to query
16
+ # @param collector [Executor::ResultCollector] collector for output
17
+ # @return [void]
18
+ def in_process_query(object, collector)
19
+ validated_tags = config_or_default('ValidatedTags')
37
20
  style = enforced_style
38
21
 
39
- <<~QUERY.strip
40
- '
41
- docstring
42
- .tags
43
- .select { |tag| #{validated_tags_array}.include?(tag.tag_name) }
44
- .each do |tag|
45
- next unless tag.types
46
-
47
- tag.types.each do |type_str|
48
- detected_style = nil
49
-
50
- # Check for Hash<...> syntax (angle brackets)
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}"
63
- puts object.file + ":" + object.line.to_s + ": " + object.title
64
- puts tag.tag_name + "|" + type_str + "|" + detected_style
65
- break
66
- end
67
- end
22
+ object.docstring.tags
23
+ .select { |tag| validated_tags.include?(tag.tag_name) }
24
+ .each do |tag|
25
+ next unless tag.types
26
+
27
+ tag.types.each do |type_str|
28
+ detected_style = nil
29
+
30
+ # Check for Hash<...> syntax (angle brackets)
31
+ if type_str =~ /Hash<.*>/
32
+ detected_style = 'short'
33
+ # Check for Hash{...} syntax (curly braces)
34
+ elsif type_str =~ /Hash\{.*\}/
35
+ detected_style = 'long'
36
+ # Check for {...} syntax without Hash prefix
37
+ elsif type_str =~ /^\{.*\}$/
38
+ detected_style = 'short'
68
39
  end
69
40
 
70
- false
71
- '
72
- QUERY
41
+ # Report violations based on enforced style
42
+ if detected_style && detected_style != style
43
+ collector.puts "#{object.file}:#{object.line}: #{object.title}"
44
+ collector.puts "#{tag.tag_name}|#{type_str}|#{detected_style}"
45
+ break
46
+ end
47
+ end
48
+ end
73
49
  end
74
50
 
51
+ private
52
+
75
53
  # Gets the enforced collection style from configuration
76
54
  # @return [String] 'long' or 'short'
77
55
  def enforced_style
78
56
  config_or_default('EnforcedStyle')
79
57
  end
80
-
81
- # Array of tag names to validate, formatted for YARD query
82
- # @return [String] Ruby array literal string
83
- def validated_tags_array
84
- tags = config_or_default('ValidatedTags')
85
- "[#{tags.map { |t| "\"#{t}\"" }.join(',')}]"
86
- end
87
58
  end
88
59
  end
89
60
  end
@@ -41,7 +41,6 @@ module Yard
41
41
  #
42
42
  # Tags/CollectionType:
43
43
  # Enabled: false
44
- #
45
44
  module CollectionType
46
45
  end
47
46
  end