Module: Ast::Merge::NodeTyping
- Defined in:
- lib/ast/merge/node_typing.rb,
lib/ast/merge/node_typing/wrapper.rb,
lib/ast/merge/node_typing/normalizer.rb,
lib/ast/merge/node_typing/frozen_wrapper.rb
Overview
Provides node type wrapping support for SmartMerger implementations.
NodeTyping allows custom callable objects to be associated with specific
node types. When a node is processed, the corresponding callable can:
- Return the node unchanged (passthrough)
- Return a modified node with a custom
merge_typeattribute - Return nil to indicate the node should be skipped
The merge_type attribute can then be used by other merge tools like
signature_generator, match_refiner, and per-node-type preference settings.
Important: Two Uses of merge_type
The merge_type method serves two complementary purposes in the codebase:
1. NodeTyping-specific (gated by typed_node?)
Wrapped nodes (Wrapper/FrozenWrapper) with custom type tagging for:
- Per-node-type preferences (e.g.,
:lint_gem→:template) - Match refinement based on custom categories
- Only applies when
typed_node?returns true - Accessed via
NodeTyping.merge_type_for(node)
2. General node classification (any node)
Any node can implement merge_type for category identification:
- FreezeNodeBase has
merge_type→:freeze_block - GapLineNode has
merge_type→:gap_line - Used by systems like MarkdownStructure for structural spacing rules
- These nodes are NOT “typed nodes” (typed_node? returns false)
The key distinction: typed_node? is the gate for NodeTyping wrapper
semantics. A node can have merge_type without being a NodeTyping wrapper.
Defined Under Namespace
Modules: Normalizer Classes: FrozenWrapper, Wrapper
Class Method Summary collapse
-
.frozen(node, merge_type = :frozen) ⇒ FrozenWrapper
Wrap a node as frozen with the Freezable behavior.
-
.frozen_node?(node) ⇒ Boolean
Check if a node is a frozen wrapper.
-
.merge_type_for(node) ⇒ Symbol?
Get the merge_type from a node, returning nil if it’s not a typed node.
-
.process(node, typing_config) ⇒ Object?
Process a node through a typing configuration.
-
.typed_node?(node) ⇒ Boolean
Check if a node is a node type wrapper.
-
.unwrap(node) ⇒ Object
Unwrap a typed node to get the original node.
-
.validate!(typing_config) ⇒ void
Validate a typing configuration hash.
-
.with_merge_type(node, merge_type) ⇒ Wrapper
Wrap a node with a custom merge_type.
Class Method Details
.frozen(node, merge_type = :frozen) ⇒ FrozenWrapper
Wrap a node as frozen with the Freezable behavior.
99 100 101 |
# File 'lib/ast/merge/node_typing.rb', line 99 def frozen(node, merge_type = :frozen) FrozenWrapper.new(node, merge_type) end |
.frozen_node?(node) ⇒ Boolean
Check if a node is a frozen wrapper.
107 108 109 |
# File 'lib/ast/merge/node_typing.rb', line 107 def frozen_node?(node) node.is_a?(Freezable) end |
.merge_type_for(node) ⇒ Symbol?
Get the merge_type from a node, returning nil if it’s not a typed node.
123 124 125 |
# File 'lib/ast/merge/node_typing.rb', line 123 def merge_type_for(node) typed_node?(node) ? node.merge_type : nil end |
.process(node, typing_config) ⇒ Object?
Process a node through a typing configuration.
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/ast/merge/node_typing.rb', line 152 def process(node, typing_config) return node unless typing_config return node if typing_config.empty? # Get the node type name for lookup type_key = node_type_key(node) # Try to find a matching typing callable callable = find_typing_callable(typing_config, type_key, node) return node unless callable # Call the typing callable with the node. # NOTE: For TreeHaver-based backends, the node already has a unified API # with #text, #type, #source_position methods. For other backends, they # must conform to the same API (either via TreeHaver or equivalent adapter). callable.call(node) end |
.typed_node?(node) ⇒ Boolean
Check if a node is a node type wrapper.
115 116 117 |
# File 'lib/ast/merge/node_typing.rb', line 115 def typed_node?(node) node.respond_to?(:typed_node?) && node.typed_node? end |
.unwrap(node) ⇒ Object
Unwrap a typed node to get the original node.
Returns the node unchanged if it’s not wrapped.
132 133 134 |
# File 'lib/ast/merge/node_typing.rb', line 132 def unwrap(node) typed_node?(node) ? node.unwrap : node end |
.validate!(typing_config) ⇒ void
This method returns an undefined value.
Validate a typing configuration hash.
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/ast/merge/node_typing.rb', line 175 def validate!(typing_config) return if typing_config.nil? unless typing_config.is_a?(Hash) raise ArgumentError, "node_typing must be a Hash, got #{typing_config.class}" end typing_config.each do |key, value| unless key.is_a?(Symbol) || key.is_a?(String) raise ArgumentError, "node_typing keys must be Symbol or String, got #{key.class} for #{key.inspect}" end unless value.respond_to?(:call) raise ArgumentError, "node_typing values must be callable (respond to #call), " \ "got #{value.class} for key #{key.inspect}" end end end |