Report a bug
If you spot a problem with this page, click here to create a GitHub issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

mir.reflection

Base reflection utilities.
License:
Authors:
Ilya Yaroshenko
enum bool isStdNullable(T);
Match types like std.typeconst: Nullable.
Examples:
import std.typecons;
assert(isStdNullable!(Nullable!double));
struct reflectDeprecated(string target);
Attribute for deprecated API
template ReflectName(string target)

auto reflectName(string target = null, Args...)(string name);
Attribute to rename methods, types and functions
Examples:
enum E { A, B, C }

struct S
{
    @reflectName("A")
    int a;

    @reflectName!"c++"("B")
    int b;

    @reflectName!("C",  double)("cd")
    @reflectName!("C",  float)("cf")
    F c(F)()
    {
        return b;
    }
}

import std.traits: hasUDA;

alias UniName = ReflectName!null;
alias CppName = ReflectName!"c++";
alias CName = ReflectName!"C";

static assert(hasUDA!(S.a, UniName!()("A")));
static assert(hasUDA!(S.b, CppName!()("B")));

// static assert(hasUDA!(S.c, ReflectName)); // doesn't work for now
static assert(hasUDA!(S.c, CName));
static assert(hasUDA!(S.c, CName!double));
static assert(hasUDA!(S.c, CName!float));
static assert(hasUDA!(S.c, CName!double("cd")));
static assert(hasUDA!(S.c, CName!float("cf")));
struct ReflectName(Args...);
string name;
template ReflectMeta(string target, string[] fields)

template reflectMeta(string target, string[] fields)
Attribute to rename methods, types and functions
Examples:
enum E { A, B, C }

struct S
{
    int a;
    @reflectMeta!("c++", ["type"])(E.C)
    int b;
}

import std.traits: hasUDA;

alias CppMeta = ReflectMeta!("c++", ["type"]);

static assert(CppMeta!E(E.C).type == E.C);
static assert(!hasUDA!(S.a, CppMeta!E(E.A)));
static assert(hasUDA!(S.b, CppMeta!E(E.C)));
struct ReflectMeta(Args...);
Args args;
template reflectIgnore(string target)
Attribute to ignore a reflection target
Examples:
struct S
{
    @reflectIgnore!"c++"
    int a;
}

import std.traits: hasUDA;
static assert(hasUDA!(S.a, reflectIgnore!"c++"));
struct ReflectDoc(string target);
Attribute for documentation and unittests
string text;
reflectUnittest!target test;
pure nothrow @nogc @safe this(string text);
pure nothrow @nogc @safe this(string text, reflectUnittest!target test);
const scope void toString(W)(ref scope W w);
const pure nothrow scope @safe string toString()();
ReflectDoc!target reflectDoc(string target = null)(string text);
Attribute for documentation.
template reflectGetDocs(string target, alias symbol)

template reflectGetDocs(string target)
Examples:
enum E
{
    @reflectDoc("alpha")
    a,
    @reflectDoc!"C#"("Beta", reflectUnittest!"C#"("some c# code"))
    @reflectDoc("beta")
    b,
    c,
}

alias Doc = ReflectDoc!null;
alias CSDoc = ReflectDoc!"C#";

static assert(reflectGetDocs!null(E.a) == [Doc("alpha")]);
static assert(reflectGetDocs!"C#"(E.b) == [CSDoc("Beta", reflectUnittest!"C#"("some c# code"))]);
static assert(reflectGetDocs!null(E.b) == [Doc("beta")]);
static assert(reflectGetDocs!null(E.c) is null);

struct S
{
    @reflectDoc("alpha")
    @reflectDoc!"C#"("Alpha")
    int a;
}

static assert(reflectGetDocs!(null, S.a) == [Doc("alpha")]);
static assert(reflectGetDocs!("C#", S.a) == [CSDoc("Alpha")]);

import std.conv: to;
static assert(CSDoc("Beta", reflectUnittest!"C#"("some c# code")).to!string == "Beta\nExample usage:\nsome c# code");
struct reflectUnittest(string target);
Attribute for extern unit-test.
string text;
template reflectGetUnittest(string target, alias symbol)

template reflectGetUnittest(string target)
Examples:
enum E
{
    @reflectUnittest!"c++"("assert(E::a == 0);")
    a,
    @reflectUnittest!"c++"("assert(E::b == 1);")
    b,
    c,
}

static assert(reflectGetUnittest!"c++"(E.a) == "assert(E::a == 0);");
static assert(reflectGetUnittest!"c++"(E.b) == "assert(E::b == 1);");
static assert(reflectGetUnittest!"c++"(E.c) is null);

struct S
{
    @reflectUnittest!"c++"("alpha")
    int a;
}

static assert(reflectGetUnittest!("c++", S.a) == "alpha");
template getUDA(alias symbol, alias attribute)
Returns:
single UDA.
enum bool isField(T, string member);
Checks if member is field.
Examples:
struct D
{
    int gi;
}

struct I
{
    int f;

    D base;
    alias base this;

    void gi(double ) @property {}
    void gi(uint ) @property {}
}

struct S
{
    int d;

    I i;
    alias i this;

    int gm() @property {return 0;}
    int gc() const @property {return 0;}
    void gs(int) @property {}
}

static assert(!isField!(S, "gi"));
static assert(!isField!(S, "gs"));
static assert(!isField!(S, "gc"));
static assert(!isField!(S, "gm"));
static assert(!isField!(S, "gi"));
static assert(isField!(S, "d"));
static assert(isField!(S, "f"));
static assert(isField!(S, "i"));
Examples:
with classes
class I
{
    int f;

    void gi(double ) @property {}
    void gi(uint ) @property {}
}

class S
{
    int d;

    I i;
    alias i this;

    int gm() @property {return 0;}
    int gc() const @property {return 0;}
    void gs(int) @property {}
}

static assert(!isField!(S, "gi"));
static assert(!isField!(S, "gs"));
static assert(!isField!(S, "gc"));
static assert(!isField!(S, "gm"));
static assert(isField!(S, "d"));
static assert(isField!(S, "f"));
static assert(isField!(S, "i"));
template isProperty(T, string member)
Checks if member is property.
Examples:
struct D
{
    int y;

    void gf(double ) @property {}
    void gf(uint ) @property {}
}

struct I
{
    int f;

    D base;
    alias base this;

    void gi(double ) @property {}
    void gi(uint ) @property {}
}

struct S
{
    int d;

    I i;
    alias i this;

    int gm() @property {return 0;}
    int gc() const @property {return 0;}
    void gs(int) @property {}
}

static assert(isProperty!(S, "gf"));
static assert(isProperty!(S, "gi"));
static assert(isProperty!(S, "gs"));
static assert(isProperty!(S, "gc"));
static assert(isProperty!(S, "gm"));
static assert(!isProperty!(S, "d"));
static assert(!isProperty!(S, "f"));
static assert(!isProperty!(S, "y"));
template getSetters(T, string member)
Returns:
list of the setter properties.

Note The implementation ignores templates.

Examples:
struct I
{
    int f;

    void gi(double ) @property {}
    void gi(uint ) @property {}
}

struct S
{
    int d;

    I i;
    alias i this;

    int gm() @property {return 0;}
    int gc() const @property {return 0;}
    void gs(int) @property {}
}

static assert(getSetters!(S, "gi").length == 2);
static assert(getSetters!(S, "gs").length == 1);
static assert(getSetters!(S, "gc").length == 0);
static assert(getSetters!(S, "gm").length == 0);
static assert(getSetters!(S, "d").length == 0);
static assert(getSetters!(S, "f").length == 0);
enum string[] SerializableMembers(T);
Returns:
list of the serializable (public getters) members.
Examples:
struct D
{
    int y;

    int gf() @property {return 0;}
}

struct I
{
    int f;

    D base;
    alias base this;

    int gi() @property {return 0;}
}

struct S
{
    int d;

    package int p;

    int gm() @property {return 0;}

    private int q;

    I i;
    alias i this;

    int gc() const @property {return 0;}
    void gs(int) @property {}
}

static assert(SerializableMembers!S == ["y", "gf", "f", "gi", "d", "gm", "gc"]);
static assert(SerializableMembers!(const S) == ["y", "f", "d", "gc"]);
enum string[] DeserializableMembers(T);
Returns:
list of the deserializable (public setters) members.
Examples:
struct I
{
    int f;
    void ga(int) @property {}
}

struct S
{
    int d;
    package int p;

    int gm() @property {return 0;}
    void gm(int) @property {}

    private int q;

    I i;
    alias i this;


    void gc(int, int) @property {}
    void gc(int) @property {}
}

S s;
// s.gc(0);

static assert (DeserializableMembers!S == ["f", "ga", "d", "gm", "gc"]);
static assert (DeserializableMembers!(const S) == []);