-
i want to run i have several instances of undocumentable code one instance is this in a rails model, also the subject of this 12-year-old SO question which i just put a bounty on 😄 include Rails.application.routes.url_helpers is there any way to ignore or document these so that there are no warnings? i researched high and low before writing this, i hope i didn't miss something. thanks for a great project! |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments
-
in case helplful to someone finding this, here's what i'm trying in CircleCI set +e # do not exit right away if a command fails https://circleci.com/docs/configuration-reference/#default-shell-options
yard doc --fail-on-warning --no-output &> yard_out
grep "\[warn\]" yard_out | grep -ivq undocumentable
if [ $? -eq 0 ]; then # grep found a warning that is not undocumentable? that's bad
echo "IMPORTANT: Do not try to fix 'Undocumentable' errors, only fix the others"
echo
cat yard_out
echo
echo "IMPORTANT: Do not try to fix 'Undocumentable' errors, only fix the others"
exit 1
fi
cat yard_out # all good! show output and exit success |
Beta Was this translation helpful? Give feedback.
-
This is a bit of a loaded question. There is no way to retain the same syntax and not have YARD display warnings. By the same token, if you do not want warnings to fail your CI build, you should not use the built-in In general, the solution to providing documentable code is to reduce your use of dynamic calls such as the one you've listed. In almost all cases, there is a non-dynamic alternative to dynamic Ruby syntaxes. In the case of your specific example, you could use module WithRoutes
extend ActiveSupport::Concern
included do
include Rails.application.routes.url_helpers
end
end
class MyController < ApplicationController
include WithRoutes
end This will bypass top-level inclusion in the YARD parser. If you do not want to change your syntax, the solution you've come up with is basically the simplest "recommended" path as far as implementing simple custom linting in CI. If you want something a little more robust, you can consider using YARD extensions, like overriding YARD::Logger#warn to do this type of parsing in Ruby, or via an extension to specific handlers. The latter would afford you a lot more flexibility about what type of code is allowed and when, for example: # yard_extensions/ignore_rails_mixin.rb
module IgnoreRailsMixin
def process
super
rescue YARD::Parser::UndocumentableError => e
raise e unless statement.last.source.start_with?("Rails.")
end
end
YARD::Handlers::Ruby::MixinHandler.prepend(IgnoreRailsMixin) You can use the above via |
Beta Was this translation helpful? Give feedback.
-
Wow, thank you so much for these solutions! |
Beta Was this translation helpful? Give feedback.
-
Here's what I came up with, I couldn't figure out a way to get it into the top level process method, since it's done with metaprogramming # https://github.com/lsegal/yard/issues/1542
module YardIgnoreUndocumentable
def process
super
rescue YARD::Parser::UndocumentableError => e
puts '😎'
end
end
YARD::Handlers::Ruby::MixinHandler.prepend(YardIgnoreUndocumentable)
YARD::Handlers::Ruby::AttributeHandler.prepend(YardIgnoreUndocumentable)
YARD::Handlers::Ruby::MethodHandler.prepend(YardIgnoreUndocumentable) and then running this in CI yard doc -e lib/yard_extensions/ignore_undocumentable.rb --fail-on-warning # do not add --no-output |
Beta Was this translation helpful? Give feedback.
-
I found this thread really useful. Here is a version that comes with a config file. Probably worth making it a plugin in the future. Extension # yard_extensions/ignore_warnings.rb
module IgnoreWarnings
def process
super
rescue YARD::Parser::UndocumentableError => e
raise e unless ::IgnoreWarnings::Registry.instance.ignore?(exception: e, statement: statement)
end
end
require_relative "ignore_warnings/registry"
IgnoreWarnings::Registry.initialize_instance(File.join(File.dirname(__FILE__), "../yard.yml"))
YARD::Handlers::Ruby::ClassHandler.prepend(IgnoreWarnings)
YARD::Handlers::Ruby::MixinHandler.prepend(IgnoreWarnings) # yard_extensions/ignore_warnings/registry.rb
class IgnoreWarnings::Registry
attr_reader :rules
attr_accessor :debug
def initialize
@debug = false
@rules = []
end
def add_rule(hash = {})
if hash.nil? || hash.empty?
raise ArgumentError, "Invalid rule: #{hash}"
end
unknown_keys = hash.keys - %w[file line error_class source]
unless unknown_keys.empty?
raise ArgumentError, "Unknown rule keys #{unknown_keys.map(&:inspect).join(", ")} in #{hash}"
end
@rules << (hash.map { |k, v| [k.to_sym, v] }.to_h)
end
def ignore?(exception:, statement:)
file = statement.last.file
source = statement.last.source
error_class = exception.class.name
line = statement.last.line
@rules.each do |r|
next if r.key?(:error) && r[:error] != error_class
next if r.key?(:file) && r[:file] != file
next if r.key?(:line) && r[:line] != line
next if r.key?(:source) && r[:source] != source
if debug
puts "* [IgnoreWarnings] Rule Matched:\n rule: #{r}\n error_class: #{error_class.inspect}\n file: #{file}\n line: #{line}\n source: #{source.inspect}"
end
return true
end
if debug
puts "* [IgnoreWarnings] No rules matched:\n error_class: #{error_class.inspect}\n file: #{file}\n line: #{line}\n source: #{source.inspect}"
end
false
end
private
class << self
def new_from_config(path)
require "yaml"
new.tap do |registry|
config = YAML.safe_load_file(path)
rules = config.dig("yard", "ignore_warnings", "rules")
registry.debug = config.dig("yard", "ignore_warnings", "debug")
if rules
rules.each { |r| registry.add_rule(r) }
else
raise "No rules found in: #{config}"
end
end
end
def initialize_instance(config_path)
@instance = new_from_config(config_path)
end
def instance
@instance || raise("Did you forget to call IgnoreWarnings::Registry.initialize_instance?")
end
end
end Configuration # yard.yml
yard:
ignore_warnings:
# debug: true
rules:
- file: app/lib/route_helpers.rb
error_class: YARD::Parser::UndocumentableError
source: Rails.application.routes.url_helpers
- file: lib/core_ext/to_bool.rb
error_class: YARD::Parser::UndocumentableError
line: 21 Hope it helps someone else! |
Beta Was this translation helpful? Give feedback.
This is a bit of a loaded question. There is no way to retain the same syntax and not have YARD display warnings. By the same token, if you do not want warnings to fail your CI build, you should not use the built-in
--fail-on-warning
option. YARD's fail-on-warning option is intentionally simplistic, since YARD's core codebase itself is not a documentation linter; the fail on warning option is a convenience to provide an error code if any warning text was printed. tl;dr, fail-on-warning does not allow for customization.In general, the solution to providing documentable code is to reduce your use of dynamic calls…