1 /**
2 Copyright: Copyright (c) 2018, 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.mutate.backend.database.type;
11 
12 import core.time : Duration;
13 import std.datetime : SysTime;
14 
15 import dextool.type : AbsolutePath, Path;
16 import dextool.plugin.mutate.backend.type;
17 
18 import sumtype;
19 
20 @safe:
21 
22 /// Primary key in the database
23 struct Pkey(Pkeys T) {
24     long payload;
25     alias payload this;
26 }
27 
28 enum Pkeys {
29     mutationId,
30     fileId,
31     testCaseId,
32     mutationStatusId,
33 }
34 
35 /// Primary key in the mutation table
36 alias MutationId = Pkey!(Pkeys.mutationId);
37 
38 /// Primary key for mutation status
39 alias MutationStatusId = Pkey!(Pkeys.mutationStatusId);
40 
41 /// Primary key in the files table
42 alias FileId = Pkey!(Pkeys.fileId);
43 
44 /// Primary key in the test_case table
45 alias TestCaseId = Pkey!(Pkeys.testCaseId);
46 
47 struct MutationEntry {
48     MutationId id;
49     Path file;
50     SourceLoc sloc;
51     MutationPoint mp;
52     Duration timeSpentMutating;
53     Language lang;
54 }
55 
56 struct NextMutationEntry {
57     import std.typecons : Nullable;
58 
59     enum Status {
60         /// Mutant retrieved.
61         ok,
62         /// All mutants tested.
63         done,
64     }
65 
66     Status st;
67     Nullable!MutationEntry entry;
68 }
69 
70 struct MutationPointEntry {
71     MutationPoint mp;
72     Path file;
73     /// Start of the mutation point.
74     SourceLoc sloc;
75     /// End of the mutation point.
76     SourceLoc slocEnd;
77 }
78 
79 /// The source code mutations for a mutation point.
80 struct MutationPointEntry2 {
81     Path file;
82     Offset offset;
83     /// Start of the mutation point.
84     SourceLoc sloc;
85     /// End of the mutation point.
86     SourceLoc slocEnd;
87     CodeMutant[] cms;
88 
89     void put(CodeMutant m) @safe pure nothrow {
90         cms ~= m;
91     }
92 }
93 
94 /// Report about mutants of a specific kind(s).
95 struct MutationReportEntry {
96     ///
97     long count;
98     /// Test time spent on the mutants.
99     Duration time;
100 }
101 
102 /// Mutants that are tagged with nomut of a specific kind(s).
103 struct MetadataNoMutEntry {
104     ///
105     long count;
106 }
107 
108 struct MutantInfo {
109     MutationId id;
110     Mutation.Status status;
111     Mutation.Kind kind;
112     SourceLoc sloc;
113 }
114 
115 struct TestCaseInfo {
116     /// The sum on the execution time of killing the mutants.
117     Duration time;
118     ///
119     long killedMutants;
120 }
121 
122 struct MutationStatusTime {
123     import std.datetime : SysTime;
124 
125     MutationStatusId id;
126     SysTime updated;
127 }
128 
129 struct MutationStatus {
130     import std.datetime : SysTime;
131     import std.typecons : Nullable;
132 
133     MutationStatusId statusId;
134     Mutation.Status status;
135     MutantTestCount testCnt;
136     SysTime updated;
137     Nullable!SysTime added;
138 }
139 
140 // TODO: rename to LineMetaData.
141 /// Metadata about a line in a file.
142 struct LineMetadata {
143     FileId id;
144     uint line;
145     LineAttr attr;
146 
147     this(FileId fid, uint line) {
148         this(fid, line, LineAttr.init);
149     }
150 
151     this(FileId fid, uint line, LineAttr attr) {
152         this.id = fid;
153         this.line = line;
154         this.attr = attr;
155     }
156 
157     void set(NoMut a) @safe pure nothrow @nogc {
158         attr = LineAttr(a);
159     }
160 
161     bool isNoMut() @safe pure nothrow const @nogc {
162         return attr.match!((NoMetadata a) => false, (NoMut a) => true);
163     }
164 }
165 
166 struct NoMetadata {
167 }
168 
169 /// A mutation suppression with optional tag and comment.
170 struct NoMut {
171     string tag;
172     string comment;
173 }
174 
175 /// Metadata attributes that may be attached to a mutant.
176 alias MutantAttr = SumType!(NoMetadata, NoMut);
177 
178 /// Metadata attributes that may be attached to a line.
179 alias LineAttr = SumType!(NoMetadata, NoMut);
180 
181 /// Metadata about a mutant.
182 struct MutantMetaData {
183     import std.range : isOutputRange;
184 
185     MutationId id;
186     MutantAttr attr;
187 
188     this(MutationId id) {
189         this(id, MutantAttr.init);
190     }
191 
192     this(MutationId id, MutantAttr attr) {
193         this.id = id;
194         this.attr = attr;
195     }
196 
197     void set(NoMut a) @safe pure nothrow @nogc {
198         attr = MutantAttr(a);
199     }
200 
201     bool isNoMut() @safe pure nothrow const @nogc {
202         return attr.match!((NoMetadata a) => false, (NoMut a) => true);
203     }
204 
205     string kindToString() @safe pure const {
206         import std.array : appender;
207         import std.format : FormatSpec;
208 
209         auto buf = appender!string;
210         kindToString(buf);
211         return buf.data;
212     }
213 
214     void kindToString(Writer)(ref Writer w) const if (isOutputRange!(Writer, char)) {
215         import std.range : put;
216 
217         attr.match!((NoMetadata a) {}, (NoMut a) => put(w, "nomut"));
218     }
219 }