yard-lint 1.2.2 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +174 -1
- data/README.md +118 -3
- data/Rakefile +20 -0
- data/bin/yard-lint +80 -37
- data/lib/yard/lint/config.rb +5 -0
- data/lib/yard/lint/config_generator.rb +8 -179
- data/lib/yard/lint/config_updater.rb +222 -0
- data/lib/yard/lint/errors.rb +6 -0
- data/lib/yard/lint/executor/in_process_registry.rb +130 -0
- data/lib/yard/lint/executor/query_executor.rb +109 -0
- data/lib/yard/lint/executor/result_collector.rb +55 -0
- data/lib/yard/lint/executor/warning_dispatcher.rb +79 -0
- data/lib/yard/lint/results/base.rb +2 -1
- data/lib/yard/lint/runner.rb +88 -35
- data/lib/yard/lint/stats_calculator.rb +1 -1
- data/lib/yard/lint/templates/default_config.yml +279 -0
- data/lib/yard/lint/templates/strict_config.yml +283 -0
- data/lib/yard/lint/validators/base.rb +52 -118
- data/lib/yard/lint/validators/documentation/blank_line_before_definition/config.rb +25 -0
- data/lib/yard/lint/validators/documentation/blank_line_before_definition/messages_builder.rb +39 -0
- data/lib/yard/lint/validators/documentation/blank_line_before_definition/parser.rb +59 -0
- data/lib/yard/lint/validators/documentation/blank_line_before_definition/result.rb +61 -0
- data/lib/yard/lint/validators/documentation/blank_line_before_definition/validator.rb +94 -0
- data/lib/yard/lint/validators/documentation/blank_line_before_definition.rb +63 -0
- data/lib/yard/lint/validators/documentation/empty_comment_line/config.rb +24 -0
- data/lib/yard/lint/validators/documentation/empty_comment_line/messages_builder.rb +34 -0
- data/lib/yard/lint/validators/documentation/empty_comment_line/parser.rb +60 -0
- data/lib/yard/lint/validators/documentation/empty_comment_line/result.rb +25 -0
- data/lib/yard/lint/validators/documentation/empty_comment_line/validator.rb +109 -0
- data/lib/yard/lint/validators/documentation/empty_comment_line.rb +58 -0
- data/lib/yard/lint/validators/documentation/markdown_syntax/validator.rb +36 -21
- data/lib/yard/lint/validators/documentation/markdown_syntax.rb +0 -1
- data/lib/yard/lint/validators/documentation/undocumented_boolean_methods/validator.rb +19 -29
- data/lib/yard/lint/validators/documentation/undocumented_boolean_methods.rb +0 -1
- data/lib/yard/lint/validators/documentation/undocumented_method_arguments/validator.rb +18 -34
- data/lib/yard/lint/validators/documentation/undocumented_method_arguments.rb +0 -1
- data/lib/yard/lint/validators/documentation/undocumented_objects/parser.rb +2 -2
- data/lib/yard/lint/validators/documentation/undocumented_objects/validator.rb +17 -25
- data/lib/yard/lint/validators/documentation/undocumented_objects.rb +4 -5
- data/lib/yard/lint/validators/documentation/undocumented_options/validator.rb +30 -21
- data/lib/yard/lint/validators/documentation/undocumented_options.rb +0 -1
- data/lib/yard/lint/validators/semantic/abstract_methods/result.rb +2 -2
- data/lib/yard/lint/validators/semantic/abstract_methods/validator.rb +31 -43
- data/lib/yard/lint/validators/semantic/abstract_methods.rb +0 -1
- data/lib/yard/lint/validators/tags/api_tags/validator.rb +24 -39
- data/lib/yard/lint/validators/tags/api_tags.rb +0 -1
- data/lib/yard/lint/validators/tags/collection_type/parser.rb +1 -1
- data/lib/yard/lint/validators/tags/collection_type/validator.rb +37 -66
- data/lib/yard/lint/validators/tags/collection_type.rb +0 -1
- data/lib/yard/lint/validators/tags/example_syntax/validator.rb +51 -64
- data/lib/yard/lint/validators/tags/example_syntax.rb +0 -1
- data/lib/yard/lint/validators/tags/informal_notation/config.rb +40 -0
- data/lib/yard/lint/validators/tags/informal_notation/messages_builder.rb +35 -0
- data/lib/yard/lint/validators/tags/informal_notation/parser.rb +55 -0
- data/lib/yard/lint/validators/tags/informal_notation/result.rb +26 -0
- data/lib/yard/lint/validators/tags/informal_notation/validator.rb +133 -0
- data/lib/yard/lint/validators/tags/informal_notation.rb +45 -0
- data/lib/yard/lint/validators/tags/invalid_types/validator.rb +57 -70
- data/lib/yard/lint/validators/tags/invalid_types.rb +0 -1
- data/lib/yard/lint/validators/tags/meaningless_tag/parser.rb +1 -1
- data/lib/yard/lint/validators/tags/meaningless_tag/validator.rb +22 -54
- data/lib/yard/lint/validators/tags/meaningless_tag.rb +0 -1
- data/lib/yard/lint/validators/tags/non_ascii_type/config.rb +21 -0
- data/lib/yard/lint/validators/tags/non_ascii_type/messages_builder.rb +29 -0
- data/lib/yard/lint/validators/tags/non_ascii_type/parser.rb +59 -0
- data/lib/yard/lint/validators/tags/non_ascii_type/result.rb +25 -0
- data/lib/yard/lint/validators/tags/non_ascii_type/validator.rb +50 -0
- data/lib/yard/lint/validators/tags/non_ascii_type.rb +39 -0
- data/lib/yard/lint/validators/tags/option_tags/result.rb +2 -2
- data/lib/yard/lint/validators/tags/option_tags/validator.rb +25 -40
- data/lib/yard/lint/validators/tags/option_tags.rb +0 -1
- data/lib/yard/lint/validators/tags/order/validator.rb +28 -55
- data/lib/yard/lint/validators/tags/order.rb +0 -1
- data/lib/yard/lint/validators/tags/redundant_param_description/config.rb +15 -1
- data/lib/yard/lint/validators/tags/redundant_param_description/messages_builder.rb +5 -0
- data/lib/yard/lint/validators/tags/redundant_param_description/validator.rb +134 -100
- data/lib/yard/lint/validators/tags/redundant_param_description.rb +0 -1
- data/lib/yard/lint/validators/tags/tag_group_separator/config.rb +29 -0
- data/lib/yard/lint/validators/tags/tag_group_separator/messages_builder.rb +49 -0
- data/lib/yard/lint/validators/tags/tag_group_separator/parser.rb +67 -0
- data/lib/yard/lint/validators/tags/tag_group_separator/result.rb +28 -0
- data/lib/yard/lint/validators/tags/tag_group_separator/validator.rb +117 -0
- data/lib/yard/lint/validators/tags/tag_group_separator.rb +49 -0
- data/lib/yard/lint/validators/tags/tag_type_position/parser.rb +1 -1
- data/lib/yard/lint/validators/tags/tag_type_position/validator.rb +53 -84
- data/lib/yard/lint/validators/tags/tag_type_position.rb +4 -5
- data/lib/yard/lint/validators/tags/type_syntax/parser.rb +8 -3
- data/lib/yard/lint/validators/tags/type_syntax/validator.rb +29 -59
- data/lib/yard/lint/validators/tags/type_syntax.rb +0 -1
- data/lib/yard/lint/validators/warnings/duplicated_parameter_name/validator.rb +1 -18
- data/lib/yard/lint/validators/warnings/invalid_directive_format/validator.rb +1 -18
- data/lib/yard/lint/validators/warnings/invalid_tag_format/validator.rb +1 -18
- data/lib/yard/lint/validators/warnings/unknown_directive/validator.rb +1 -18
- data/lib/yard/lint/validators/warnings/unknown_parameter_name/messages_builder.rb +243 -0
- data/lib/yard/lint/validators/warnings/unknown_parameter_name/result.rb +4 -3
- data/lib/yard/lint/validators/warnings/unknown_parameter_name/validator.rb +1 -18
- data/lib/yard/lint/validators/warnings/unknown_tag/messages_builder.rb +144 -0
- data/lib/yard/lint/validators/warnings/unknown_tag/result.rb +4 -3
- data/lib/yard/lint/validators/warnings/unknown_tag/validator.rb +1 -18
- data/lib/yard/lint/validators/warnings/unknown_tag.rb +10 -0
- data/lib/yard/lint/version.rb +1 -1
- data/lib/yard/lint.rb +81 -13
- data/renovate.json +1 -8
- metadata +40 -6
- data/bin/console +0 -11
- data/bin/setup +0 -8
- data/lib/yard/lint/command_cache.rb +0 -93
|
@@ -16,7 +16,7 @@ module Yard
|
|
|
16
16
|
|
|
17
17
|
# @param yard_list_output [String] raw yard list results string
|
|
18
18
|
# @param config [Yard::Lint::Config, nil] configuration object (optional)
|
|
19
|
-
# @
|
|
19
|
+
# @option _kwargs [Object] :unused this parameter accepts no options (reserved for future use)
|
|
20
20
|
# @return [Array<Hash>] Array with undocumented objects details
|
|
21
21
|
def call(yard_list_output, config: nil, **_kwargs)
|
|
22
22
|
excluded_methods = config&.validator_config(
|
|
@@ -108,7 +108,7 @@ module Yard
|
|
|
108
108
|
|
|
109
109
|
# Match an arity pattern like "initialize/0"
|
|
110
110
|
# @param method_name [String] the method name
|
|
111
|
-
# @param arity [Integer, nil] the method
|
|
111
|
+
# @param arity [Integer, nil] number of parameters the method accepts (nil if unknown)
|
|
112
112
|
# @param pattern [String] the full pattern like "initialize/0"
|
|
113
113
|
# @return [Boolean] true if matches
|
|
114
114
|
def match_arity_pattern(method_name, arity, pattern)
|
|
@@ -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
|
-
|
|
10
|
+
# Enable in-process execution for this validator
|
|
11
|
+
in_process visibility: :public
|
|
11
12
|
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
# @param
|
|
15
|
-
# @
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
#
|
|
26
|
-
#
|
|
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
|
-
#
|
|
38
|
-
#
|
|
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
|
-
#
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
|
@@ -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
|
-
|
|
10
|
+
# Enable in-process execution with all visibility
|
|
11
|
+
in_process visibility: :all
|
|
11
12
|
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
# @param
|
|
15
|
-
# @
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
27
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
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
|
-
|
|
50
|
-
|
|
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
|
|
@@ -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
|
-
|
|
10
|
+
# Enable in-process execution with all visibility
|
|
11
|
+
in_process visibility: :all
|
|
11
12
|
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
# @param
|
|
15
|
-
# @
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
@@ -9,7 +9,7 @@ module Yard
|
|
|
9
9
|
class Parser < ::Yard::Lint::Parsers::Base
|
|
10
10
|
# Parses YARD query output into structured violation data
|
|
11
11
|
# @param yard_output [String] raw output from YARD query
|
|
12
|
-
# @
|
|
12
|
+
# @option _kwargs [Object] :unused this parameter accepts no options (reserved for future use)
|
|
13
13
|
# @return [Array<Hash>] array of violation hashes
|
|
14
14
|
def call(yard_output, **_kwargs)
|
|
15
15
|
return [] if yard_output.nil? || yard_output.strip.empty?
|
|
@@ -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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# @
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|