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 enum isManifestConstant(T, string name) = isManifestConstant!(__traits(getMember, T, name));
66 
67 /// ditto
68 enum isManifestConstant(alias symbol) = __traits(compiles, { enum e = symbol; }) &&
69   !__traits(compiles, { const ptr = &symbol; });
70 
71 /// it should describe a public manifest constant
72 unittest {
73   struct Test {
74     enum config = 3;
75   }
76 
77   auto result = describeManifestConstant!(Test, "config");
78 
79   result.name.should.equal("config");
80   result.value.should.equal("3");
81 
82   result.type.name.should.equal("int");
83   result.type.isManifestConstant.should.equal(true);
84 
85   result.protection.should.equal(Protection.public_);
86 
87   result.location.file.should.equal("source/introspection/manifestConstant.d");
88   result.location.line.should.be.greaterThan(0);
89   result.location.column.should.equal(3);
90 }
91 
92 /// it should describe a private manifest constant
93 unittest {
94   struct Test {
95     private enum config = "test";
96   }
97 
98   auto result = describeManifestConstant!(Test, "config");
99 
100   result.name.should.equal("config");
101   result.value.should.equal("test");
102 
103   result.type.name.should.equal("string");
104   result.type.isManifestConstant.should.equal(true);
105 
106   result.protection.should.equal(Protection.private_);
107 }