Module: Ast::Merge::SectionTyping
- Defined in:
- lib/ast/merge/section_typing.rb
Overview
AST-aware section typing for identifying logical sections within parsed trees.
Unlike text-based splitting (see ‘Ast::Merge::Text::SectionSplitter`), SectionTyping works with already-parsed AST nodes where the parser has already identified structural boundaries. This eliminates the need for regex pattern matching.
## Use Cases
-
Identifying ‘appraise` blocks in Appraisals files
-
Identifying ‘group` blocks in Gemfiles
-
Identifying method definitions in Ruby files
-
Any case where the AST parser provides structural information
## How It Works
-
Classifier: A callable that inspects an AST node and returns section info
-
**Typed Node**: The node wrapped with its section classification
-
**Merge Logic**: Section-aware merging based on classifications
Defined Under Namespace
Classes: CallableClassifier, Classifier, CompositeClassifier, TypedSection
Class Method Summary collapse
-
.merge_sections(template_sections, dest_sections, preference: :destination, add_template_only: false) ⇒ Array<TypedSection>
Merge typed sections from template and destination.
-
.preference_for(section_name, preference) ⇒ Symbol
Get preference for a specific section.
Class Method Details
.merge_sections(template_sections, dest_sections, preference: :destination, add_template_only: false) ⇒ Array<TypedSection>
Merge typed sections from template and destination.
Similar to ‘Text::SectionSplitter#merge_section_lists` but works with TypedSection objects wrapping AST nodes.
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/ast/merge/section_typing.rb', line 245 def self.merge_sections(template_sections, dest_sections, preference: :destination, add_template_only: false) dest_by_name = dest_sections.each_with_object({}) do |section, hash| key = section.normalized_name hash[key] = section unless section.unclassified? end merged = [] seen_names = Set.new template_sections.each do |template_section| if template_section.unclassified? # Unclassified sections are typically kept as-is or merged specially merged << template_section if add_template_only next end key = template_section.normalized_name seen_names << key dest_section = dest_by_name[key] if dest_section # Section exists in both - choose based on preference section_pref = preference_for(template_section.name, preference) merged << ((section_pref == :template) ? template_section : dest_section) elsif add_template_only merged << template_section end end # Append destination-only sections dest_sections.each do |dest_section| next if dest_section.unclassified? key = dest_section.normalized_name next if seen_names.include?(key) merged << dest_section end merged end |
.preference_for(section_name, preference) ⇒ Symbol
Get preference for a specific section.
291 292 293 294 295 296 297 298 299 300 |
# File 'lib/ast/merge/section_typing.rb', line 291 def self.preference_for(section_name, preference) return preference unless preference.is_a?(Hash) normalized = section_name.to_s.strip.downcase preference.each do |key, value| return value if key.to_s.strip.downcase == normalized end preference.fetch(:default, :destination) end |