Class: Ast::Merge::Text::FileAnalysis

Inherits:
Object
  • Object
show all
Includes:
FileAnalyzable
Defined in:
lib/ast/merge/text/file_analysis.rb

Overview

Text file analysis class for the text-based AST.

This class parses plain text files into a simple AST structure where:

  • Top-level nodes are LineNodes (one per line)
  • Nested nodes are WordNodes (words within each line, split on word boundaries)

This provides a minimal AST implementation that can be used to test the merge infrastructure with any text-based content.

Examples:

Basic usage

analysis = FileAnalysis.new("Hello world\nGoodbye world")
analysis.statements.size  # => 2
analysis.statements[0].words.size  # => 2

With freeze blocks

content = <<~TEXT
  Line one
  # text-merge:freeze
  Frozen content
  # text-merge:unfreeze
  Line four
TEXT
analysis = FileAnalysis.new(content, freeze_token: "text-merge")
analysis.freeze_blocks.size  # => 1

Constant Summary collapse

DEFAULT_FREEZE_TOKEN =

Default freeze token for text files

'text-merge'

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from FileAnalyzable

#comment_attachment_for, #comment_attachment_strategy, #comment_augmenter, #comment_capability, #comment_node_at, #comment_nodes, #comment_region_for_range, #comment_support_style, #feature_profile, #freeze_block_at, #freeze_blocks, #generate_signature, #in_freeze_block?, included, #layout_attachment_for, #layout_augmenter, #layout_owner_supported?, #line_at, #merge_augmented_comment_attachment_with_layout, #merge_comment_attachment_with_layout, #normalize_layout_owned_comment_attachment, #normalize_tracked_comment_attachment_with_layout, #normalized_line, #owner_leading_comment_freeze?, #owner_leading_comment_unfreeze?, #ruleset_attachment_strategy, #ruleset_capabilities, #ruleset_comment_style, #ruleset_delegation_policies, #ruleset_logical_owners, #ruleset_match_key, #ruleset_owner_selector, #ruleset_read_strategy, #ruleset_render_family, #ruleset_repair_policies, #ruleset_surfaces, #shared_comment_attachment_for, #shared_comment_support_style, #signature_at

Constructor Details

#initialize(source, freeze_token: DEFAULT_FREEZE_TOKEN, signature_generator: nil) ⇒ FileAnalysis

Initialize a new FileAnalysis

Parameters:

  • source (String)

    Source text content

  • freeze_token (String) (defaults to: DEFAULT_FREEZE_TOKEN)

    Token for freeze block markers

  • signature_generator (Proc, nil) (defaults to: nil)

    Custom signature generator



41
42
43
44
45
46
47
48
49
# File 'lib/ast/merge/text/file_analysis.rb', line 41

def initialize(source, freeze_token: DEFAULT_FREEZE_TOKEN, signature_generator: nil)
  @source = source
  # Split preserving empty lines, but remove trailing empty line from final newline
  @lines = source.split("\n", -1)
  @lines.pop if @lines.last&.empty? && source.end_with?("\n")
  @freeze_token = freeze_token
  @signature_generator = signature_generator
  @statements = parse_statements
end

Instance Attribute Details

#statementsArray<LineNode, FreezeNodeBase> (readonly)

Get all top-level statements (LineNodes and FreezeNodes)

Returns:



54
55
56
# File 'lib/ast/merge/text/file_analysis.rb', line 54

def statements
  @statements
end

Instance Method Details

#compute_node_signature(node) ⇒ Array?

Compute signature for a node

Parameters:

  • node (Object)

    Node to compute signature for

Returns:

  • (Array, nil)

    Signature array or nil



60
61
62
63
64
65
66
67
# File 'lib/ast/merge/text/file_analysis.rb', line 60

def compute_node_signature(node)
  case node
  when LineNode
    node.signature
  when FreezeNodeBase
    [:freeze_block, node.start_line, node.end_line]
  end
end

#fallthrough_node?(value) ⇒ Boolean

Check if a value is a fallthrough node

Parameters:

  • value (Object)

    Value to check

Returns:

  • (Boolean)

    True if fallthrough node



73
74
75
# File 'lib/ast/merge/text/file_analysis.rb', line 73

def fallthrough_node?(value)
  value.is_a?(LineNode) || value.is_a?(FreezeNodeBase) || super
end

#searchable_text(nodes: nil) ⇒ String

Build a whitespace-normalized, searchable string from a set of line nodes.

Joins each line's normalized content with a single space, collapsing all internal whitespace. This allows phrase-based content matching (e.g. MIT license detection) regardless of where the author chose to break lines.

Examples:

Detect MIT license regardless of line breaks

analysis = FileAnalysis.new(license_text)
analysis.searchable_text.downcase.include?("permission is hereby granted")

Parameters:

  • nodes (Array<LineNode>, nil) (defaults to: nil)

    Subset of nodes to search. Defaults to all statements when nil.

Returns:

  • (String)

    Single-space-joined, stripped, whitespace-collapsed string



90
91
92
93
94
95
96
97
98
99
# File 'lib/ast/merge/text/file_analysis.rb', line 90

def searchable_text(nodes: nil)
  source_nodes = nodes || @statements
  source_nodes
    .select { |n| n.is_a?(LineNode) }
    .map(&:normalized_content)
    .reject(&:empty?)
    .join(' ')
    .gsub(/\s+/, ' ')
    .strip
end