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                 #define FUN(x) x
51                 #define GUN(y, ...) y(__VA_ARGS__)
52                 #define STR(x) #x
53             `
54         ),
55         TranslationUnitFlags.DetailedPreprocessingRecord,
56     );
57 
58     auto childrenRange = tu.children.filter!(a => !isBuiltinMacro(a));
59     const children = () @trusted { return childrenRange.array; }();
60     children.length.should == 7;
61 
62     const int_ = children[0];
63     int_.tokens.should == [
64         Token(Token.Kind.Identifier, "INT"),
65         Token(Token.Kind.Literal, "42"),
66     ];
67 
68     const double_ = children[1];
69     double_.tokens.should == [
70         Token(Token.Kind.Identifier, "DOUBLE"),
71         Token(Token.Kind.Literal, "33.3"),
72     ];
73 
74     const octal = children[2];
75     octal.tokens.should == [
76         Token(Token.Kind.Identifier, "OCTAL"),
77         Token(Token.Kind.Literal, "00177"),
78     ];
79 
80     const string_ = children[3];
81     string_.tokens.should == [
82         Token(Token.Kind.Identifier, "STRING"),
83         Token(Token.Kind.Literal, `"foobar"`),
84     ];
85 
86     const fun = children[4];
87     fun.tokens.should == [
88         Token(Token.Kind.Identifier, "FUN"),
89         Token(Token.Kind.Punctuation, "("),
90         Token(Token.Kind.Identifier, "x"),
91         Token(Token.Kind.Punctuation, ")"),
92         Token(Token.Kind.Identifier, "x"),
93     ];
94 
95     const gun = children[5];
96     gun.tokens.should == [
97         Token(Token.Kind.Identifier, "GUN"),
98         Token(Token.Kind.Punctuation, "("),
99         Token(Token.Kind.Identifier, "y"),
100         Token(Token.Kind.Punctuation, ","),
101         Token(Token.Kind.Punctuation, "..."),
102         Token(Token.Kind.Punctuation, ")"),
103         Token(Token.Kind.Identifier, "y"),
104         Token(Token.Kind.Punctuation, "("),
105         Token(Token.Kind.Identifier, "__VA_ARGS__"),
106         Token(Token.Kind.Punctuation, ")"),
107     ];
108 
109     const str = children[6];
110     str.tokens.should == [
111         Token(Token.Kind.Identifier, "STR"),
112         Token(Token.Kind.Punctuation, "("),
113         Token(Token.Kind.Identifier, "x"),
114         Token(Token.Kind.Punctuation, ")"),
115         Token(Token.Kind.Punctuation, "#"),
116         Token(Token.Kind.Identifier, "x"),
117     ];
118 
119 }