describeAggregate

Describes classes, structs, unions and interfaces

describeAggregate
(
T
bool withUnitTests = false
)
()
if (
isAggregateType!T
)

Examples

It should describe a class with interfaces and base classes

interface I1 { }
interface I2 { }

class C1 { }
class C2 : C1, I1 { }
class C3 : C2, I2 { }

auto result = describeAggregate!C3;

result.name.should.equal("C3");

result.baseClasses.length.should.equal(3);
result.baseClasses[0].name.should.equal("C2");
result.baseClasses[1].name.should.equal("C1");
result.baseClasses[2].name.should.equal("Object");

result.interfaces.length.should.equal(2);
result.interfaces[0].name.should.equal("I1");
result.interfaces[1].name.should.equal("I2");

result.location.file.should.equal("source/introspection/aggregate.d");
result.location.line.should.be.greaterThan(0);
result.location.column.should.equal(3);

result.protection = Protection.public_;

It should describe struct attributes

int attr(int) { return 0; }

@("attribute1") @attr(1)
struct Test { }

auto result = describeAggregate!Test;

result.name.should.equal("Test");
result.attributes.length.should.equal(2);

result.attributes[0].name.should.equal(`"attribute1"`);
result.attributes[0].type.name.should.equal(`string`);

result.attributes[1].name.should.equal("0");
result.attributes[1].type.name.should.equal(`int`);

It should find properties from a struct

struct Test { int a; string b; }

auto result = describeAggregate!Test;

result.properties.length.should.equal(2);

result.properties[0].name.should.equal("a");
result.properties[0].isStatic.should.equal(false);
result.properties[0].protection.should.equal(Protection.public_);
result.properties[0].type.name.should.equal("int");

result.properties[1].name.should.equal("b");
result.properties[0].isStatic.should.equal(false);
result.properties[1].protection.should.equal(Protection.public_);
result.properties[1].type.name.should.equal("string");

It should find a static property

struct Test {
  static int a;
  string b;
}

auto result = describeAggregate!Test;

result.properties[0].name.should.equal("a");
result.properties[0].isStatic.should.equal(true);
result.properties[1].isStatic.should.equal(false);

It should find property protection levels

class Test {
  public int a;
  protected int b;
  private int c;
  export int d;
}

auto result = describeAggregate!Test;

result.properties.length.should.equal(4);

result.properties[0].name.should.equal("a");
result.properties[0].protection.should.equal(Protection.public_);

result.properties[1].name.should.equal("b");
result.properties[1].protection.should.equal(Protection.protected_);

result.properties[2].name.should.equal("c");
result.properties[2].protection.should.equal(Protection.private_);

result.properties[3].name.should.equal("d");
result.properties[3].protection.should.equal(Protection.export_);

It should describe struct property attributes

int attr(int) { return 0; }

struct Test {
  @("attribute1") @attr(1)
  string name;
}

auto result = describeAggregate!Test;

result.name.should.equal("Test");

result.properties[0].attributes.length.should.equal(2);
result.properties[0].attributes[0].name.should.equal(`"attribute1"`);
result.properties[0].attributes[0].type.name.should.equal(`string`);

It should find public methods from a struct

struct Test {
  void a() {}
  void b() {}
}

auto result = describeAggregate!Test;

result.methods.length.should.equal(2);

result.methods[0].name.should.equal("a");
result.methods[0].isStatic.should.equal(false);
result.methods[0].protection.should.equal(Protection.public_);
result.methods[0].type.name.should.equal("void()");

result.methods[1].name.should.equal("b");
result.methods[1].isStatic.should.equal(false);
result.methods[1].protection.should.equal(Protection.public_);
result.methods[1].type.name.should.equal("void()");

It should find all methods from a class

class Test {
  public void a() {}
  protected void b() {}
  private void c() {}
}

auto result = describeAggregate!Test;

result.methods.length.should.equal(8);

result.methods.map!(a => a.name).array.should.equal(["a", "b", "c", "toString", "toHash", "opCmp", "opEquals", "factory"]);

result.methods[0].name.should.equal("a");
result.methods[0].isStatic.should.equal(false);
result.methods[0].protection.should.equal(Protection.public_);
result.methods[0].type.name.should.equal("void()");

result.methods[1].name.should.equal("b");
result.methods[1].isStatic.should.equal(false);
result.methods[1].protection.should.equal(Protection.protected_);
result.methods[1].type.name.should.equal("void()");

result.methods[2].name.should.equal("c");
result.methods[2].isStatic.should.equal(false);
result.methods[2].protection.should.equal(Protection.private_);
result.methods[2].type.name.should.equal("void()");

It should find overloaded methods

class Test {
  void a(int) {}
  void a(string) {}
}

auto result = describeAggregate!Test;

result.methods.length.should.equal(7);

result.methods.map!(a => a.name).array.should.equal(["a", "a", "toString", "toHash", "opCmp", "opEquals", "factory"]);

result.methods[0].name.should.equal("a");
result.methods[0].overloadIndex.should.equal(0);
result.methods[0].isStatic.should.equal(false);
result.methods[0].protection.should.equal(Protection.public_);
result.methods[0].type.name.should.equal("void(int)");
result.methods[0].parameters[0].name.should.equal("_param_0");
result.methods[0].parameters[0].type.name.should.equal("int");

result.methods[1].name.should.equal("a");
result.methods[1].overloadIndex.should.equal(1);
result.methods[1].isStatic.should.equal(false);
result.methods[1].protection.should.equal(Protection.public_);
result.methods[1].type.name.should.equal("void(string)");
result.methods[1].parameters[0].name.should.equal("_param_0");
result.methods[1].parameters[0].type.name.should.equal("string");

It should describe struct method attributes

int attr(int) { return 0; }

struct Test {
  @("attribute1") @attr(1)
  string name();
}

auto result = describeAggregate!Test;

result.name.should.equal("Test");
result.methods[0].attributes.length.should.equal(3);
result.methods[0].attributes[0].name.should.equal(`"attribute1"`);
result.methods[0].attributes[0].type.name.should.equal(`string`);

It should describe a struct @property

int attr(int) { return 0; }

struct Test {
  @property string name();
}

auto result = describeAggregate!Test;

result.name.should.equal("Test");
result.methods[0].attributes.length.should.equal(2);
result.methods[0].attributes[0].name.should.equal(`"@property"`);
result.methods[0].attributes[0].type.name.should.equal(`string`);
result.methods[0].attributes[1].name.should.equal(`"@system"`);
result.methods[0].attributes[1].type.name.should.equal(`string`);

It should describe static struct method

struct Test {
  static string name();
  string name(int);
}

auto result = describeAggregate!Test;

result.name.should.equal("Test");
result.methods[0].name.should.equal("name");
result.methods[0].isStatic.should.equal(true);
result.methods[0].parameters.length.should.equal(0);

result.methods[1].name.should.equal("name");
result.methods[1].isStatic.should.equal(false);
result.methods[1].parameters.length.should.equal(1);

It should describe enums defined in classes

class Test {
  enum Other : int {
    a, b, c, d
  }
}

auto result = describeAggregate!Test;

result.enums.length.should.equal(1);
result.enums[0].name.should.equal("Other");

It should describe a manifest constant

class Test {
  enum constant = 4;
}

auto result = describeAggregate!Test;

result.manifestConstants.length.should.equal(1);
result.manifestConstants[0].name.should.equal("constant");

It should describe a struct type defined inside a class

class Test {
  struct Other {}
}

auto result = describeAggregate!Test;

result.nested.length.should.equal(1);
result.nested[0].name.should.equal("Other");

It should describe a template defined inside a class

class Test {
  struct Other(T) {}
}

auto result = describeAggregate!Test;

result.nested.length.should.equal(0);

result.templates.length.should.equal(1);
result.templates[0].name.should.equal("Other");

It should describe an instantiated template

class Test(T) {
  T bar(T val) { return val; }
}

alias TestInstantiated = Test!string;

auto result = describeAggregate!TestInstantiated;

result.name.should.equal("Test!string");
result.nested.length.should.equal(0);
result.templates.length.should.equal(0);

result.methods.length.should.equal(6);
result.methods[0].name.should.equal("bar");
result.methods[0].returns.name.should.equal("string");

It should describe unittests defined in a struct

struct Test { unittest { } }

auto result = describeAggregate!(Test, true);
result.unitTests.length.should.equal(1);

It should describe attributes that return structs

struct Mapper { }
Mapper mapper() {
  return Mapper();
}

class MockClass {
  @mapper @Mapper @("mapper")
  void mapper() @trusted nothrow { }
}

enum result = describeAggregate!(MockClass, true);
result.methods[0].attributes.length.should.equal(5);
result.methods[0].attributes[0].name.should.equal("mapper");
result.methods[0].attributes[0].type.name.should.equal("nothrow @trusted void()");
result.methods[0].attributes[1].name.should.equal("Mapper");
result.methods[0].attributes[2].name.should.equal(`"mapper"`);

Meta