Class: Docscribe::Config
- Inherits:
-
Object
- Object
- Docscribe::Config
- Defined in:
- lib/docscribe/config.rb,
lib/docscribe/config/rbs.rb,
lib/docscribe/config/emit.rb,
lib/docscribe/config/utils.rb,
lib/docscribe/config/loader.rb,
lib/docscribe/config/plugin.rb,
lib/docscribe/config/sorbet.rb,
lib/docscribe/config/sorting.rb,
lib/docscribe/config/defaults.rb,
lib/docscribe/config/template.rb,
lib/docscribe/config/filtering.rb
Constant Summary collapse
- DEFAULT =
Default configuration values used when no ‘docscribe.yml` is present or when specific keys are missing from user config.
These defaults define:
-
which documentation tags are emitted
-
default generated text
-
type inference behavior
-
method / file filtering
-
optional RBS integration
-
optional Sorbet integration
-
{ 'emit' => { 'header' => false, 'include_default_message' => true, 'include_param_documentation' => true, 'param_tags' => true, 'return_tag' => true, 'visibility_tags' => true, 'raise_tags' => true, 'rescue_conditional_returns' => true, 'attributes' => false }, 'doc' => { 'default_message' => 'Method documentation.', 'param_tag_style' => 'type_name', 'param_documentation' => 'Param documentation.', 'sort_tags' => true, 'tag_order' => %w[todo note api private protected param option yieldparam raise return] }, 'methods' => { 'instance' => { 'public' => {}, 'protected' => {}, 'private' => {} }, 'class' => { 'public' => {}, 'protected' => {}, 'private' => {} } }, 'inference' => { 'fallback_type' => 'Object', 'nil_as_optional' => true, 'treat_options_keyword_as_hash' => true }, 'filter' => { 'visibilities' => %w[public protected private], 'scopes' => %w[instance class], 'include' => [], 'exclude' => [], 'files' => { 'include' => [], 'exclude' => ['spec'] } }, 'rbs' => { 'enabled' => false, 'collection' => false, 'sig_dirs' => ['sig'], 'collapse_generics' => false }, 'sorbet' => { 'enabled' => false, 'rbi_dirs' => ['sorbet/rbi', 'rbi'], 'collapse_generics' => false }, 'plugins' => { 'require' => [] } }.freeze
Instance Attribute Summary collapse
-
#raw ⇒ Object
readonly
Raw config hash after deep-merging user config with defaults.
Class Method Summary collapse
-
.default_yaml ⇒ String
Return the default YAML template used by ‘docscribe init`.
-
.load(path = nil) ⇒ Docscribe::Config
Load Docscribe configuration from YAML.
-
.safe_load_compat(yaml, filename: nil) ⇒ Hash
Safely load YAML from a string across Psych API versions.
-
.safe_load_file_compat(path) ⇒ Hash
Safely load YAML from a file across Ruby/Psych versions.
Instance Method Summary collapse
-
#core_rbs_provider ⇒ Object
Method documentation.
-
#default_message(scope, visibility) ⇒ String
Default text inserted into generated doc blocks, taking per-scope and per-visibility overrides into account.
-
#emit_attributes? ⇒ Boolean
Whether to emit YARD ‘@!attribute` docs for `attr_*` macros.
-
#emit_header? ⇒ Boolean
Whether to emit method header lines such as: # MyClass#foo -> Integer.
-
#emit_param_tags? ⇒ Boolean
Whether to emit ‘@param` tags.
-
#emit_raise_tags? ⇒ Boolean
Whether to emit inferred ‘@raise` tags.
-
#emit_rescue_conditional_returns? ⇒ Boolean
Whether to emit conditional rescue-return tags like: # @return [String] if FooError.
-
#emit_return_tag?(scope, visibility) ⇒ Boolean
Whether to emit the ‘@return` tag for a method, taking per-scope and per-visibility overrides into account.
-
#emit_visibility_tags? ⇒ Boolean
Whether to emit visibility tags such as ‘@private` and `@protected`.
-
#fallback_type ⇒ String
Fallback type used when inference cannot determine a more specific type.
-
#include_default_message? ⇒ Boolean
Whether to include the default placeholder line: # Method documentation.
-
#include_param_documentation? ⇒ Boolean
Whether to append placeholder text to generated @param tags: # @param [String] name Param documentation.
-
#initialize(raw = {}) ⇒ void
constructor
Create a configuration object from a raw config hash.
-
#load_plugins! ⇒ void
Load and register plugins declared under ‘plugins.require` in config.
-
#nil_as_optional? ⇒ Boolean
Whether unions involving nil should be rendered as optional types.
-
#param_documentation ⇒ String
Default generated parameter description text.
-
#param_tag_style ⇒ String
Param tag syntax style.
-
#process_file?(path) ⇒ Boolean
Decide whether a file path should be processed based on ‘filter.files`.
-
#process_method?(container:, scope:, visibility:, name:) ⇒ Boolean
Decide whether a method should be processed based on configured method filters.
-
#rbs_enabled? ⇒ Boolean
Whether RBS integration is enabled.
-
#rbs_provider ⇒ Docscribe::Types::RBS::Provider?
Return a memoized RBS provider if RBS integration is enabled and available.
-
#signature_provider_for(source:, file:) ⇒ Docscribe::Types::ProviderChain?
Build the effective external signature provider chain for a given source.
-
#sorbet_collapse_generics? ⇒ Boolean
Whether generic Sorbet/RBI container types should be simplified.
-
#sorbet_enabled? ⇒ Boolean
Whether Sorbet support is enabled in config.
-
#sorbet_rbi_dirs ⇒ Array<String>
RBI directories searched by the Sorbet provider.
-
#sorbet_rbi_provider ⇒ Docscribe::Types::Sorbet::RBIProvider?
Return a memoized Sorbet RBI provider if Sorbet integration is enabled.
-
#sort_tags? ⇒ Boolean
Whether sortable tag normalization is enabled for doc-like blocks.
-
#tag_order ⇒ Array<String>
Configured sortable tag order.
-
#treat_options_keyword_as_hash? ⇒ Boolean
Whether keyword arguments named ‘options` / `options:` should be treated specially as Hash values during inference.
Constructor Details
Instance Attribute Details
#raw ⇒ Object (readonly)
Raw config hash after deep-merging user config with defaults.
13 14 15 |
# File 'lib/docscribe/config.rb', line 13 def raw @raw end |
Class Method Details
.default_yaml ⇒ String
Return the default YAML template used by ‘docscribe init`.
The template documents the most common CLI workflows and all supported configuration sections with comments.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/docscribe/config/template.rb', line 12 def self.default_yaml <<~YAML --- # Docscribe configuration file # # Docscribe works without this file — create it only for customization. # # Quick start: # bundle exec docscribe lib # check what would change # bundle exec docscribe -a lib # apply safe updates # bundle exec docscribe -A lib # rebuild all doc blocks emit: # What to include in generated documentation header: false # +MyClass#foo+ -> ReturnType param_tags: true # @param tags return_tag: true # @return tag visibility_tags: true # @private / @protected raise_tags: true # @raise tags rescue_conditional_returns: true # @return [Type] if Error attributes: false # @!attribute for attr_* # Placeholder text for generated docs include_default_message: true # "Method documentation." include_param_documentation: true # "Param documentation." doc: # Default text and formatting default_message: "Method documentation." param_documentation: "Param documentation." param_tag_style: "type_name" # "type_name" or "name_type" sort_tags: true tag_order: ["todo", "note", "api", "private", "protected", "param", "option", "yieldparam", "raise", "return"] inference: # Type inference behavior fallback_type: "Object" # when uncertain nil_as_optional: true # String | nil => String? treat_options_keyword_as_hash: true # options: keyword => Hash filter: # Which methods and files to process # Method format: "Container#method" (instance) or "Container.method" (class) # Supports globs ("*#initialize") and regex ("/^MyApp::.*$/") include: [] exclude: [] visibilities: ["public", "protected", "private"] scopes: ["instance", "class"] files: # File paths relative to project root (globs or /regex/) include: [] exclude: ["spec"] methods: # Override defaults per scope and visibility. # Empty {} means "use values from `doc` section". # # Example: # instance: # public: # default_message: "Public API." # private: # return_tag: false instance: public: {} protected: {} private: {} class: public: {} protected: {} private: {} rbs: # Use RBS signatures for better types (requires `gem "rbs"`) enabled: false sig_dirs: ["sig"] collapse_generics: false # Hash<Symbol, String> => Hash collection: false # auto-discover from rbs_collection.lock.yaml sorbet: # Use Sorbet inline sigs and RBI files for better types enabled: false rbi_dirs: ["sorbet/rbi", "rbi"] collapse_generics: false plugins: # Load custom plugins # Example: # require: # - ./docscribe_plugins # - docscribe-rails-associations require: [] YAML end |
.load(path = nil) ⇒ Docscribe::Config
Load Docscribe configuration from YAML.
Resolution order:
-
explicit ‘path`, if it exists
-
‘docscribe.yml` in the current directory, if present
-
otherwise defaults only
14 15 16 17 18 19 20 21 22 |
# File 'lib/docscribe/config/loader.rb', line 14 def self.load(path = nil) raw = {} if path && File.file?(path) raw = safe_load_file_compat(path) elsif File.file?('docscribe.yml') raw = safe_load_file_compat('docscribe.yml') end new(raw) end |
.safe_load_compat(yaml, filename: nil) ⇒ Hash
Safely load YAML from a string across Psych API versions.
46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/docscribe/config/loader.rb', line 46 def self.safe_load_compat(yaml, filename: nil) Psych.safe_load( yaml, permitted_classes: [], permitted_symbols: [], aliases: true, filename: filename ) rescue ArgumentError # Older Psych signature uses positional args Psych.safe_load(yaml, [], [], true, filename) end |
.safe_load_file_compat(path) ⇒ Hash
Safely load YAML from a file across Ruby/Psych versions.
Uses ‘YAML.safe_load_file` when available, otherwise falls back to reading the file and calling safe_load_compat.
31 32 33 34 35 36 37 38 |
# File 'lib/docscribe/config/loader.rb', line 31 def self.safe_load_file_compat(path) if YAML.respond_to?(:safe_load_file) YAML.safe_load_file(path, permitted_classes: [], permitted_symbols: [], aliases: true) || {} else yaml = File.open(path, 'r:bom|utf-8', &:read) safe_load_compat(yaml, filename: path) || {} end end |
Instance Method Details
#core_rbs_provider ⇒ Object
Method documentation.
38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/docscribe/config/rbs.rb', line 38 def core_rbs_provider return nil unless ruby_supports_rbs? @core_rbs_provider ||= begin require 'docscribe/types/rbs/provider' Docscribe::Types::RBS::Provider.new( sig_dirs: [], collapse_generics: false ) rescue LoadError nil end end |
#default_message(scope, visibility) ⇒ String
Default text inserted into generated doc blocks, taking per-scope and per-visibility overrides into account.
70 71 72 73 74 75 76 77 78 79 |
# File 'lib/docscribe/config/emit.rb', line 70 def (scope, visibility) method_override_str( scope, visibility, 'default_message', default: raw.dig('doc', 'default_message') || DEFAULT.dig('doc', 'default_message') || 'Method documentation.' ) end |
#emit_attributes? ⇒ Boolean
Whether to emit YARD ‘@!attribute` docs for `attr_*` macros.
45 46 47 |
# File 'lib/docscribe/config/emit.rb', line 45 def emit_attributes? fetch_bool(%w[emit attributes], false) end |
#emit_header? ⇒ Boolean
Whether to emit method header lines such as:
# +MyClass#foo+ -> Integer
9 10 11 |
# File 'lib/docscribe/config/emit.rb', line 9 def emit_header? fetch_bool(%w[emit header], true) end |
#emit_param_tags? ⇒ Boolean
Whether to emit ‘@param` tags.
16 17 18 |
# File 'lib/docscribe/config/emit.rb', line 16 def fetch_bool(%w[emit param_tags], true) end |
#emit_raise_tags? ⇒ Boolean
Whether to emit inferred ‘@raise` tags.
30 31 32 |
# File 'lib/docscribe/config/emit.rb', line 30 def fetch_bool(%w[emit raise_tags], true) end |
#emit_rescue_conditional_returns? ⇒ Boolean
Whether to emit conditional rescue-return tags like:
# @return [String] if FooError
38 39 40 |
# File 'lib/docscribe/config/emit.rb', line 38 def emit_rescue_conditional_returns? fetch_bool(%w[emit rescue_conditional_returns], true) end |
#emit_return_tag?(scope, visibility) ⇒ Boolean
Whether to emit the ‘@return` tag for a method, taking per-scope and per-visibility overrides into account.
55 56 57 58 59 60 61 62 |
# File 'lib/docscribe/config/emit.rb', line 55 def emit_return_tag?(scope, visibility) method_override_bool( scope, visibility, 'return_tag', default: fetch_bool(%w[emit return_tag], true) ) end |
#emit_visibility_tags? ⇒ Boolean
Whether to emit visibility tags such as ‘@private` and `@protected`.
23 24 25 |
# File 'lib/docscribe/config/emit.rb', line 23 def fetch_bool(%w[emit visibility_tags], true) end |
#fallback_type ⇒ String
Fallback type used when inference cannot determine a more specific type.
84 85 86 87 88 |
# File 'lib/docscribe/config/emit.rb', line 84 def fallback_type raw.dig('inference', 'fallback_type') || DEFAULT.dig('inference', 'fallback_type') || 'Object' end |
#include_default_message? ⇒ Boolean
Whether to include the default placeholder line:
# Method documentation.
130 131 132 |
# File 'lib/docscribe/config/emit.rb', line 130 def fetch_bool(%w[emit include_default_message], true) end |
#include_param_documentation? ⇒ Boolean
Whether to append placeholder text to generated @param tags:
# @param [String] name Param documentation.
138 139 140 |
# File 'lib/docscribe/config/emit.rb', line 138 def include_param_documentation? fetch_bool(%w[emit include_param_documentation], true) end |
#load_plugins! ⇒ void
This method returns an undefined value.
Load and register plugins declared under ‘plugins.require` in config.
Each entry is expanded relative to the current working directory and passed to ‘require`. Registration is expected to happen inside the required file via Plugin::Registry.register.
Loading failures are non-fatal: a warning is printed and the run continues without the plugin.
16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/docscribe/config/plugin.rb', line 16 def load_plugins! paths = Array(raw.dig('plugins', 'require')).compact return if paths.empty? require 'docscribe/plugin' paths.each do |path| require File.(path) rescue LoadError => e warn "Docscribe: could not load plugin #{path.inspect}: #{e.}" end end |
#nil_as_optional? ⇒ Boolean
Whether unions involving nil should be rendered as optional types.
For example, ‘String, nil` may become `String?` depending on formatter behavior.
96 97 98 |
# File 'lib/docscribe/config/emit.rb', line 96 def nil_as_optional? fetch_bool(%w[inference nil_as_optional], true) end |
#param_documentation ⇒ String
Default generated parameter description text.
122 123 124 |
# File 'lib/docscribe/config/emit.rb', line 122 def param_documentation raw.dig('doc', 'param_documentation') || DEFAULT.dig('doc', 'param_documentation') end |
#param_tag_style ⇒ String
Param tag syntax style.
Supported values:
-
‘“type_name”` => `@param [String] name`
-
‘“name_type”` => `@param name [String]`
115 116 117 |
# File 'lib/docscribe/config/emit.rb', line 115 def param_tag_style raw.dig('doc', 'param_tag_style') || DEFAULT.dig('doc', 'param_tag_style') end |
#process_file?(path) ⇒ Boolean
Decide whether a file path should be processed based on ‘filter.files`.
File paths are matched relative to the current working directory when possible. Exclude rules win. If no include rules are configured, files are included by default.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/docscribe/config/filtering.rb', line 13 def process_file?(path) files = raw.dig('filter', 'files') || {} include_patterns = normalize_file_patterns(files['include']) exclude_patterns = normalize_file_patterns(files['exclude']) rel = begin Pathname.new(path)..relative_path_from(Pathname.pwd).cleanpath.to_s rescue StandardError path end return false if file_matches_any?(exclude_patterns, rel) return true if include_patterns.empty? file_matches_any?(include_patterns, rel) end |
#process_method?(container:, scope:, visibility:, name:) ⇒ Boolean
Decide whether a method should be processed based on configured method filters.
Method IDs are normalized as:
-
instance method => ‘MyModule::MyClass#foo`
-
class method => ‘MyModule::MyClass.foo`
Exclude rules win. If no include rules are configured, methods are included by default subject to scope and visibility allow-lists.
44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/docscribe/config/filtering.rb', line 44 def process_method?(container:, scope:, visibility:, name:) return false unless filter_scopes.include?(scope.to_s) return false unless filter_visibilities.include?(visibility.to_s) method_id = "#{container}#{scope == :instance ? '#' : '.'}#{name}" return false if matches_any?(filter_exclude_patterns, method_id) inc = filter_include_patterns return true if inc.empty? matches_any?(inc, method_id) end |
#rbs_enabled? ⇒ Boolean
Whether RBS integration is enabled.
30 31 32 |
# File 'lib/docscribe/config/rbs.rb', line 30 def rbs_enabled? fetch_bool(%w[rbs enabled], false) end |
#rbs_provider ⇒ Docscribe::Types::RBS::Provider?
Return a memoized RBS provider if RBS integration is enabled and available.
If RBS cannot be loaded, this returns nil and Docscribe falls back to inference.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/docscribe/config/rbs.rb', line 12 def rbs_provider return nil unless rbs_enabled? return nil unless ruby_supports_rbs? @rbs_provider ||= begin require 'docscribe/types/rbs/provider' Docscribe::Types::RBS::Provider.new( sig_dirs: rbs_sig_dirs, collapse_generics: rbs_collapse_generics? ) rescue LoadError nil end end |
#signature_provider_for(source:, file:) ⇒ Docscribe::Types::ProviderChain?
Build the effective external signature provider chain for a given source.
Provider precedence is:
-
inline Sorbet signatures from the current source
-
Sorbet RBI files
-
RBS files
Returns nil when no external type provider is enabled or available.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/docscribe/config/sorbet.rb', line 18 def signature_provider_for(source:, file:) providers = [] if sorbet_enabled? begin require 'docscribe/types/sorbet/source_provider' providers << Docscribe::Types::Sorbet::SourceProvider.new( source: source, file: file, collapse_generics: sorbet_collapse_generics? ) rescue LoadError # Sorbet support is optional; fall back quietly. end providers << sorbet_rbi_provider end providers << rbs_provider if rbs_enabled? providers = providers.compact return nil if providers.empty? require 'docscribe/types/provider_chain' Docscribe::Types::ProviderChain.new(*providers) end |
#sorbet_collapse_generics? ⇒ Boolean
Whether generic Sorbet/RBI container types should be simplified.
Falls back to the RBS ‘collapse_generics` setting when Sorbet-specific config is not present.
83 84 85 |
# File 'lib/docscribe/config/sorbet.rb', line 83 def sorbet_collapse_generics? fetch_bool(%w[sorbet collapse_generics], rbs_collapse_generics?) end |
#sorbet_enabled? ⇒ Boolean
Whether Sorbet support is enabled in config.
66 67 68 |
# File 'lib/docscribe/config/sorbet.rb', line 66 def sorbet_enabled? fetch_bool(%w[sorbet enabled], false) end |
#sorbet_rbi_dirs ⇒ Array<String>
RBI directories searched by the Sorbet provider.
73 74 75 |
# File 'lib/docscribe/config/sorbet.rb', line 73 def sorbet_rbi_dirs Array(raw.dig('sorbet', 'rbi_dirs') || DEFAULT.dig('sorbet', 'rbi_dirs')).map(&:to_s) end |
#sorbet_rbi_provider ⇒ Docscribe::Types::Sorbet::RBIProvider?
Return a memoized Sorbet RBI provider if Sorbet integration is enabled.
49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/docscribe/config/sorbet.rb', line 49 def sorbet_rbi_provider return nil unless sorbet_enabled? @sorbet_rbi_provider ||= begin require 'docscribe/types/sorbet/rbi_provider' Docscribe::Types::Sorbet::RBIProvider.new( rbi_dirs: sorbet_rbi_dirs, collapse_generics: sorbet_collapse_generics? ) rescue LoadError nil end end |
#sort_tags? ⇒ Boolean
Whether sortable tag normalization is enabled for doc-like blocks.
8 9 10 |
# File 'lib/docscribe/config/sorting.rb', line 8 def raw.dig('doc', 'sort_tags') != false end |
#tag_order ⇒ Array<String>
Configured sortable tag order.
Tags are normalized without a leading ‘@`.
17 18 19 20 21 |
# File 'lib/docscribe/config/sorting.rb', line 17 def tag_order Array(raw.dig('doc', 'tag_order') || DEFAULT.dig('doc', 'tag_order')).map do |t| t.to_s.sub(/\A@/, '') end end |
#treat_options_keyword_as_hash? ⇒ Boolean
Whether keyword arguments named ‘options` / `options:` should be treated specially as Hash values during inference.
104 105 106 |
# File 'lib/docscribe/config/emit.rb', line 104 def fetch_bool(%w[inference treat_options_keyword_as_hash], true) end |