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 }