1 module contract.macro_;
2 
3 
4 import contract;
5 
6 
7 @Tags("contract")
8 @("macro after enum")
9 @safe unittest {
10 
11     import clang: TranslationUnitFlags;
12     import std.algorithm: countUntil;
13 
14     const tu = parse(
15         C(
16             `
17                 enum TheEnum { BAR = 42 };
18                 #define BAR 42
19             `
20         ),
21         TranslationUnitFlags.DetailedPreprocessingRecord,
22     );
23 
24     tu.children.length.shouldBeGreaterThan(2);
25 
26     const enumIndex = tu.children.countUntil!(a => a.kind == Cursor.Kind.EnumDecl && a.spelling == "TheEnum");
27     const macroIndex = tu.children.countUntil!(a => a.kind == Cursor.Kind.MacroDefinition && a.spelling == "BAR");
28 
29     // for unfathomable reasons, clang puts all the macros at the top
30     // completely disregarding the order they appear in the code
31     enumIndex.shouldBeGreaterThan(macroIndex);
32 }
33 
34 
35 @Tags("contract")
36 @("tokens")
37 @safe unittest {
38     import dpp.translation.macro_: isBuiltinMacro;
39     import clang: TranslationUnitFlags, Token;
40     import std.algorithm: filter;
41     import std.array: array;
42 
43     const tu = parse(
44         C(
45             `
46                 #define INT 42
47                 #define DOUBLE 33.3
48                 #define OCTAL 00177
49                 #define STRING "foobar"
50             `
51         ),
52         TranslationUnitFlags.DetailedPreprocessingRecord,
53     );
54 
55     auto childrenRange = tu.children.filter!(a => !isBuiltinMacro(a));
56     const children = () @trusted { return childrenRange.array; }();
57     children.length.should == 4;
58 
59     const int_ = children[0];
60     int_.tokens.should == [
61         Token(Token.Kind.Identifier, "INT"),
62         Token(Token.Kind.Literal, "42"),
63     ];
64 
65     const double_ = children[1];
66     double_.tokens.should == [
67         Token(Token.Kind.Identifier, "DOUBLE"),
68         Token(Token.Kind.Literal, "33.3"),
69     ];
70 
71     const octal = children[2];
72     octal.tokens.should == [
73         Token(Token.Kind.Identifier, "OCTAL"),
74         Token(Token.Kind.Literal, "00177"),
75     ];
76 
77     const string_ = children[3];
78     string_.tokens.should == [
79         Token(Token.Kind.Identifier, "STRING"),
80         Token(Token.Kind.Literal, `"foobar"`),
81     ];
82 }