1 /*
2  *Copyright (C) 2018 Laurent Tréguier
3  *
4  *This file is part of DLS.
5  *
6  *DLS is free software: you can redistribute it and/or modify
7  *it under the terms of the GNU 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  *DLS 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 General Public License for more details.
15  *
16  *You should have received a copy of the GNU General Public License
17  *along with DLS.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 module dls.tools.configuration;
22 
23 class Configuration
24 {
25     import std.json : JSONValue;
26 
27     static class SymbolConfiguration
28     {
29         string[] importPaths;
30         bool listLocalSymbols;
31     }
32 
33     static class AnalysisConfiguration
34     {
35         string configFile = "dscanner.ini";
36         string[] filePatterns = [];
37     }
38 
39     static class FormatConfiguration
40     {
41         static enum Engine : string
42         {
43             dfmt = "dfmt",
44             builtin = "builtin"
45         }
46 
47         static enum BraceStyle : string
48         {
49             allman = "allman",
50             otbs = "otbs",
51             stroustrup = "stroustrup"
52         }
53 
54         static enum EndOfLine : string
55         {
56             lf = "lf",
57             cr = "cr",
58             crlf = "crlf"
59         }
60 
61         static enum TemplateConstraintsStyle : string
62         {
63             conditionalNewlineIndent = "conditionalNewlineIndent",
64             conditionalNewline = "conditionalNewline",
65             alwaysNewline = "alwaysNewline",
66             alwaysNewlineIndent = "alwaysNewlineIndent"
67         }
68 
69         Engine engine = Engine.dfmt;
70         EndOfLine endOfLine = EndOfLine.lf;
71         bool insertFinalNewline = true;
72         bool trimTrailingWhitespace = true;
73         int maxLineLength = 120;
74         int softMaxLineLength = 80;
75         BraceStyle braceStyle = BraceStyle.allman;
76         bool spaceAfterCasts = true;
77         bool spaceAfterKeywords = true;
78         bool spaceBeforeAAColons = false;
79         bool spaceBeforeFunctionParameters = false;
80         bool spaceBeforeSelectiveImportColons = true;
81         bool alignSwitchStatements = true;
82         bool compactLabeledStatements = true;
83         bool outdentAttributes = true;
84         bool splitOperatorsAtLineEnd = false;
85         TemplateConstraintsStyle templateConstraintsStyle = TemplateConstraintsStyle
86             .conditionalNewlineIndent;
87         bool templateConstraintsSingleIndent = false;
88     }
89 
90     SymbolConfiguration symbol;
91     AnalysisConfiguration analysis;
92     FormatConfiguration format;
93 
94     this()
95     {
96         symbol = new SymbolConfiguration();
97         analysis = new AnalysisConfiguration();
98         format = new FormatConfiguration();
99     }
100 
101     void merge(JSONValue json)
102     {
103         merge!(typeof(this))(json);
104     }
105 
106     private void merge(T)(JSONValue json)
107     {
108         import dls.util.json : convertFromJSON;
109         import std.json : JSONType;
110         import std.meta : Alias;
111         import std.traits : isSomeFunction, isType;
112 
113         if (json.type != JSONType.object)
114         {
115             return;
116         }
117 
118         foreach (member; __traits(allMembers, T))
119         {
120             if (member !in json)
121             {
122                 continue;
123             }
124 
125             alias m = Alias!(__traits(getMember, T, member));
126 
127             static if (!isType!(m) && !isSomeFunction!(m))
128             {
129                 static if (is(m == class))
130                 {
131                     merge(m, json[member]);
132                 }
133                 else
134                 {
135                     m = convertFromJSON!(typeof(m))(json[member]);
136                 }
137             }
138         }
139     }
140 }