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 module dextool.plugin.analyze.filerange;
11 
12 import dextool.compilation_db : CompileCommandFilter, CompileCommandDB, parseFlag;
13 import dextool.type : FileName, AbsolutePath;
14 
15 @safe:
16 
17 struct AnalyzeFileRange {
18     import std.typecons : Nullable;
19     import dextool.clang : findFlags;
20     import dextool.compilation_db : SearchResult;
21 
22     enum RangeOver {
23         inFiles,
24         database
25     }
26 
27     this(CompileCommandDB db, string[] in_files, string[] cflags,
28             const CompileCommandFilter ccFilter) {
29         this.db = db;
30         this.cflags = cflags;
31         this.ccFilter = ccFilter;
32         this.inFiles = in_files;
33 
34         if (in_files.length == 0) {
35             kind = RangeOver.database;
36         } else {
37             kind = RangeOver.inFiles;
38         }
39     }
40 
41     const RangeOver kind;
42     CompileCommandDB db;
43     string[] inFiles;
44     string[] cflags;
45     const CompileCommandFilter ccFilter;
46 
47     Nullable!SearchResult front() {
48         assert(!empty, "Can't get front of an empty range");
49 
50         Nullable!SearchResult curr;
51 
52         final switch (kind) {
53         case RangeOver.inFiles:
54             if (db.length > 0) {
55                 curr = db.findFlags(FileName(inFiles[0]), cflags, ccFilter);
56             } else {
57                 curr = SearchResult(cflags.dup, AbsolutePath(FileName(inFiles[0])));
58             }
59             break;
60         case RangeOver.database:
61             import std.array : appender;
62 
63             auto tmp = db.payload[0];
64             auto flags = appender!(string[])();
65             flags.put(cflags);
66             flags.put(tmp.parseFlag(ccFilter).completeFlags);
67             curr = SearchResult(flags.data, tmp.absoluteFile);
68             break;
69         }
70 
71         return curr;
72     }
73 
74     void popFront() {
75         assert(!empty, "Can't pop front of an empty range");
76 
77         final switch (kind) {
78         case RangeOver.inFiles:
79             inFiles = inFiles[1 .. $];
80             break;
81         case RangeOver.database:
82             db.payload = db.payload[1 .. $];
83             break;
84         }
85     }
86 
87     bool empty() @safe pure nothrow const @nogc {
88         final switch (kind) {
89         case RangeOver.inFiles:
90             return inFiles.length == 0;
91         case RangeOver.database:
92             return db.length == 0;
93         }
94     }
95 
96     size_t length() @safe pure nothrow const @nogc {
97         final switch (kind) {
98         case RangeOver.inFiles:
99             return inFiles.length;
100         case RangeOver.database:
101             return db.length;
102         }
103     }
104 }