Index: runtime/observatory/lib/src/elements/class_tree.dart |
diff --git a/runtime/observatory/lib/src/elements/class_tree.dart b/runtime/observatory/lib/src/elements/class_tree.dart |
index 42de21c49dd31583abe795c1e26c7fa6f1d2aec1..0ba74fef32f770c2d539a4de4b97a19b4a044e59 100644 |
--- a/runtime/observatory/lib/src/elements/class_tree.dart |
+++ b/runtime/observatory/lib/src/elements/class_tree.dart |
@@ -20,27 +20,92 @@ class ClassTreeRow extends TableTreeRow { |
assert(cls != null); |
} |
- void onShow() { |
- super.onShow(); |
- if (children.length == 0) { |
- for (var subclass in cls.subclasses) { |
- if (subclass.isPatch) { |
- continue; |
- } |
+ void _addChildren(List<Class> subclasses) { |
+ for (var subclass in subclasses) { |
+ if (subclass.isPatch) { |
+ continue; |
+ } |
+ if (subclass.mixin != null) { |
+ _addChildren(subclass.subclasses); |
+ } else { |
var row = new ClassTreeRow(isolate, subclass, tree, this); |
children.add(row); |
} |
} |
+ } |
+ |
+ void _addMixins(Class cls) async { |
+ var classCell = flexColumns[0]; |
+ if (cls.superclass == null) { |
+ return; |
+ } |
+ bool first = true; |
+ while (cls.superclass != null && cls.superclass.mixin != null) { |
+ cls = cls.superclass; |
+ await cls.mixin.load(); |
+ var span = new SpanElement(); |
+ span.style.alignSelf = 'center'; |
+ span.style.whiteSpace = 'pre'; |
+ if (first) { |
+ span.text = ' with '; |
+ } else { |
+ span.text = ', '; |
+ } |
+ classCell.children.add(span); |
+ var mixinRef = new Element.tag('class-ref'); |
+ mixinRef.ref = cls.mixin.typeClass; |
+ mixinRef.style.alignSelf = 'center'; |
+ classCell.children.add(mixinRef); |
+ first = false; |
+ } |
+ } |
+ |
+ void _addClass(Class cls) async { |
var classCell = flexColumns[0]; |
classCell.style.justifyContent = 'flex-start'; |
var classRef = new Element.tag('class-ref'); |
classRef.ref = cls; |
classRef.style.alignSelf = 'center'; |
classCell.children.add(classRef); |
+ if (cls.superclass != null && cls.superclass.mixin != null) { |
+ await _addMixins(cls); |
+ } |
+ if (cls.subclasses.isNotEmpty) { |
+ var span = new SpanElement(); |
+ span.style.paddingLeft = '.5em'; |
+ span.style.alignSelf = 'center'; |
+ int subclassCount = _indirectSubclassCount(cls) - 1; |
+ if (subclassCount > 1) { |
+ span.text = '($subclassCount subclasses)'; |
+ } else { |
+ span.text = '($subclassCount subclass)'; |
+ } |
+ classCell.children.add(span); |
+ } |
+ } |
+ |
+ void onShow() { |
+ super.onShow(); |
+ if (children.length == 0) { |
+ _addChildren(cls.subclasses); |
+ } |
+ _addClass(cls); |
+ } |
+ |
+ static int _indirectSubclassCount(var cls) { |
+ int count = 0; |
+ if (cls.mixin == null) { |
+ // Don't count synthetic mixin classes in subclass count. |
+ count++; |
+ } |
+ for (var subclass in cls.subclasses) { |
+ count += _indirectSubclassCount(subclass); |
+ } |
+ return count; |
} |
bool hasChildren() { |
- return cls.subclasses.length > 0; |
+ return cls.subclasses.isNotEmpty; |
} |
} |