Class: Prism::Merge::FileAnalysis
- Inherits:
-
Object
- Object
- Prism::Merge::FileAnalysis
- 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
-
#freeze_token ⇒ String
readonly
Token used to mark freeze blocks.
-
#lines ⇒ Array<String>
readonly
Lines of source code.
-
#parse_result ⇒ Prism::ParseResult
readonly
The parse result from Prism.
-
#signature_generator ⇒ Proc?
readonly
Custom signature generator.
-
#source ⇒ String
readonly
Source code content.
-
#statements ⇒ Array<Prism::Node, FreezeNode>
readonly
Get all statements (code nodes outside freeze blocks + FreezeNodes).
Instance Method Summary collapse
-
#freeze_block_at(line_num) ⇒ FreezeNode?
Get the freeze block containing the given line, if any.
-
#freeze_blocks ⇒ Array<FreezeNode>
Get freeze blocks.
-
#generate_signature(node) ⇒ Array?
Generate signature for a node.
-
#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) ⇒ FileAnalysis
constructor
Initialize file analysis with Prism’s native comment handling.
-
#line_at(line_num) ⇒ String?
Get raw line content.
-
#nodes_with_comments ⇒ Array<Hash>
Get nodes with their associated comments and metadata Comments are now accessed via Prism’s native node.location API.
-
#normalized_line(line_num) ⇒ String?
Get normalized line content (stripped).
-
#signature_at(index) ⇒ Array?
Get structural signature for a statement at given index.
-
#valid? ⇒ Boolean
Check if parse was successful.
Constructor Details
#initialize(source, freeze_token: DEFAULT_FREEZE_TOKEN, signature_generator: nil) ⇒ FileAnalysis
Initialize file analysis with Prism’s native comment handling
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/prism/merge/file_analysis.rb', line 40 def initialize(source, freeze_token: DEFAULT_FREEZE_TOKEN, signature_generator: nil) @source = source @lines = source.lines @freeze_token = freeze_token @signature_generator = signature_generator @parse_result = 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, freeze_blocks: freeze_blocks.size, }) if defined?(DebugLogger) end |
Instance Attribute Details
#freeze_token ⇒ String (readonly)
Returns Token used to mark freeze blocks.
30 31 32 |
# File 'lib/prism/merge/file_analysis.rb', line 30 def freeze_token @freeze_token end |
#lines ⇒ Array<String> (readonly)
Returns Lines of source code.
27 28 29 |
# File 'lib/prism/merge/file_analysis.rb', line 27 def lines @lines end |
#parse_result ⇒ Prism::ParseResult (readonly)
Returns The parse result from Prism.
21 22 23 |
# File 'lib/prism/merge/file_analysis.rb', line 21 def parse_result @parse_result end |
#signature_generator ⇒ Proc? (readonly)
Returns Custom signature generator.
33 34 35 |
# File 'lib/prism/merge/file_analysis.rb', line 33 def signature_generator @signature_generator end |
#source ⇒ String (readonly)
Returns Source code content.
24 25 26 |
# File 'lib/prism/merge/file_analysis.rb', line 24 def source @source end |
#statements ⇒ Array<Prism::Node, FreezeNode> (readonly)
Get all statements (code nodes outside freeze blocks + FreezeNodes)
69 70 71 |
# File 'lib/prism/merge/file_analysis.rb', line 69 def statements @statements end |
Instance Method Details
#freeze_block_at(line_num) ⇒ FreezeNode?
Get the freeze block containing the given line, if any
147 148 149 |
# File 'lib/prism/merge/file_analysis.rb', line 147 def freeze_block_at(line_num) freeze_blocks.find { |freeze_node| freeze_node.location.cover?(line_num) } end |
#freeze_blocks ⇒ Array<FreezeNode>
Get freeze blocks
73 74 75 |
# File 'lib/prism/merge/file_analysis.rb', line 73 def freeze_blocks @statements.select { |node| node.is_a?(FreezeNode) } end |
#generate_signature(node) ⇒ Array?
Generate signature for a node.
If a custom signature_generator is provided, it is called first. The custom generator can return:
-
An array signature (e.g., ‘[:gem, “foo”]`) - used as the signature
-
‘nil` - the node gets no signature (won’t be matched by signature)
-
A ‘Prism::Node` or `FreezeNode` - falls through to default computation using the returned node. This allows the custom generator to optionally modify the node before default processing, or simply return the original node unchanged for fallthrough.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/prism/merge/file_analysis.rb', line 114 def generate_signature(node) result = if @signature_generator custom_result = @signature_generator.call(node) if custom_result.is_a?(Prism::Node) || custom_result.is_a?(FreezeNode) # Custom generator returned a node - use default computation on it compute_node_signature(custom_result) else # Custom result is either an array signature or nil custom_result end else compute_node_signature(node) end DebugLogger.debug("Generated signature", { node_type: node.class.name.split("::").last, signature: result, generator: @signature_generator ? "custom" : "default", }) if defined?(DebugLogger) && result result end |
#in_freeze_block?(line_num) ⇒ Boolean
Check if a line is within a freeze block
140 141 142 |
# File 'lib/prism/merge/file_analysis.rb', line 140 def in_freeze_block?(line_num) freeze_blocks.any? { |freeze_node| freeze_node.location.cover?(line_num) } end |
#line_at(line_num) ⇒ String?
Get raw line content
162 163 164 165 |
# File 'lib/prism/merge/file_analysis.rb', line 162 def line_at(line_num) return if line_num < 1 || line_num > lines.length lines[line_num - 1] 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
80 81 82 |
# File 'lib/prism/merge/file_analysis.rb', line 80 def nodes_with_comments @nodes_with_comments ||= extract_nodes_with_comments end |
#normalized_line(line_num) ⇒ String?
Get normalized line content (stripped)
154 155 156 157 |
# File 'lib/prism/merge/file_analysis.rb', line 154 def normalized_line(line_num) return if line_num < 1 || line_num > lines.length lines[line_num - 1].strip end |
#signature_at(index) ⇒ Array?
Get structural signature for a statement at given index
87 88 89 90 |
# File 'lib/prism/merge/file_analysis.rb', line 87 def signature_at(index) return if index < 0 || index >= statements.length generate_signature(statements[index]) end |
#valid? ⇒ Boolean
Check if parse was successful
63 64 65 |
# File 'lib/prism/merge/file_analysis.rb', line 63 def valid? @parse_result.success? end |