main = <No Member>;
library from "package:flutter/object.dart" as obj {

  class RenderFoo extends obj::RenderObject {
    synthetic constructor •() → obj::RenderFoo
      : super obj::RenderObject::•()
      ;
    get constraints() → obj::FooConstraints
      return super.{obj::RenderObject::constraints} as{ForNonNullableByDefault} obj::FooConstraints;
  }
  class FooConstraints extends obj::Constraints {
    synthetic constructor •() → obj::FooConstraints
      : super obj::Constraints::•()
      ;
    get axis() → dart.core::String
      return "hello";
  }
  class Constraints extends dart.core::Object {
    synthetic constructor •() → obj::Constraints
      : super dart.core::Object::•()
      ;
  }
  class RenderObject extends dart.core::Object {
    synthetic constructor •() → obj::RenderObject
      : super dart.core::Object::•()
      ;
    get constraints() → obj::Constraints
      return new obj::Constraints::•();
    get renderObject() → obj::RenderObject
      return this;
  }
}
library from "org-dartlang-test:///lib1.dart" as lib1 {

  import "package:flutter/object.dart";
  import "org-dartlang-test:///lib2.dart";

  abstract class _Adaptor&RenderFoo&LibMixin extends obj::RenderFoo implements lib2::LibMixin /*isAnonymousMixin,isEliminatedMixin*/  {
    synthetic constructor •() → lib1::_Adaptor&RenderFoo&LibMixin*
      : super obj::RenderFoo::•()
      ;
    abstract member-signature get /* from org-dartlang-test:///lib2.dart */ constraints() → obj::Constraints*; -> obj::RenderObject::constraints
    abstract member-signature get /* from org-dartlang-test:///lib2.dart */ renderObject() → obj::RenderObject*; -> obj::RenderObject::renderObject
    abstract member-signature get /* from org-dartlang-test:///lib2.dart */ _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
    abstract member-signature method /* from org-dartlang-test:///lib2.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
    abstract member-signature method /* from org-dartlang-test:///lib2.dart */ _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
    abstract member-signature method /* from org-dartlang-test:///lib2.dart */ _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
    abstract member-signature method /* from org-dartlang-test:///lib2.dart */ _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
    abstract member-signature operator /* from org-dartlang-test:///lib2.dart */ ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
    abstract member-signature get /* from org-dartlang-test:///lib2.dart */ hashCode() → dart.core::int*; -> dart.core::Object::hashCode
    abstract member-signature method /* from org-dartlang-test:///lib2.dart */ toString() → dart.core::String*; -> dart.core::Object::toString
    abstract member-signature method /* from org-dartlang-test:///lib2.dart */ noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
    abstract member-signature get /* from org-dartlang-test:///lib2.dart */ runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
  }
  abstract class Adaptor extends lib1::_Adaptor&RenderFoo&LibMixin {
    synthetic constructor •() → lib1::Adaptor*
      : super lib1::_Adaptor&RenderFoo&LibMixin::•()
      ;
  }
}
library from "org-dartlang-test:///lib2.dart" as lib2 {

  import "package:flutter/object.dart";

  abstract class LibMixin extends obj::RenderObject /*isMixinDeclaration*/  {
    abstract member-signature get constraints() → obj::Constraints*; -> obj::RenderObject::constraints
    abstract member-signature get renderObject() → obj::RenderObject*; -> obj::RenderObject::renderObject
    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
  }
}
library from "org-dartlang-test:///main.dart" as main {
//
// Problems in library:
//
// org-dartlang-test:///main.dart:7:36: Error: The getter 'axis' isn't defined for the class 'Constraints'.
//  - 'Constraints' is from 'package:flutter/object.dart' ('org-dartlang-test:///flutter/object.dart').
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'axis'.
//     print(renderObject.constraints.axis);
//                                    ^^^^
//

  import "package:flutter/object.dart";
  import "org-dartlang-test:///lib1.dart";

  class AdaptorElement extends obj::RenderObject {
    synthetic constructor •() → main::AdaptorElement*
      : super obj::RenderObject::•()
      ;
    get renderObject() → lib1::Adaptor*
      return super.{obj::RenderObject::renderObject} as{TypeError} lib1::Adaptor*;
    method foo() → void {
      dart.core::print(invalid-expression "org-dartlang-test:///main.dart:7:36: Error: The getter 'axis' isn't defined for the class 'Constraints'.\n - 'Constraints' is from 'package:flutter/object.dart' ('org-dartlang-test:///flutter/object.dart').\nTry correcting the name to the name of an existing getter, or defining a getter or field named 'axis'.\n    print(renderObject.constraints.axis);\n                                   ^^^^");
    }
    abstract member-signature get constraints() → obj::Constraints*; -> obj::RenderObject::constraints
    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
  }
}
