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.report.html.page_nomut;
11 
12 import logger = std.experimental.logger;
13 import std.format : format;
14 
15 import arsd.dom : Document, Element, require, Table;
16 
17 import dextool.plugin.mutate.backend.database : Database, MutantMetaData;
18 import dextool.plugin.mutate.backend.report.html.constants;
19 import dextool.plugin.mutate.backend.report.html.tmpl : tmplBasicPage,
20     dashboardCss, tmplDefaultTable;
21 import dextool.plugin.mutate.backend.report.utility;
22 import dextool.plugin.mutate.backend.type : Mutation;
23 import dextool.plugin.mutate.config : ConfigReport;
24 import dextool.plugin.mutate.type : MutationKind;
25 import dextool.type : AbsolutePath;
26 
27 auto makeNomut(ref Database db, ref const ConfigReport conf,
28         const(MutationKind)[] humanReadableKinds, const(Mutation.Kind)[] kinds) @trusted {
29     import std.datetime : Clock;
30 
31     auto doc = tmplBasicPage.dashboardCss;
32     doc.title(format("NoMut Details %(%s %) %s", humanReadableKinds, Clock.currTime));
33     doc.mainBody.addChild("p",
34             "This is all the mutation suppressions that are used and affects the analysis.");
35 
36     db.mutantApi.getMutantationMetaData(kinds, Mutation.Status.alive).toHtml(db, doc.mainBody);
37 
38     return doc.toPrettyString;
39 }
40 
41 private:
42 
43 // TODO: this is very inefficient implementation. There are so many lookups in
44 // the database. It "works" as long as there are only a limited amount of
45 // nomut.
46 void toHtml(MutantMetaData[] data, ref Database db, Element root) {
47     import std.algorithm : sort, map;
48     import std.array : array, empty;
49     import std.path : buildPath;
50     import std.typecons : Tuple;
51     import std.uni : toLower;
52     import sumtype;
53     import dextool.plugin.mutate.backend.database : MutationId, NoMetadata, NoMut;
54     import dextool.plugin.mutate.backend.report.html.utility : pathToHtmlLink;
55 
56     alias IdComment = Tuple!(MutationId, "id", string, "comment");
57     string[MutationId][string] tags;
58 
59     // group by the tag that can be added to a nomut via
60     // // NOMUT (tag) <comment>
61     foreach (x; data) {
62         x.attr.match!((NoMetadata a) {}, (NoMut a) {
63             if (auto v = a.tag.toLower in tags) {
64                 (*v)[x.id] = a.comment;
65             } else {
66                 tags[a.tag.toLower] = [x.id: a.comment];
67             }
68         });
69     }
70 
71     foreach (tag; tags.byKey.array.sort) {
72         if (!tag.empty)
73             root.addChild("h2", tag);
74 
75         auto tbl = tmplDefaultTable(root, ["Mutant"]);
76         foreach (m; tags[tag].byKeyValue
77                 .map!(a => IdComment(a.key, a.value))
78                 .array
79                 .sort!((a, b) => a.comment < b.comment)) {
80             auto r = tbl.appendRow();
81 
82             auto file = db.mutantApi.getPath(m.id);
83             if (file.isNull)
84                 continue;
85 
86             auto td = r.addChild("td");
87             td.addChild("a", file.get).href = format("%s#%s",
88                     buildPath(Html.fileDir, pathToHtmlLink(file.get)), m.id);
89             td.addChild("br");
90             td.appendText(m.comment);
91         }
92     }
93 }