Class: Rbs::Merge::FileAnalysis

Inherits:
Object
  • Object
show all
Includes:
Ast::Merge::FileAnalyzable
Defined in:
lib/rbs/merge/file_analysis.rb

Overview

File analysis for RBS type signature files. Parses RBS source code and extracts declarations, members, and freeze blocks.

This class provides the foundation for intelligent merging by:

  • Parsing RBS files using the official RBS parser

  • Extracting top-level declarations (classes, modules, interfaces, type aliases, constants)

  • Detecting freeze blocks marked with comment directives

  • Generating signatures for matching declarations between files

Examples:

Basic usage

analysis = FileAnalysis.new(rbs_source)
analysis.statements.each do |stmt|
  puts stmt.class
end

With custom freeze token

analysis = FileAnalysis.new(source, freeze_token: "my-merge")
# Looks for: # my-merge:freeze / # my-merge:unfreeze

Constant Summary collapse

DEFAULT_FREEZE_TOKEN =

Default freeze token for identifying freeze blocks

Returns:

  • (String)
"rbs-merge"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

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

Initialize file analysis with RBS parser

Parameters:

  • source (String)

    RBS source code to analyze

  • freeze_token (String) (defaults to: DEFAULT_FREEZE_TOKEN)

    Token for freeze block markers (default: “rbs-merge”)

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

    Custom signature generator

Raises:

  • (RBS::ParsingError)

    If the source has syntax errors



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/rbs/merge/file_analysis.rb', line 45

def initialize(source, freeze_token: DEFAULT_FREEZE_TOKEN, signature_generator: nil)
  @source = source
  @lines = source.split("\n", -1)
  @freeze_token = freeze_token
  @signature_generator = signature_generator

  # Parse the RBS source
  @buffer = RBS::Buffer.new(name: "merge.rbs", content: source)
  @buffer, @directives, @declarations = DebugLogger.time("FileAnalysis#parse") do
    RBS::Parser.parse_signature(@buffer)
  end

  # Extract and integrate all nodes including freeze blocks
  @statements = extract_and_integrate_all_nodes

  DebugLogger.debug("FileAnalysis initialized", {
    signature_generator: signature_generator ? "custom" : "default",
    directives_count: @directives.size,
    declarations_count: @declarations.size,
    statements_count: @statements.size,
    freeze_blocks: freeze_blocks.size,
  })
end

Instance Attribute Details

#bufferRBS::Buffer (readonly)

Returns The RBS buffer for this file.

Returns:

  • (RBS::Buffer)

    The RBS buffer for this file



31
32
33
# File 'lib/rbs/merge/file_analysis.rb', line 31

def buffer
  @buffer
end

#declarationsArray<RBS::AST::Declarations::Base> (readonly)

Returns Raw declarations from parser.

Returns:

  • (Array<RBS::AST::Declarations::Base>)

    Raw declarations from parser



37
38
39
# File 'lib/rbs/merge/file_analysis.rb', line 37

def declarations
  @declarations
end

#directivesArray<RBS::AST::Directives::Base> (readonly)

Returns RBS directives (use statements, etc.).

Returns:

  • (Array<RBS::AST::Directives::Base>)

    RBS directives (use statements, etc.)



34
35
36
# File 'lib/rbs/merge/file_analysis.rb', line 34

def directives
  @directives
end

#statementsArray<RBS::AST::Declarations::Base, FreezeNode> (readonly)

Get all statements (declarations outside freeze blocks + FreezeNodes)

Returns:

  • (Array<RBS::AST::Declarations::Base, FreezeNode>)


77
78
79
# File 'lib/rbs/merge/file_analysis.rb', line 77

def statements
  @statements
end

Instance Method Details

#compute_node_signature(node) ⇒ Array?

Compute default signature for a node

Parameters:

  • node (Object)

    The declaration or FreezeNode

Returns:

  • (Array, nil)

    Signature array



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/rbs/merge/file_analysis.rb', line 82

def compute_node_signature(node)
  case node
  when FreezeNode
    node.signature
  when RBS::AST::Declarations::Class
    [:class, node.name.to_s]
  when RBS::AST::Declarations::Module
    [:module, node.name.to_s]
  when RBS::AST::Declarations::Interface
    [:interface, node.name.to_s]
  when RBS::AST::Declarations::TypeAlias
    [:type_alias, node.name.to_s]
  when RBS::AST::Declarations::Constant
    [:constant, node.name.to_s]
  when RBS::AST::Declarations::Global
    [:global, node.name.to_s]
  when RBS::AST::Members::MethodDefinition
    [:method, node.name.to_s, node.kind]
  when RBS::AST::Members::Alias
    [:alias, node.new_name.to_s, node.old_name.to_s]
  when RBS::AST::Members::AttrReader
    [:attr_reader, node.name.to_s]
  when RBS::AST::Members::AttrWriter
    [:attr_writer, node.name.to_s]
  when RBS::AST::Members::AttrAccessor
    [:attr_accessor, node.name.to_s]
  when RBS::AST::Members::Include
    [:include, node.name.to_s]
  when RBS::AST::Members::Extend
    [:extend, node.name.to_s]
  when RBS::AST::Members::Prepend
    [:prepend, node.name.to_s]
  when RBS::AST::Members::InstanceVariable
    [:ivar, node.name.to_s]
  when RBS::AST::Members::ClassInstanceVariable
    [:civar, node.name.to_s]
  when RBS::AST::Members::ClassVariable
    [:cvar, node.name.to_s]
  else
    # Unknown node type - use class name and location as signature
    [:unknown, node.class.name, node.location&.start_line]
  end
end

#fallthrough_node?(value) ⇒ Boolean

Override to detect RBS nodes for signature generator fallthrough

Parameters:

  • value (Object)

    The value to check

Returns:

  • (Boolean)

    true if this is a fallthrough node



129
130
131
132
133
134
# File 'lib/rbs/merge/file_analysis.rb', line 129

def fallthrough_node?(value)
  value.is_a?(RBS::AST::Declarations::Base) ||
    value.is_a?(RBS::AST::Members::Base) ||
    value.is_a?(FreezeNode) ||
    super
end

#valid?Boolean

Check if parse was successful (RBS parser raises on failure, so always true if we get here)

Returns:

  • (Boolean)


71
72
73
# File 'lib/rbs/merge/file_analysis.rb', line 71

def valid?
  true
end