1 /** 2 Copyright: Copyright (c) 2017-2021, Joakim Brännström. All rights reserved. 3 License: MPL-2 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 This Source Code Form is subject to the terms of the Mozilla Public License, 7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain 8 one at http://mozilla.org/MPL/2.0/. 9 10 This file contains a visitor to extract the include directives. 11 */ 12 module libclang_ast.include_visitor; 13 14 import std.typecons : Nullable; 15 import std.algorithm : until, filter; 16 17 import my.path : Path; 18 19 import clang.Cursor : Cursor; 20 import clang.c.Index; 21 22 import libclang_ast.cursor_visitor; 23 24 /** Extract the filenames from all `#include` preprocessor macros that are 25 * found in the AST. 26 * 27 * Note that this is the filename inside the "", not the actual path on the 28 * filesystem. 29 * 30 * Params: 31 * root = clang AST 32 * depth = how deep into the AST to analyze. 33 */ 34 Path[] extractIncludes(Cursor root, int depth = 2) { 35 import std.array : appender; 36 37 auto r = appender!(Path[])(); 38 39 foreach (c; root.visitBreathFirst.filter!(a => a.kind == CXCursorKind.inclusionDirective)) { 40 r.put(Path(c.spelling)); 41 } 42 43 return r.data; 44 } 45 46 /** Analyze the AST (root) to see if any of the `#include` fulfill the user supplied matcher. 47 * 48 * Params: 49 * root = clang AST 50 * depth = how deep into the AST to analyze. 51 * Returns: the path to the header file that matched the predicate 52 */ 53 Nullable!Path hasInclude(alias matcher)(Cursor root, int depth = 2) @trusted { 54 Nullable!Path r; 55 56 foreach (c; root.visitBreathFirst.filter!(a => a.kind == CXCursorKind.inclusionDirective)) { 57 if (matcher(c.spelling)) { 58 r = Path(c.include.file.name); 59 break; 60 } 61 } 62 63 return r; 64 }