1 /** 2 Copyright: Copyright (c) 2016, 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 Various utilities used by generators. 11 TODO change the name of this module to location_filter. 12 */ 13 module cpptooling.generator.utility; 14 15 import std.functional : unaryFun; 16 import std.traits; 17 import std.range : ElementType; 18 19 version (unittest) { 20 import unit_threaded : shouldEqual; 21 } 22 23 /** Filter according to location existence and predicate. 24 * 25 * A false result is: 26 * - neither a location for a declaration or definition exist. 27 * - fails the predicate. 28 * 29 * The predicate is only called when a location exist. 30 */ 31 template filterAnyLocation(alias predicate) { 32 alias predFun = unaryFun!predicate; 33 34 auto filterAnyLocation(Range, LookupT)(Range range, LookupT lookup) { 35 import std.algorithm : filter, map; 36 import std.typecons : tuple; 37 import std.range : ElementType; 38 import cpptooling.data.type : LocationTag, Location; 39 40 struct LocElem { 41 LocationTag location; 42 ElementType!Range value; 43 } 44 45 // dfmt off 46 return range 47 // get the location associated with each item 48 .map!(a => tuple(lookup(a.usr), a)) 49 // remove those that don't have a location 50 .filter!(a => a[0].length != 0) 51 // unpack the location. a declaration or definition, doesn't matter 52 .map!(a => tuple(a[0].front.any, a[1])) 53 // pack data in a struct that make it easier to use with named 54 // fields 55 .map!(a => LocElem(a[0].front, a[1])) 56 .filter!(a => predicate(a)); 57 // dfmt on 58 } 59 }