Skip to content

Commit

Permalink
Model: Handle property visibility
Browse files Browse the repository at this point in the history
Signed-off-by: Alexandre Terrasa <[email protected]>
  • Loading branch information
Morriar committed Jun 18, 2024
1 parent 0ee72b9 commit 24e0695
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 2 deletions.
22 changes: 22 additions & 0 deletions lib/spoom/model/builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def initialize(model, file)
@model = model
@file = file
@namespace_nesting = T.let([], T::Array[Namespace])
@visibility_stack = T.let([Visibility::Public], T::Array[Visibility])
@last_sigs = T.let([], T::Array[Sig])
end

Expand All @@ -26,7 +27,9 @@ def visit_class_node(node)
location: node_location(node),
superclass_name: node.superclass&.slice,
)
@visibility_stack << Visibility::Public
super
@visibility_stack.pop
@namespace_nesting.pop
@last_sigs.clear
end
Expand All @@ -38,7 +41,9 @@ def visit_singleton_class_node(node)
owner: @namespace_nesting.last,
location: node_location(node),
)
@visibility_stack << Visibility::Public
super
@visibility_stack.pop
@namespace_nesting.pop
@last_sigs.clear
end
Expand All @@ -52,7 +57,9 @@ def visit_module_node(node)
owner: @namespace_nesting.last,
location: node_location(node),
)
@visibility_stack << Visibility::Public
super
@visibility_stack.pop
@namespace_nesting.pop
@last_sigs.clear
end
Expand Down Expand Up @@ -124,6 +131,7 @@ def visit_def_node(node)
@model.register_symbol([*names_nesting, node.name.to_s].join("::")),
owner: @namespace_nesting.last,
location: node_location(node),
visibility: current_visibility,
sigs: collect_sigs,
)
end
Expand All @@ -149,6 +157,7 @@ def visit_call_node(node)
@model.register_symbol([*names_nesting, arg.slice.delete_prefix(":")].join("::")),
owner: current_namespace,
location: node_location(arg),
visibility: current_visibility,
sigs: sigs,
)
end
Expand All @@ -161,6 +170,7 @@ def visit_call_node(node)
@model.register_symbol([*names_nesting, arg.slice.delete_prefix(":")].join("::")),
owner: current_namespace,
location: node_location(arg),
visibility: current_visibility,
sigs: sigs,
)
end
Expand All @@ -173,6 +183,7 @@ def visit_call_node(node)
@model.register_symbol([*names_nesting, arg.slice.delete_prefix(":")].join("::")),
owner: current_namespace,
location: node_location(arg),
visibility: current_visibility,
sigs: sigs,
)
end
Expand All @@ -197,6 +208,12 @@ def visit_call_node(node)

current_namespace.mixins << Extend.new(arg.slice)
end
when :public, :private, :protected
@visibility_stack << Visibility.from_serialized(node.name.to_s)
if node.arguments
super
@visibility_stack.pop
end
when :sig
@last_sigs << Sig.new(node.slice)
else
Expand All @@ -207,6 +224,11 @@ def visit_call_node(node)

private

sig { returns(Visibility) }
def current_visibility
T.must(@visibility_stack.last)
end

sig { returns(T::Array[Sig]) }
def collect_sigs
sigs = @last_sigs
Expand Down
24 changes: 22 additions & 2 deletions lib/spoom/model/model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,25 @@ def initialize(symbol, owner:, location:, value:)
class Property < SymbolDef
abstract!

sig { returns(Visibility) }
attr_reader :visibility

sig { returns(T::Array[Sig]) }
attr_reader :sigs

sig { params(symbol: Symbol, owner: T.nilable(Namespace), location: Location, sigs: T::Array[Sig]).void }
def initialize(symbol, owner:, location:, sigs: [])
sig do
params(
symbol: Symbol,
owner: T.nilable(Namespace),
location: Location,
visibility: Visibility,
sigs: T::Array[Sig],
).void
end
def initialize(symbol, owner:, location:, visibility:, sigs: [])
super(symbol, owner: owner, location: location)

@visibility = visibility
@sigs = sigs
end
end
Expand All @@ -165,6 +177,14 @@ class AttrReader < Attr; end
class AttrWriter < Attr; end
class AttrAccessor < Attr; end

class Visibility < T::Enum
enums do
Public = new("public")
Protected = new("protected")
Private = new("private")
end
end

# A mixin (include, prepend, extend) to a namespace
class Mixin
extend T::Sig
Expand Down
85 changes: 85 additions & 0 deletions test/spoom/model/builder_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,91 @@ def p3; end
)
end

def test_visibility
model = model(<<~RB)
def m1; end
private
def m2; end
protected
def m3; end
class Foo
def m4; end
private
def m5; end
end
module Bar
def m6; end
private
class << self
def m7; end
end
end
RB

assert_equal(
[
"m1: public",
"m2: private",
"m3: protected",
"Foo::m4: public",
"Foo::m5: private",
"Bar::m6: public",
"Bar::m7: public",
],
model.symbols.values
.flat_map(&:definitions)
.filter { |d| d.is_a?(Method) }
.map { |d| "#{d.full_name}: #{T.cast(d, Method).visibility.serialize}" },
)
end

def test_inline_visibility
model = model(<<~RB)
protected def m1; end
private
public def m2; end
protected
private def m3; end
class Foo
private def m4; end
def m5; end
end
def m6; end
RB

assert_equal(
[
"m1: protected",
"m2: public",
"m3: private",
"Foo::m4: private",
"Foo::m5: public",
"m6: protected",
],
model.symbols.values
.flat_map(&:definitions)
.filter { |d| d.is_a?(Method) }
.map { |d| "#{d.full_name}: #{T.cast(d, Method).visibility.serialize}" },
)
end

def test_sigs
model = model(<<~RB)
sig { void }
Expand Down

0 comments on commit 24e0695

Please sign in to comment.