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 }