source: appstream-generator/src/asgen/hint.d @ 4841

Last change on this file since 4841 was 4841, checked in by Juanma, 2 years ago

Initial release

File size: 5.3 KB
Line 
1/*
2 * Copyright (C) 2016 Matthias Klumpp <matthias@tenstral.net>
3 *
4 * Licensed under the GNU Lesser General Public License Version 3
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the license, or
9 * (at your option) any later version.
10 *
11 * This software is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this software.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20module asgen.hint;
21
22import std.stdio;
23import std.string;
24import std.json;
25
26import asgen.logging;
27import asgen.utils;
28
29alias HintList = GeneratorHint[];
30
31/**
32 * Severity assigned with an issue hint.
33 *
34 * INFO:    Information, no immediate action needed (but will likely be an issue later).
35 * WARNING: An issue which did not prevent generating meaningful data, but which is still serious
36 *          and should be fixed (warning of this kind usually result in less data).
37 * ERROR:   A fatal error which resulted in the component being excluded from the final metadata.
38 */
39enum HintSeverity
40{
41    UNKNOWN,
42    INFO,
43    WARNING,
44    ERROR
45}
46
47@safe
48private HintSeverity severityFromString (string str) pure
49{
50    switch (str) {
51        case "error":
52            return HintSeverity.ERROR;
53        case "warning":
54            return HintSeverity.WARNING;
55        case "info":
56            return HintSeverity.INFO;
57        default:
58            return HintSeverity.UNKNOWN;
59    }
60}
61
62final class GeneratorHint
63{
64
65private:
66    string tag;
67    string cid;
68
69    string[string] vars;
70
71    HintSeverity severity;
72
73public:
74
75    @trusted
76    this (string tag, string cid = null)
77    {
78        this.tag = tag;
79        this.cid = cid;
80
81        severity = HintsStorage.get ().getSeverity (tag);
82        if (severity == HintSeverity.UNKNOWN)
83            logWarning ("Severity of hint tag '%s' is unknown. This likely means that this tag is not registered and should not be emitted.", tag);
84    }
85
86    @safe
87    bool isError () pure
88    {
89        return severity == HintSeverity.ERROR;
90    }
91
92    @safe
93    void setVars (string[string] vars) pure
94    {
95        this.vars = vars;
96    }
97
98    @safe
99    auto toJsonNode () pure
100    {
101        JSONValue json = JSONValue(["tag":  JSONValue (tag),
102                                    "vars": JSONValue (vars)
103                                   ]);
104        return json;
105    }
106}
107
108/**
109 * Singleton holding information about the hint tags we know about.
110 **/
111final class HintsStorage
112{
113    // Thread local
114    private static bool instantiated_;
115
116    // Thread global
117    private __gshared HintsStorage instance_;
118
119    static HintsStorage get()
120    {
121        if (!instantiated_) {
122            synchronized (HintsStorage.classinfo) {
123                if (!instance_)
124                    instance_ = new HintsStorage ();
125
126                instantiated_ = true;
127            }
128        }
129
130        return instance_;
131    }
132
133    struct HintDefinition
134    {
135        string tag;
136        string text;
137        HintSeverity severity;
138        bool internal;
139    }
140
141    private HintDefinition[string] hintDefs;
142
143    @trusted
144    private this ()
145    {
146        import std.path;
147        static import std.file;
148
149        // find the hint definition file
150        auto hintsDefFile = getDataPath ("asgen-hints.json");
151        if (!std.file.exists (hintsDefFile)) {
152            logError ("Hints definition file '%s' was not found! This means we can not determine severity of issue tags and not render report pages.", hintsDefFile);
153            return;
154        }
155
156        // read the hints definition JSON file
157        auto f = File (hintsDefFile, "r");
158        string jsonData;
159        string line;
160        while ((line = f.readln ()) !is null)
161            jsonData ~= line;
162
163        auto hintDefsJSON = parseJSON (jsonData);
164
165        foreach (tag; hintDefsJSON.object.byKey ()) {
166            auto j = hintDefsJSON[tag];
167            auto def = HintDefinition ();
168
169            def.tag = tag;
170            def.severity = severityFromString (j["severity"].str);
171
172            if (j["text"].type == JSON_TYPE.ARRAY) {
173                foreach (l; j["text"].array)
174                    def.text ~= l.str ~ "\n";
175            } else {
176                def.text = j["text"].str;
177            }
178
179            if ("internal" in j)
180                def.internal = j["internal"].type == JSON_TYPE.TRUE;
181
182            hintDefs[tag] = def;
183        }
184    }
185
186    @safe
187    HintDefinition getHintDef (string tag) pure
188    {
189        auto defP = (tag in hintDefs);
190        if (defP is null)
191            return HintDefinition ();
192        return *defP;
193    }
194
195    @safe
196    HintSeverity getSeverity (string tag) pure
197    {
198        auto hDef = getHintDef (tag);
199        return hDef.severity;
200    }
201}
202
203unittest
204{
205    writeln ("TEST: ", "Issue Hints");
206
207    auto hint = new GeneratorHint ("just-a-unittest", "org.freedesktop.foobar.desktop");
208    hint.vars = ["rainbows": "yes", "unicorns": "no", "storage": "towel"];
209    auto root = hint.toJsonNode ();
210
211    writeln (toJSON (&root, true));
212
213    HintsStorage.get ();
214}
Note: See TracBrowser for help on using the repository browser.