Class: Rigor::Plugin::ProtocolContract
- Inherits:
-
Object
- Object
- Rigor::Plugin::ProtocolContract
- Defined in:
- lib/rigor/plugin/protocol_contract.rb
Overview
ADR-28 declaration: “every instance/singleton method named ‘method_name`, defined in a source file matching `path_glob`, is implicitly required to satisfy the declared parameter + return-type protocol.”
Authored on a plugin manifest:
manifest(
id: "web",
version: "0.1.0",
protocol_contracts: [
Rigor::Plugin::ProtocolContract.new(
path_glob: "lib/controller/**/*.rb",
method_name: :get,
param_types: [{ index: 0, type_name: "Rack::Request" }],
return_type_name: "Rack::Response"
)
]
)
The contract drives two distinct engine behaviours (ADR-28 § “provide-and-check”):
-
provide — when the inference engine binds the parameter list of a matching ‘def`, Inference::MethodParameterBinder substitutes the declared `param_types` for the usual `Dynamic` fallback, so the method body is analysed as if the parameter carried its protocol type.
-
check — the contributing plugin’s ‘#diagnostics_for_file` hook confirms the method exists and its inferred return type conforms to `return_type_name`.
## Fields
-
‘path_glob` — `File.fnmatch` glob (String) selecting the source files the contract applies to, relative to the analysed project root (e.g. `“lib/controller/*/.rb”`).
-
‘method_name` — Symbol; the instance (or singleton) method the contract constrains.
-
‘singleton` — Boolean; `true` constrains `def self.<name>`, `false` (default) constrains instance methods.
-
‘param_types` — Array of `ParamType` (positional index →fully-qualified type name). The type names resolve against the analysed project’s environment lazily, at consumption time, so the contract value object stays independent of environment construction order.
-
‘return_type_name` — fully-qualified type name (String) the method’s inferred return type must conform to.
-
‘severity` — Symbol diagnostic severity for contract violations (`:error` default).
## Ractor-shareability
Every field is frozen at construction (ADR-15 Phase 1); the nested ‘ParamType` is a frozen `Data`. `Ractor.shareable?` returns true after `#initialize`, so the contract survives `Plugin::Registry.materialize` into a worker Ractor.
Defined Under Namespace
Classes: ParamType
Constant Summary collapse
- VALID_SEVERITIES =
%i[error warning info].freeze
Instance Attribute Summary collapse
-
#method_name ⇒ Object
readonly
Returns the value of attribute method_name.
-
#param_types ⇒ Object
readonly
Returns the value of attribute param_types.
-
#path_glob ⇒ Object
readonly
Returns the value of attribute path_glob.
-
#return_type_name ⇒ Object
readonly
Returns the value of attribute return_type_name.
-
#severity ⇒ Object
readonly
Returns the value of attribute severity.
-
#singleton ⇒ Object
readonly
Returns the value of attribute singleton.
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
- #hash ⇒ Object
-
#initialize(path_glob:, method_name:, return_type_name: nil, param_types: [], singleton: false, severity: :error) ⇒ ProtocolContract
constructor
A new instance of ProtocolContract.
- #to_h ⇒ Object
-
#with_path_glob(glob) ⇒ Object
Returns a copy with ‘path_glob` replaced.
Constructor Details
#initialize(path_glob:, method_name:, return_type_name: nil, param_types: [], singleton: false, severity: :error) ⇒ ProtocolContract
Returns a new instance of ProtocolContract.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/rigor/plugin/protocol_contract.rb', line 72 def initialize(path_glob:, method_name:, return_type_name: nil, param_types: [], singleton: false, severity: :error) validate_path_glob!(path_glob) validate_method_name!(method_name) validate_return_type_name!(return_type_name) validate_severity!(severity) @path_glob = path_glob.dup.freeze @method_name = method_name.to_sym @singleton = singleton ? true : false @param_types = coerce_param_types(param_types) @return_type_name = return_type_name.nil? ? nil : return_type_name.dup.freeze @severity = severity.to_sym freeze end |
Instance Attribute Details
#method_name ⇒ Object (readonly)
Returns the value of attribute method_name.
70 71 72 |
# File 'lib/rigor/plugin/protocol_contract.rb', line 70 def method_name @method_name end |
#param_types ⇒ Object (readonly)
Returns the value of attribute param_types.
70 71 72 |
# File 'lib/rigor/plugin/protocol_contract.rb', line 70 def param_types @param_types end |
#path_glob ⇒ Object (readonly)
Returns the value of attribute path_glob.
70 71 72 |
# File 'lib/rigor/plugin/protocol_contract.rb', line 70 def path_glob @path_glob end |
#return_type_name ⇒ Object (readonly)
Returns the value of attribute return_type_name.
70 71 72 |
# File 'lib/rigor/plugin/protocol_contract.rb', line 70 def return_type_name @return_type_name end |
#severity ⇒ Object (readonly)
Returns the value of attribute severity.
70 71 72 |
# File 'lib/rigor/plugin/protocol_contract.rb', line 70 def severity @severity end |
#singleton ⇒ Object (readonly)
Returns the value of attribute singleton.
70 71 72 |
# File 'lib/rigor/plugin/protocol_contract.rb', line 70 def singleton @singleton end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
113 114 115 |
# File 'lib/rigor/plugin/protocol_contract.rb', line 113 def ==(other) other.is_a?(ProtocolContract) && to_h == other.to_h end |
#hash ⇒ Object
118 119 120 |
# File 'lib/rigor/plugin/protocol_contract.rb', line 118 def hash to_h.hash end |
#to_h ⇒ Object
102 103 104 105 106 107 108 109 110 111 |
# File 'lib/rigor/plugin/protocol_contract.rb', line 102 def to_h { "path_glob" => path_glob, "method_name" => method_name.to_s, "singleton" => singleton, "param_types" => param_types.map { |pt| { "index" => pt.index, "type_name" => pt.type_name } }, "return_type_name" => return_type_name, "severity" => severity.to_s } end |
#with_path_glob(glob) ⇒ Object
Returns a copy with ‘path_glob` replaced. Plugins use this to honour a per-project config override of the convention path without rebuilding the whole contract by hand.
91 92 93 94 95 96 97 98 99 100 |
# File 'lib/rigor/plugin/protocol_contract.rb', line 91 def with_path_glob(glob) ProtocolContract.new( path_glob: glob, method_name: method_name, return_type_name: return_type_name, param_types: param_types.map { |pt| { index: pt.index, type_name: pt.type_name } }, singleton: singleton, severity: severity ) end |