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
@@ -7,63 +7,31 @@ module Yard
7
7
  module MeaninglessTag
8
8
  # Validates that @param/@option tags only appear on methods
9
9
  class Validator < Base
10
- private
11
-
12
- # Runs YARD query to find @param/@option tags on non-methods
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("--private --protected #{shell_arguments} -b #{Shellwords.escape(dir)}\n")
24
- f.flush
25
- f.chmod(0o755)
26
-
27
- shell("bash #{Shellwords.escape(f.path)}")
10
+ # Enable in-process execution with all visibility
11
+ in_process visibility: :all
12
+
13
+ # Execute query for a single object during in-process execution.
14
+ # Checks for @param/@option tags on non-method objects.
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
+ object_type = object.type.to_s
20
+ invalid_types = invalid_object_types
21
+ tags_to_check = checked_tags
22
+
23
+ return unless invalid_types.include?(object_type)
24
+
25
+ object.docstring.tags.each do |tag|
26
+ next unless tags_to_check.include?(tag.tag_name)
27
+
28
+ collector.puts "#{object.file}:#{object.line}: #{object.title}"
29
+ collector.puts "#{object_type}|#{tag.tag_name}"
30
+ break
28
31
  end
29
32
  end
30
33
 
31
- # YARD query that finds method-only tags on non-method objects
32
- # Format output as two lines per violation:
33
- # Line 1: file.rb:LINE: ClassName
34
- # Line 2: object_type|tag_name
35
- # @return [String] YARD query string
36
- def query
37
- <<~QUERY.strip
38
- '
39
- object_type = object.type.to_s
40
-
41
- if #{invalid_object_types_array}.include?(object_type)
42
- docstring.tags.each do |tag|
43
- if #{checked_tags_array}.include?(tag.tag_name)
44
- puts object.file + ":" + object.line.to_s + ": " + object.title
45
- puts object_type + "|" + tag.tag_name
46
- break
47
- end
48
- end
49
- end
50
-
51
- false
52
- '
53
- QUERY
54
- end
55
-
56
- # Array of tag names to check, formatted for YARD query
57
- # @return [String] Ruby array literal string
58
- def checked_tags_array
59
- "[#{checked_tags.map { |t| "\"#{t}\"" }.join(',')}]"
60
- end
61
-
62
- # Array of invalid object types, formatted for YARD query
63
- # @return [String] Ruby array literal string
64
- def invalid_object_types_array
65
- "[#{invalid_object_types.map { |t| "\"#{t}\"" }.join(',')}]"
66
- end
34
+ private
67
35
 
68
36
  # @return [Array<String>] tags that should only appear on methods
69
37
  def checked_tags
@@ -34,7 +34,6 @@ module Yard
34
34
  # @name = name
35
35
  # end
36
36
  # end
37
- #
38
37
  module MeaninglessTag
39
38
  end
40
39
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Tags
7
+ module NonAsciiType
8
+ # Configuration for NonAsciiType validator
9
+ class Config < ::Yard::Lint::Validators::Config
10
+ self.id = :non_ascii_type
11
+ self.defaults = {
12
+ 'Enabled' => true,
13
+ 'Severity' => 'warning',
14
+ 'ValidatedTags' => %w[param option return yieldreturn yieldparam]
15
+ }.freeze
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Tags
7
+ module NonAsciiType
8
+ # Builds human-readable messages for non-ASCII type violations
9
+ class MessagesBuilder
10
+ class << self
11
+ # Formats a non-ASCII type violation message
12
+ # @param offense [Hash] offense details with tag_name, type_string, character, codepoint
13
+ # @return [String] formatted message
14
+ def call(offense)
15
+ tag = offense[:tag_name]
16
+ type = offense[:type_string]
17
+ char = offense[:character]
18
+ codepoint = offense[:codepoint]
19
+
20
+ "Type specification in @#{tag} tag contains non-ASCII character " \
21
+ "'#{char}' (#{codepoint}) in '#{type}'. Ruby type names must use ASCII characters only."
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Tags
7
+ module NonAsciiType
8
+ # Parser for NonAsciiType validator output
9
+ # Parses output that reports non-ASCII characters in type specifications
10
+ class Parser < ::Yard::Lint::Parsers::Base
11
+ # Parses validator output and extracts non-ASCII type violations
12
+ # Expected format (two lines per violation):
13
+ # file.rb:LINE: ClassName#method_name
14
+ # tag_name|type_string|character|codepoint
15
+ # @param yard_output [String] raw validator query results
16
+ # @option _kwargs [Object] :unused this parameter accepts no options (reserved for future use)
17
+ # @return [Array<Hash>] array with violation details
18
+ def call(yard_output, **_kwargs)
19
+ return [] if yard_output.nil?
20
+
21
+ # Handle potential encoding issues
22
+ sanitized = yard_output.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')
23
+ return [] if sanitized.strip.empty?
24
+
25
+ lines = sanitized.split("\n").map(&:strip).reject(&:empty?)
26
+ violations = []
27
+
28
+ lines.each_slice(2) do |location_line, details_line|
29
+ next unless location_line && details_line
30
+
31
+ # Parse location: "file.rb:10: ClassName#method_name"
32
+ location_match = location_line.match(/^(.+):(\d+): (.+)$/)
33
+ next unless location_match
34
+
35
+ # Parse details: "tag_name|type_string|character|codepoint"
36
+ details = details_line.split('|', 4)
37
+ next unless details.size == 4
38
+
39
+ tag_name, type_string, character, codepoint = details
40
+
41
+ violations << {
42
+ location: location_match[1],
43
+ line: location_match[2].to_i,
44
+ method_name: location_match[3],
45
+ tag_name: tag_name,
46
+ type_string: type_string,
47
+ character: character,
48
+ codepoint: codepoint
49
+ }
50
+ end
51
+
52
+ violations
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Tags
7
+ module NonAsciiType
8
+ # Result wrapper for NonAsciiType validator
9
+ class Result < Results::Base
10
+ self.default_severity = 'warning'
11
+ self.offense_type = 'method'
12
+ self.offense_name = 'NonAsciiType'
13
+
14
+ # Builds a human-readable message for the offense
15
+ # @param offense [Hash] offense details
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,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Tags
7
+ module NonAsciiType
8
+ # Validates that type specifications contain only ASCII characters
9
+ # Ruby type names must be valid Ruby identifiers (ASCII only)
10
+ class Validator < Base
11
+ # Enable in-process execution
12
+ in_process visibility: :public
13
+
14
+ # Pattern to match non-ASCII characters
15
+ NON_ASCII_PATTERN = /[^\x00-\x7F]/
16
+
17
+ # Execute query for a single object during in-process execution.
18
+ # Checks type specifications for non-ASCII characters.
19
+ # @param object [YARD::CodeObjects::Base] the code object to query
20
+ # @param collector [Executor::ResultCollector] collector for output
21
+ # @return [void]
22
+ def in_process_query(object, collector)
23
+ validated_tags = config.validator_config('Tags/NonAsciiType', 'ValidatedTags') ||
24
+ %w[param option return yieldreturn yieldparam]
25
+
26
+ object.docstring.tags
27
+ .select { |tag| validated_tags.include?(tag.tag_name) }
28
+ .each do |tag|
29
+ next unless tag.types
30
+
31
+ tag.types.each do |type_str|
32
+ non_ascii_chars = type_str.scan(NON_ASCII_PATTERN).uniq
33
+ next if non_ascii_chars.empty?
34
+
35
+ # Format: file:line: object_title
36
+ # Then: tag_name|type_string|char|codepoint
37
+ non_ascii_chars.each do |char|
38
+ codepoint = format('U+%04X', char.ord)
39
+ collector.puts "#{object.file}:#{object.line}: #{object.title}"
40
+ collector.puts "#{tag.tag_name}|#{type_str}|#{char}|#{codepoint}"
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yard
4
+ module Lint
5
+ module Validators
6
+ module Tags
7
+ # NonAsciiType validator
8
+ #
9
+ # Detects non-ASCII characters in YARD type specifications. Ruby type names
10
+ # must be valid Ruby identifiers which only support ASCII characters. Non-ASCII
11
+ # characters in type specifications are usually the result of copy-paste errors
12
+ # from word processors that use smart typography (e.g., `…` instead of `...`).
13
+ #
14
+ # This validator is enabled by default.
15
+ #
16
+ # @example Bad - Non-ASCII characters in type specification
17
+ # # @param flags [Symbol, …] variadic flags
18
+ # # @return [String→Integer] transformation result
19
+ # def process(flags)
20
+ # end
21
+ #
22
+ # @example Good - Valid ASCII type syntax
23
+ # # @param flags [Symbol] variadic flags
24
+ # # @return [Hash{String => Integer}] transformation result
25
+ # def process(flags)
26
+ # end
27
+ #
28
+ # ## Configuration
29
+ #
30
+ # To disable this validator:
31
+ #
32
+ # Tags/NonAsciiType:
33
+ # Enabled: false
34
+ module NonAsciiType
35
+ end
36
+ end
37
+ end
38
+ end
39
+ 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,53 +7,38 @@ module Yard
7
7
  module OptionTags
8
8
  # Validator to check methods with options hash have @option tags
9
9
  class Validator < Base
10
- private
11
-
12
- # Runs yard list query to find methods with options parameter but missing @option 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}")
10
+ # Enable in-process execution with all visibility
11
+ in_process visibility: :all
25
12
 
26
- shell(cmd)
27
- end
13
+ # Execute query for a single object during in-process execution.
14
+ # Checks if methods with options parameter have @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
+ return unless object.is_a?(YARD::CodeObjects::MethodObject)
28
20
 
29
- # @return [String] yard query to find methods with options parameter
30
- # but no @option tags
31
- def query
32
21
  parameter_names = config_parameter_names
33
- <<~QUERY
34
- '
35
- if object.is_a?(YARD::CodeObjects::MethodObject)
36
- # Check if method has a parameter named "options" or "opts"
37
- has_options_param = object.parameters.any? do |param|
38
- param_name = param[0].to_s.gsub(/[*:]/, '')
39
- #{parameter_names.inspect}.include?(param_name)
40
- end
41
22
 
42
- if has_options_param
43
- # Check if method has any @option tags
44
- option_tags = object.tags(:option)
23
+ # Check if method has a parameter named "options" or "opts" etc.
24
+ has_options_param = object.parameters.any? do |param|
25
+ param_name = param[0].to_s.gsub(/[*:]/, '')
26
+ parameter_names.include?(param_name)
27
+ end
28
+
29
+ return unless has_options_param
45
30
 
46
- if option_tags.empty?
47
- puts object.file + ':' + object.line.to_s + ': ' + object.title
48
- puts 'missing_option_tags'
49
- end
50
- end
51
- end
52
- false
53
- '
54
- QUERY
31
+ # Check if method has any @option tags
32
+ option_tags = object.tags(:option)
33
+
34
+ return unless option_tags.empty?
35
+
36
+ collector.puts "#{object.file}:#{object.line}: #{object.title}"
37
+ collector.puts 'missing_option_tags'
55
38
  end
56
39
 
40
+ private
41
+
57
42
  # @return [Array<String>] parameter names that should have @option tags
58
43
  def config_parameter_names
59
44
  config.validator_config('Tags/OptionTags', 'ParameterNames') || Config.defaults['ParameterNames']
@@ -29,7 +29,6 @@ module Yard
29
29
  # # @param options [Hash] configuration options
30
30
  # def configure(name, options = {})
31
31
  # end
32
- #
33
32
  module OptionTags
34
33
  end
35
34
  end
@@ -8,78 +8,51 @@ module Yard
8
8
  # Runs a query that will pick all the objects that have docs with tags in an invalid
9
9
  # order. By invalid we mean, that they are not as defined in the settings.
10
10
  class Validator < Base
11
- private
12
-
13
- # Runs yard list query with proper settings on a given dir and files
14
- # @param dir [String] dir where the yard db is (or where it should be generated)
15
- # @param file_list_path [String] path to temp file containing file paths (one per line)
16
- # @return [Hash] shell command execution hash results
17
- def yard_cmd(dir, file_list_path)
18
- cmd = <<~CMD
19
- cat #{Shellwords.escape(file_list_path)} | xargs yard list \
20
- --private \
21
- --protected \
22
- --query #{query} \
23
- -b #{Shellwords.escape(dir)}
24
- CMD
25
-
26
- result = shell(cmd)
27
- result[:stdout] = { result: result[:stdout], tags_order: tags_order }
28
- result
29
- end
30
-
31
- # @return [String] multiline yard query that we use to find methods with
32
- # tags that are not in the valid order
33
- # @note We need to print things for all of the elements as some of them
34
- # are listed in yard twice (for example module functions), and for the
35
- # second time, yard injects things by itself making it impossible to
36
- # figure out whether the order is ok or now. That's why we print all and those
37
- # that are ok, we mark with 'valid' and if it is reported later as invalid again,
38
- # we know, that it is valid
39
- def query
40
- <<-QUERY
41
- '
42
- tags_order = #{query_array(tags_order)}
11
+ # Enable in-process execution with all visibility
12
+ in_process visibility: :all
13
+
14
+ # Execute query for a single object during in-process execution.
15
+ # Checks if tags appear in the configured order.
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
+ return if object.is_alias?
21
+
22
+ # Extract @tag names from docstring
23
+ tag_pattern = /^@(\S+)/
24
+ doc_tags = object.docstring.all.scan(tag_pattern).flatten
25
+
26
+ # Remove consecutive duplicates
43
27
  accu = []
44
- str = "@"
45
- slash = 92.chr
46
- regexp = "^"+str+"("+slash+"S+)"
47
- doc_tags = object.docstring.all.scan(Regexp.new(regexp)).flatten
48
-
49
28
  doc_tags.each do |param|
50
29
  accu << param unless accu.last == param
51
30
  end
52
31
 
53
- tags_order.delete_if { |el| !accu.include?(el) }
54
- accu.delete_if { |el| !tags_order.include?(el) }
32
+ # Filter to only configured tags
33
+ order = tags_order.dup
34
+ order.delete_if { |el| !accu.include?(el) }
35
+ accu.delete_if { |el| !order.include?(el) }
55
36
 
56
- tags_orders = tags_order.join.to_i(36)
37
+ # Compare order using base-36 encoding
38
+ tags_orders = order.join.to_i(36)
57
39
  accus = accu.join.to_i(36)
58
40
 
59
- puts object.file + ":" + object.line.to_s + ": " + object.title
41
+ collector.puts "#{object.file}:#{object.line}: #{object.title}"
60
42
 
61
- if accus != tags_orders && !is_alias?
62
- puts tags_order.join(",")
43
+ if accus != tags_orders
44
+ collector.puts order.join(',')
63
45
  else
64
- puts "valid"
46
+ collector.puts 'valid'
65
47
  end
66
-
67
- false
68
- ' \\
69
- QUERY
70
48
  end
71
49
 
50
+ private
51
+
72
52
  # @return [Array<String>] tags order
73
53
  def tags_order
74
54
  config.validator_config('Tags/Order', 'EnforcedOrder')
75
55
  end
76
-
77
- # @param elements [Array<String>] array of elements that we want to convert into
78
- # a string ruby yard query array form
79
- # @return [String] array of elements for yard query converted into a string
80
- def query_array(elements)
81
- "[#{elements.map { |type| "\"#{type}\"" }.join(',')}]"
82
- end
83
56
  end
84
57
  end
85
58
  end
@@ -28,7 +28,6 @@ module Yard
28
28
  #
29
29
  # Tags/Order:
30
30
  # Enabled: false
31
- #
32
31
  module Order
33
32
  end
34
33
  end
@@ -15,6 +15,19 @@ module Yard
15
15
  'Articles' => %w[The the A a An an],
16
16
  'MaxRedundantWords' => 6,
17
17
  'GenericTerms' => %w[object instance value data item element],
18
+ 'LowValueConnectors' => %w[being to that which for],
19
+ 'LowValueVerbs' => %w[
20
+ perform performed performing
21
+ process processed processing
22
+ use used using
23
+ handle handled handling
24
+ act acted acting
25
+ pass passed passing
26
+ invoke invoked invoking
27
+ call called calling
28
+ execute executed executing
29
+ run running
30
+ ],
18
31
  'EnabledPatterns' => {
19
32
  'ArticleParam' => true,
20
33
  'PossessiveParam' => true,
@@ -22,7 +35,8 @@ module Yard
22
35
  'ParamToVerb' => true,
23
36
  'IdPattern' => true,
24
37
  'DirectionalDate' => true,
25
- 'TypeGeneric' => true
38
+ 'TypeGeneric' => true,
39
+ 'ArticleParamPhrase' => true
26
40
  }
27
41
  }.freeze
28
42
  end
@@ -48,6 +48,11 @@ module Yard
48
48
  'The @' + tag_name + ' description \'' + description + '\' just combines type and generic terms. ' \
49
49
  'Consider removing it or providing specific details about this ' + param_name + '.'
50
50
 
51
+ when 'article_param_phrase'
52
+ 'The @' + tag_name + ' description \'' + description + '\' is a filler phrase that adds no value ' \
53
+ 'beyond the parameter name. ' \
54
+ 'Consider removing it or explaining the specific purpose of ' + param_name + '.'
55
+
51
56
  else
52
57
  'The @' + tag_name + ' description \'' + description + '\' appears redundant. ' \
53
58
  'Consider providing a meaningful description or omitting it entirely.'