Class: Psych::Merge::FileAnalysis
- Inherits:
-
Object
- Object
- Psych::Merge::FileAnalysis
- Includes:
- Ast::Merge::FileAnalyzable
- Defined in:
- lib/psych/merge/file_analysis.rb
Overview
Analyzes YAML file structure, extracting statements, comments, and freeze blocks.
This is the main analysis class that prepares YAML content for merging.
Constant Summary collapse
- DEFAULT_FREEZE_TOKEN =
Default freeze token for identifying freeze blocks
"psych-merge"
Instance Attribute Summary collapse
-
#ast ⇒ Psych::Nodes::Stream?
readonly
Parsed AST.
-
#comment_tracker ⇒ CommentTracker
readonly
Comment tracker for this file.
-
#errors ⇒ Array
readonly
Parse errors if any.
-
#tree ⇒ TreeHaver::Backends::Psych::Tree?
readonly
TreeHaver tree (for future use).
Instance Method Summary collapse
-
#comment_attachment_for(owner, line_num: nil, **options) ⇒ Ast::Merge::Comment::Attachment
Build a passive shared comment attachment for an owner.
-
#comment_augmenter(owners: nil, **options) ⇒ Ast::Merge::Comment::Augmenter
Build a passive shared comment augmenter for this analysis.
-
#comment_capability ⇒ Ast::Merge::Comment::Capability
Get shared comment capability information for this analysis.
-
#comment_node_at(line_num) ⇒ Ast::Merge::Comment::Line?
Get a shared Ast::Merge comment node at a specific line.
-
#comment_nodes ⇒ Array<Ast::Merge::Comment::Line>
Get all comments converted to shared Ast::Merge comment nodes.
-
#comment_region_for_range(range, kind:, full_line_only: false) ⇒ Ast::Merge::Comment::Region
Get comments in a line range converted to a shared comment region.
-
#fallthrough_node?(value) ⇒ Boolean
Override to detect Psych nodes for signature generator fallthrough.
-
#freeze_block_at(line_num) ⇒ FreezeNode?
Get the freeze block containing the given line.
-
#in_freeze_block?(line_num) ⇒ Boolean
Check if a line is within a freeze block.
-
#initialize(source, freeze_token: DEFAULT_FREEZE_TOKEN, signature_generator: nil, **options) ⇒ FileAnalysis
constructor
Initialize file analysis.
-
#root_mapping_entries ⇒ Array<Array(NodeWrapper, NodeWrapper)>
Get mapping entries from the root document.
-
#root_node ⇒ NodeWrapper?
Get the root node of the first document.
-
#valid? ⇒ Boolean
Check if parse was successful.
Constructor Details
#initialize(source, freeze_token: DEFAULT_FREEZE_TOKEN, signature_generator: nil, **options) ⇒ FileAnalysis
Initialize file analysis
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 |
# File 'lib/psych/merge/file_analysis.rb', line 37 def initialize(source, freeze_token: DEFAULT_FREEZE_TOKEN, signature_generator: nil, **) @source = source @lines = source.lines.map(&:chomp) @freeze_token = freeze_token @signature_generator = signature_generator @errors = [] # **options captures any additional parameters (e.g., node_typing) for forward compatibility # Initialize comment tracking @comment_tracker = CommentTracker.new(source) # Parse the YAML DebugLogger.time("FileAnalysis#parse_yaml") { parse_yaml } # Extract freeze blocks and integrate with nodes @freeze_blocks = extract_freeze_blocks @statements = integrate_nodes_and_freeze_blocks DebugLogger.debug("FileAnalysis initialized", { signature_generator: signature_generator ? "custom" : "default", statements_count: @statements.size, freeze_blocks: @freeze_blocks.size, valid: valid?, }) end |
Instance Attribute Details
#ast ⇒ Psych::Nodes::Stream? (readonly)
Returns Parsed AST.
23 24 25 |
# File 'lib/psych/merge/file_analysis.rb', line 23 def ast @ast end |
#comment_tracker ⇒ CommentTracker (readonly)
Returns Comment tracker for this file.
20 21 22 |
# File 'lib/psych/merge/file_analysis.rb', line 20 def comment_tracker @comment_tracker end |
#errors ⇒ Array (readonly)
Returns Parse errors if any.
29 30 31 |
# File 'lib/psych/merge/file_analysis.rb', line 29 def errors @errors end |
#tree ⇒ TreeHaver::Backends::Psych::Tree? (readonly)
Returns TreeHaver tree (for future use).
26 27 28 |
# File 'lib/psych/merge/file_analysis.rb', line 26 def tree @tree end |
Instance Method Details
#comment_attachment_for(owner, line_num: nil, **options) ⇒ Ast::Merge::Comment::Attachment
Build a passive shared comment attachment for an owner.
189 190 191 |
# File 'lib/psych/merge/file_analysis.rb', line 189 def (owner, line_num: nil, **) @comment_tracker.(owner, line_num: line_num, **) end |
#comment_augmenter(owners: nil, **options) ⇒ Ast::Merge::Comment::Augmenter
Build a passive shared comment augmenter for this analysis.
110 111 112 113 114 115 |
# File 'lib/psych/merge/file_analysis.rb', line 110 def comment_augmenter(owners: nil, **) comment_tracker.augment( owners: owners || comment_augmenter_default_owners, **, ) end |
#comment_capability ⇒ Ast::Merge::Comment::Capability
Get shared comment capability information for this analysis.
72 73 74 |
# File 'lib/psych/merge/file_analysis.rb', line 72 def comment_capability @comment_capability ||= comment_tracker.augment(owners: []).capability end |
#comment_node_at(line_num) ⇒ Ast::Merge::Comment::Line?
Get a shared Ast::Merge comment node at a specific line.
87 88 89 |
# File 'lib/psych/merge/file_analysis.rb', line 87 def comment_node_at(line_num) comment_tracker.comment_node_at(line_num) end |
#comment_nodes ⇒ Array<Ast::Merge::Comment::Line>
Get all comments converted to shared Ast::Merge comment nodes.
79 80 81 |
# File 'lib/psych/merge/file_analysis.rb', line 79 def comment_nodes comment_tracker.comment_nodes end |
#comment_region_for_range(range, kind:, full_line_only: false) ⇒ Ast::Merge::Comment::Region
Get comments in a line range converted to a shared comment region.
97 98 99 100 101 102 103 |
# File 'lib/psych/merge/file_analysis.rb', line 97 def comment_region_for_range(range, kind:, full_line_only: false) comment_tracker.comment_region_for_range( range, kind: kind, full_line_only: full_line_only, ) end |
#fallthrough_node?(value) ⇒ Boolean
Override to detect Psych nodes for signature generator fallthrough
150 151 152 |
# File 'lib/psych/merge/file_analysis.rb', line 150 def fallthrough_node?(value) value.is_a?(NodeWrapper) || value.is_a?(Ast::Merge::FreezeNodeBase) || value.is_a?(MappingEntry) || super end |
#freeze_block_at(line_num) ⇒ FreezeNode?
Get the freeze block containing the given line.
NOTE: This method intentionally does NOT call super or use the base
freeze_blocks method. The base implementation derives freeze blocks from
statements.select { |n| n.is_a?(Freezable) }, but during initialization
@freeze_blocks is extracted BEFORE @statements is populated (see
integrate_nodes_and_freeze_blocks). This method is called during that
integration process, so we must use @freeze_blocks directly.
143 144 145 |
# File 'lib/psych/merge/file_analysis.rb', line 143 def freeze_block_at(line_num) @freeze_blocks.find { |fb| fb.location.cover?(line_num) } end |
#in_freeze_block?(line_num) ⇒ Boolean
Check if a line is within a freeze block.
NOTE: This method intentionally does NOT call super or use the base
freeze_blocks method. The base implementation derives freeze blocks from
statements.select { |n| n.is_a?(Freezable) }, but during initialization
@freeze_blocks is extracted BEFORE @statements is populated (see
integrate_nodes_and_freeze_blocks). This method is called during that
integration process, so we must use @freeze_blocks directly.
128 129 130 |
# File 'lib/psych/merge/file_analysis.rb', line 128 def in_freeze_block?(line_num) @freeze_blocks.any? { |fb| fb.location.cover?(line_num) } end |
#root_mapping_entries ⇒ Array<Array(NodeWrapper, NodeWrapper)>
Get mapping entries from the root document
156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/psych/merge/file_analysis.rb', line 156 def root_mapping_entries return [] unless valid? && @ast.children&.any? doc = @ast.children.first return [] unless doc.is_a?(::Psych::Nodes::Document) root = doc.children&.first return [] unless root.is_a?(::Psych::Nodes::Mapping) root_wrapper = wrap_root_node(root) root_wrapper.mapping_entries(comment_tracker: @comment_tracker) end |
#root_node ⇒ NodeWrapper?
Get the root node of the first document
171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/psych/merge/file_analysis.rb', line 171 def root_node return unless valid? && @ast.children&.any? doc = @ast.children.first return unless doc.is_a?(::Psych::Nodes::Document) root = doc.children&.first return unless root wrap_root_node(root) end |
#valid? ⇒ Boolean
Check if parse was successful
65 66 67 |
# File 'lib/psych/merge/file_analysis.rb', line 65 def valid? @errors.empty? && !@ast.nil? end |