lib/parlour/conflict_resolver.rb in parlour-0.8.0 vs lib/parlour/conflict_resolver.rb in parlour-0.8.1
- old
+ new
@@ -37,62 +37,97 @@
# which there is a conflict.
# @yieldreturn [RbiGenerator::RbiObject] One of the +candidates+, which
# will be kept, or nil to keep none of them.
# @return [void]
def resolve_conflicts(namespace, &resolver)
+ Debugging.debug_puts(self, Debugging::Tree.begin("Resolving conflicts for #{namespace.name}..."))
+
# Check for multiple definitions with the same name
grouped_by_name_children = namespace.children.group_by(&:name)
grouped_by_name_children.each do |name, children|
+ Debugging.debug_puts(self, Debugging::Tree.begin("Checking children named #{name}..."))
+
if children.length > 1
+ Debugging.debug_puts(self, Debugging::Tree.here("Possible conflict between #{children.length} objects"))
+
# Special case: do we have two methods, one of which is a class method
# and the other isn't? If so, do nothing - this is fine
- next if children.length == 2 &&
+ if children.length == 2 &&
children.all? { |c| c.is_a?(RbiGenerator::Method) } &&
children.count { |c| T.cast(c, RbiGenerator::Method).class_method } == 1
+ Debugging.debug_puts(self, Debugging::Tree.end("One is an instance method and one is a class method; no resolution required"))
+ next
+ end
+
# Special case: do we have two attributes, one of which is a class
# attribute and the other isn't? If so, do nothing - this is fine
- next if children.length == 2 &&
+ if children.length == 2 &&
children.all? { |c| c.is_a?(RbiGenerator::Attribute) } &&
children.count { |c| T.cast(c, RbiGenerator::Attribute).class_attribute } == 1
+ Debugging.debug_puts(self, Debugging::Tree.end("One is an instance attribute and one is a class attribute; no resolution required"))
+ next
+ end
+
+ # Special case: are they all clearly equal? If so, remove all but one
+ if all_eql?(children)
+ Debugging.debug_puts(self, Debugging::Tree.end("All children are identical"))
+
+ # All of the children are the same, so this deletes all of them
+ namespace.children.delete(T.must(children.first))
+
+ # Re-add one child
+ namespace.children << T.must(children.first)
+ next
+ end
+
# We found a conflict!
# Start by removing all the conflicting items
children.each do |c|
namespace.children.delete(c)
end
# We can only try to resolve automatically if they're all the same
# type of object, so check that first
children_type = single_type_of_array(children)
unless children_type
- # The types aren't the same, so ask the resovler what to do, and
+ Debugging.debug_puts(self, Debugging::Tree.end("Children are different types; requesting manual resolution"))
+ # The types aren't the same, so ask the resolver what to do, and
# insert that (if not nil)
choice = resolver.call("Different kinds of definition for the same name", children)
namespace.children << choice if choice
next
end
# Can the children merge themselves automatically? If so, let them
first, *rest = children
first, rest = T.must(first), T.must(rest)
if T.must(first).mergeable?(T.must(rest))
+ Debugging.debug_puts(self, Debugging::Tree.end("Children are all mergeable; resolving automatically"))
first.merge_into_self(rest)
namespace.children << first
next
end
# I give up! Let it be resolved manually somehow
+ Debugging.debug_puts(self, Debugging::Tree.end("Unable to resolve automatically; requesting manual resolution"))
choice = resolver.call("Can't automatically resolve", children)
namespace.children << choice if choice
+ else
+ Debugging.debug_puts(self, Debugging::Tree.end("No conflicts"))
end
end
+ Debugging.debug_puts(self, Debugging::Tree.here("Resolving children..."))
+
# Recurse to child namespaces
namespace.children.each do |child|
resolve_conflicts(child, &resolver) if RbiGenerator::Namespace === child
end
+
+ Debugging.debug_puts(self, Debugging::Tree.end("All children done"))
end
private
sig { params(arr: T::Array[T.untyped]).returns(T.nilable(Class)) }