Class: Prism::Merge::FileAnalysis
- Inherits:
-
Object
- Object
- Prism::Merge::FileAnalysis
- Includes:
- Ast::Merge::FileAnalyzable
- Defined in:
- lib/prism/merge/file_analysis.rb
Overview
Simplified file analysis using Prism’s native comment attachment.
This version leverages parse_result.attach_comments! to automatically
attach comments to nodes, eliminating the need for manual comment tracking
and the CommentNode class.
Key improvements over V1:
- Uses Prism’s native node.location.leading_comments and trailing_comments
- No manual comment tracking or CommentNode class
- Simpler freeze block extraction via comment scanning
- Better performance (one attach_comments! call vs multiple iterations)
- Enhanced freeze block validation (detects partial nodes and non-class/module contexts)
Constant Summary collapse
- DEFAULT_FREEZE_TOKEN =
Default freeze token for identifying freeze blocks
"prism-merge"
Instance Attribute Summary collapse
-
#parse_result ⇒ Prism::ParseResult
readonly
The parse result from Prism.
Class Method Summary collapse
-
.attach_comments_safely!(parse_result) ⇒ void
Safely attach comments to nodes, handling JRuby compatibility issues.
Instance Method Summary collapse
-
#errors ⇒ Array<Prism::ParseError>
Get parse errors for compatibility with SmartMergerBase.
-
#fallthrough_node?(value) ⇒ Boolean
Override to detect Prism nodes for signature generator fallthrough.
-
#frozen_node?(node) ⇒ Boolean
Determine if a node is frozen (has a freeze marker in its leading comments).
-
#frozen_nodes ⇒ Array<Ast::Merge::NodeTyping::FrozenWrapper>
Get nodes that are frozen (have a freeze marker).
-
#initialize(source, freeze_token: DEFAULT_FREEZE_TOKEN, signature_generator: nil, **options) ⇒ FileAnalysis
constructor
Initialize file analysis with Prism’s native comment handling.
-
#nodes_with_comments ⇒ Array<Hash>
Get nodes with their associated comments and metadata Comments are now accessed via Prism’s native node.location API.
-
#valid? ⇒ Boolean
Check if parse was successful.
Constructor Details
#initialize(source, freeze_token: DEFAULT_FREEZE_TOKEN, signature_generator: nil, **options) ⇒ FileAnalysis
Initialize file analysis with Prism’s native comment handling
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/prism/merge/file_analysis.rb', line 33 def initialize(source, freeze_token: DEFAULT_FREEZE_TOKEN, signature_generator: nil, **) @source = source @lines = source.lines @freeze_token = freeze_token @signature_generator = signature_generator # **options captured for forward compatibility @parse_result = DebugLogger.time("FileAnalysis#parse") { Prism.parse(source) } # Use Prism's native comment attachment # On JRuby, the Comments class may not be loaded yet, so we need to require it attach_comments_safely! # Extract and validate structure @statements = extract_and_integrate_all_nodes DebugLogger.debug("FileAnalysis initialized", { signature_generator: signature_generator ? "custom" : "default", statements_count: @statements.size, frozen_nodes_count: frozen_nodes.size, }) end |
Instance Attribute Details
#parse_result ⇒ Prism::ParseResult (readonly)
Returns The parse result from Prism.
25 26 27 |
# File 'lib/prism/merge/file_analysis.rb', line 25 def parse_result @parse_result end |
Class Method Details
.attach_comments_safely!(parse_result) ⇒ void
This method returns an undefined value.
Safely attach comments to nodes, handling JRuby compatibility issues.
On JRuby, the Prism::ParseResult::Comments class may not be autoloaded,
so we need to explicitly require it.
This is a class method so it can be used anywhere in prism-merge code
that needs to attach comments to a parse result.
136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/prism/merge/file_analysis.rb', line 136 def attach_comments_safely!(parse_result) parse_result.attach_comments! # :nocov: defensive - JRuby compatibility for Comments class autoloading rescue NameError => e if e..include?("Comments") # On JRuby, the Comments class needs to be explicitly required require "prism/parse_result/comments" parse_result.attach_comments! else raise end # :nocov: end |
Instance Method Details
#errors ⇒ Array<Prism::ParseError>
Get parse errors for compatibility with SmartMergerBase.
63 64 65 |
# File 'lib/prism/merge/file_analysis.rb', line 63 def errors @parse_result.errors end |
#fallthrough_node?(value) ⇒ Boolean
Override to detect Prism nodes for signature generator fallthrough
77 78 79 |
# File 'lib/prism/merge/file_analysis.rb', line 77 def fallthrough_node?(value) value.is_a?(::Prism::Node) || super end |
#frozen_node?(node) ⇒ Boolean
Determine if a node is frozen (has a freeze marker in its leading comments).
For Ruby AST nodes, a freeze marker applies only to the node it directly
precedes in leading comments. If a freeze marker appears INSIDE a block
(nested in the body), it applies to that nested statement, NOT the outer
block. This is different from comment-only formats like Markdown where
checking content containment makes sense.
Nested freeze markers inside the node’s body are handled during recursive
body merging, where each nested statement gets its own freeze detection.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/prism/merge/file_analysis.rb', line 94 def frozen_node?(node) # Already wrapped as frozen return true if node.is_a?(Ast::Merge::Freezable) return false unless @freeze_token # Get the actual node (in case it's a Wrapper) actual_node = node.respond_to?(:unwrap) ? node.unwrap : node freeze_pattern = /#{Regexp.escape(@freeze_token)}:freeze/i # Check for freeze marker in leading comments ONLY if actual_node.respond_to?(:location) && actual_node.location.respond_to?(:leading_comments) return true if actual_node.location.leading_comments.any? { |c| c.slice.match?(freeze_pattern) } end false end |
#frozen_nodes ⇒ Array<Ast::Merge::NodeTyping::FrozenWrapper>
Get nodes that are frozen (have a freeze marker).
Returns FrozenWrapper instances that include the Freezable behavior,
allowing them to satisfy both is_a?(Freezable) and is_a?(NodeTyping::Wrapper).
118 119 120 121 122 123 124 |
# File 'lib/prism/merge/file_analysis.rb', line 118 def frozen_nodes # Return the underlying Prism nodes for tests and callers that expect # Prism node types. Statements may be wrapped in FrozenWrapper; unwrap # them here. statements.select { |node| node.is_a?(Ast::Merge::Freezable) } .map { |node| node.respond_to?(:unwrap) ? node.unwrap : node } end |
#nodes_with_comments ⇒ Array<Hash>
Get nodes with their associated comments and metadata
Comments are now accessed via Prism’s native node.location API
70 71 72 |
# File 'lib/prism/merge/file_analysis.rb', line 70 def nodes_with_comments @nodes_with_comments ||= extract_nodes_with_comments end |
#valid? ⇒ Boolean
Check if parse was successful
57 58 59 |
# File 'lib/prism/merge/file_analysis.rb', line 57 def valid? @parse_result.success? end |