1 /** 2 Copyright: Copyright (c) 2017, 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 cpptooling.analyzer.clang.include_visitor; 13 14 import std.typecons : Nullable; 15 import std.algorithm : until, filter; 16 17 import clang.Cursor : Cursor; 18 import clang.c.Index; 19 20 import cpptooling.analyzer.clang.cursor_visitor; 21 import dextool.type : FileName; 22 23 /** Extract the filenames from all `#include` preprocessor macros that are 24 * found in the AST. 25 * 26 * Note that this is the filename inside the "", not the actuall path on the 27 * filesystem. 28 * 29 * Params: 30 * root = clang AST 31 * depth = how deep into the AST to analyze. 32 */ 33 FileName[] extractIncludes(Cursor root, int depth = 2) { 34 import std.array : appender; 35 36 auto r = appender!(FileName[])(); 37 38 foreach (c; root.visitBreathFirst.filter!(a => a.kind == CXCursorKind.inclusionDirective)) { 39 r.put(FileName(c.spelling)); 40 } 41 42 return r.data; 43 } 44 45 /** Analyze the AST (root) to see if any of the `#include` fulfill the user supplied matcher. 46 * 47 * Params: 48 * root = clang AST 49 * depth = how deep into the AST to analyze. 50 * Returns: the path to the header file that matched the predicate 51 */ 52 Nullable!FileName hasInclude(alias matcher)(Cursor root, int depth = 2) @trusted { 53 Nullable!FileName r; 54 55 foreach (c; root.visitBreathFirst.filter!(a => a.kind == CXCursorKind.inclusionDirective)) { 56 if (matcher(c.spelling)) { 57 r = FileName(c.include.file.name); 58 break; 59 } 60 } 61 62 return r; 63 }