Name: TestReflection

Properties:
  property:
    Contract: $.string()
    Default: object
    Usage: InOut

  staticProperty:
    Contract: $.string()
    Default: static
    Usage: Static

Methods:
  testTypeInfo:
    Body:
      - $typeinfo: typeinfo($)
      - Return:
          name: $typeinfo.name
          versionStr: str($typeinfo.version)
          versionMajor: $typeinfo.version.major
          versionMinor: $typeinfo.version.minor
          versionPatch: $typeinfo.version.patch
          ancestors: $typeinfo.ancestors.name
          properties: $typeinfo.properties.name.orderBy($)
          methods: $typeinfo.methods.name.where(not $.startsWith(test)).orderBy($)
          package: $typeinfo.package.name

  testMethodInfo:
    Body:
      - $method: typeinfo($).methods.where($.name = foo).single()
      - $bar: $method.arguments.where($.name = bar).single()
      - $baz: $method.arguments.where($.name = baz).single()
      - Return:
          name: $method.name
          arguments: $method.arguments.name
          barHasDefault: $bar.hasDefault
          bazHasDefault: $baz.hasDefault
          declaringType: $method.declaringType.name
          barMethod: $bar.declaringMethod.name
          bazMethod: $baz.declaringMethod.name

  testPropertyInfo:
    Body:
      - $property: typeinfo($).properties.orderBy($.name).first()
      - Return:
          name: $property.name
          hasDefault: $property.hasDefault
          usage: $property.usage

  foo:
    Arguments:
      - bar:
          Contract: $.string()
          Default: null
      - baz:
          Contract: $.string()
    Body:
      Return: $bar + $baz

  testPropertyRead:
    Body:
      - $instanceValues: typeinfo($).properties.orderBy($.name).
          select($.getValue($this))
      - $staticValues: typeinfo($).properties.orderBy($.name).
          where($.usage = Static).select($.getValue(null))
      - Return: [$instanceValues, $staticValues]

  testPropertyWrite:
    Body:
      - $instanceProperty: typeinfo($).properties.where($.name = property).single()
      - $instanceProperty.setValue($, 'new object')
      - $staticProperty: typeinfo($).properties.where($.name = staticProperty).single()
      - $staticProperty.setValue($, 'new static')
      - Return: $.testPropertyRead()

  testMethodInvoke:
    Body:
      - $method: typeinfo($).methods.where($.name = foo).single()
      - Return: $method.invoke($, 'bar ', baz => baz)

  testInstanceCreate:
    Body:
      - $obj: new(typeinfo($).type, property => test)
      - Return: $obj.property
