1 module introspection.manifestConstant;
2 
3 import std.traits;
4 import std.conv;
5 
6 import introspection.type;
7 import introspection.location;
8 import introspection.protection;
9 
10 version(unittest) {
11   import fluent.asserts;
12 }
13 
14 /// Stores information about manifest constants
15 struct ManifestConstant {
16   /// The constant name
17   string name;
18 
19   ///
20   string value;
21 
22   ///
23   Type type;
24 
25   ///
26   Protection protection;
27 
28   ///
29   Location location;
30 }
31 
32 /// Describe a manifest constant defined in aggregate types
33 ManifestConstant describeManifestConstant(T, string member)() {
34   ManifestConstant manifestConstant;
35 
36   manifestConstant.name = member;
37   manifestConstant.value = __traits(getMember, T, member).to!string;
38   manifestConstant.type = describeType!(__traits(getMember, T, member));
39 
40   auto location = __traits(getLocation, T);
41   manifestConstant.location = Location(location[0], location[1], location[2]);
42 
43   manifestConstant.protection = __traits(getProtection, __traits(getMember, T, member)).toProtection;
44 
45   return manifestConstant;
46 }
47 
48 /// ditto
49 ManifestConstant describeManifestConstant(alias T, string member)() {
50   ManifestConstant manifestConstant;
51 
52   manifestConstant.name = member;
53   manifestConstant.value = __traits(getMember, T, member).to!string;
54   manifestConstant.type = describeType!(__traits(getMember, T, member));
55 
56   auto location = __traits(getLocation, __traits(getMember, T, member));
57   manifestConstant.location = Location(location[0], location[1], location[2]);
58 
59   manifestConstant.protection = __traits(getProtection, __traits(getMember, T, member)).toProtection;
60 
61   return manifestConstant;
62 }
63 
64 /// Check if a member is manifest constant
65 bool isManifestConstant(T, string name)() {
66   mixin(`return is(typeof(T.init.` ~ name ~ `)) && !is(typeof(&T.init.` ~ name ~ `));`);
67 }
68 
69 /// ditto
70 bool isManifestConstant(alias T)() {
71   return is(typeof(T)) && !is(typeof(&T));
72 }
73 
74 /// it should describe a public manifest constant
75 unittest {
76   struct Test {
77     enum config = 3;
78   }
79 
80   auto result = describeManifestConstant!(Test, "config");
81 
82   result.name.should.equal("config");
83   result.value.should.equal("3");
84 
85   result.type.name.should.equal("int");
86   result.type.isManifestConstant.should.equal(true);
87 
88   result.protection.should.equal(Protection.public_);
89 
90   result.location.file.should.equal("source/introspection/manifestConstant.d");
91   result.location.line.should.be.greaterThan(0);
92   result.location.column.should.equal(3);
93 }
94 
95 /// it should describe a private manifest constant
96 unittest {
97   struct Test {
98     private enum config = "test";
99   }
100 
101   auto result = describeManifestConstant!(Test, "config");
102 
103   result.name.should.equal("config");
104   result.value.should.equal("test");
105 
106   result.type.name.should.equal("string");
107   result.type.isManifestConstant.should.equal(true);
108 
109   result.protection.should.equal(Protection.private_);
110 }