1 //          Copyright Brian Schott (Hackerpilot) 2014.
2 // Distributed under the Boost Software License, Version 1.0.
3 //    (See accompanying file LICENSE_1_0.txt or copy at
4 //          http://www.boost.org/LICENSE_1_0.txt)
5 
6 module dscanner.analysis.config;
7 
8 import inifiled;
9 
10 /// Returns: A default configuration.
11 StaticAnalysisConfig defaultStaticAnalysisConfig()
12 {
13 	StaticAnalysisConfig config;
14 	return config;
15 }
16 
17 /// Describes how a check is operated.
18 enum Check: string
19 {
20     /// Check is disabled.
21     disabled    = "disabled",
22     /// Check is enabled.
23     enabled     = "enabled",
24     /// Check is enabled but not operated in the unittests.
25     skipTests   = "skip-unittest"
26 }
27 
28 /// Applies the --skipTests switch, allowing to call Dscanner without config
29 /// and less noise related to the unittests.
30 void enabled2SkipTests(ref StaticAnalysisConfig config)
31 {
32     foreach (mem; __traits(allMembers, StaticAnalysisConfig))
33     {
34         static if (is(typeof(__traits(getMember, StaticAnalysisConfig, mem))))
35             static if (is(typeof(__traits(getMember, config, mem)) == string))
36         {
37             if (__traits(getMember, config, mem) == Check.enabled)
38                 __traits(getMember, config, mem) = Check.skipTests;
39 
40         }
41     }
42 }
43 
44 /// Returns a config with all the checks disabled.
45 StaticAnalysisConfig disabledConfig()
46 {
47     StaticAnalysisConfig config;
48     foreach (mem; __traits(allMembers, StaticAnalysisConfig))
49     {
50         static if (is(typeof(__traits(getMember, StaticAnalysisConfig, mem))))
51             static if (is(typeof(__traits(getMember, config, mem)) == string))
52                 __traits(getMember, config, mem) = Check.disabled;
53     }
54     return config;
55 }
56 
57 @INI("Configure which static analysis checks are enabled", "analysis.config.StaticAnalysisConfig")
58 struct StaticAnalysisConfig
59 {
60 	@INI("Check variable, class, struct, interface, union, and function names against the Phobos style guide")
61 	string style_check = Check.enabled;
62 
63 	@INI("Check for array literals that cause unnecessary allocation")
64 	string enum_array_literal_check = Check.enabled;
65 
66 	@INI("Check for poor exception handling practices")
67 	string exception_check = Check.enabled;
68 
69 	@INI("Check for use of the deprecated 'delete' keyword")
70 	string delete_check = Check.enabled;
71 
72 	@INI("Check for use of the deprecated floating point operators")
73 	string float_operator_check = Check.enabled;
74 
75 	@INI("Check number literals for readability")
76 	string number_style_check = Check.enabled;
77 
78 	@INI("Checks that opEquals, opCmp, toHash, and toString are either const, immutable, or inout.")
79 	string object_const_check = Check.enabled;
80 
81 	@INI("Checks for .. expressions where the left side is larger than the right.")
82 	string backwards_range_check = Check.enabled;
83 
84 	@INI("Checks for if statements whose 'then' block is the same as the 'else' block")
85 	string if_else_same_check = Check.enabled;
86 
87 	@INI("Checks for some problems with constructors")
88 	string constructor_check = Check.enabled;
89 
90 	@INI("Checks for unused variables and function parameters")
91 	string unused_variable_check = Check.enabled;
92 
93 	@INI("Checks for unused labels")
94 	string unused_label_check = Check.enabled;
95 
96 	@INI("Checks for duplicate attributes")
97 	string duplicate_attribute = Check.enabled;
98 
99 	@INI("Checks that opEquals and toHash are both defined or neither are defined")
100 	string opequals_tohash_check = Check.enabled;
101 
102 	@INI("Checks for subtraction from .length properties")
103 	string length_subtraction_check = Check.enabled;
104 
105 	@INI("Checks for methods or properties whose names conflict with built-in properties")
106 	string builtin_property_names_check = Check.enabled;
107 
108 	@INI("Checks for confusing code in inline asm statements")
109 	string asm_style_check = Check.enabled;
110 
111 	@INI("Checks for confusing logical operator precedence")
112 	string logical_precedence_check = Check.enabled;
113 
114 	@INI("Checks for undocumented public declarations")
115 	string undocumented_declaration_check = Check.enabled;
116 
117 	@INI("Checks for poor placement of function attributes")
118 	string function_attribute_check = Check.enabled;
119 
120 	@INI("Checks for use of the comma operator")
121 	string comma_expression_check = Check.enabled;
122 
123 	@INI("Checks for local imports that are too broad")
124 	string local_import_check = Check.enabled;
125 
126 	@INI("Checks for variables that could be declared immutable")
127 	string could_be_immutable_check = Check.enabled;
128 
129 	@INI("Checks for redundant expressions in if statements")
130 	string redundant_if_check = Check.enabled;
131 
132 	@INI("Checks for redundant parenthesis")
133 	string redundant_parens_check = Check.enabled;
134 
135 	@INI("Checks for mismatched argument and parameter names")
136 	string mismatched_args_check = Check.enabled;
137 
138 	@INI("Checks for labels with the same name as variables")
139 	string label_var_same_name_check = Check.enabled;
140 
141 	@INI("Checks for lines longer than 120 characters")
142 	string long_line_check = Check.enabled;
143 
144 	@INI("Checks for assignment to auto-ref function parameters")
145 	string auto_ref_assignment_check = Check.enabled;
146 
147 	@INI("Checks for incorrect infinite range definitions")
148 	string incorrect_infinite_range_check = Check.enabled;
149 
150 	@INI("Checks for asserts that are always true")
151 	string useless_assert_check = Check.enabled;
152 
153 	@INI("Check for uses of the old-style alias syntax")
154 	string alias_syntax_check = Check.enabled;
155 
156 	@INI("Checks for else if that should be else static if")
157 	string static_if_else_check = Check.enabled;
158 
159 	@INI("Check for unclear lambda syntax")
160 	string lambda_return_check = Check.enabled;
161 
162 	@INI("Check for auto function without return statement")
163 	string auto_function_check = Check.enabled;
164 
165 	@INI("Check for sortedness of imports")
166 	string imports_sortedness = Check.disabled;
167 
168 	@INI("Check for explicitly annotated unittests")
169 	string explicitly_annotated_unittests = Check.disabled;
170 
171 	@INI("Check for properly documented public functions (Returns, Params)")
172 	string properly_documented_public_functions = Check.disabled;
173 
174     @INI("Check for useless usage of the final attribute")
175     string final_attribute_check = Check.enabled;
176 
177     @INI("Check for virtual calls in the class constructors")
178     string vcall_in_ctor = Check.enabled;
179 
180     @INI("Check for useless user defined initializers")
181     string useless_initializer = Check.enabled;
182 
183 	@INI("Check allman brace style")
184 	string allman_braces_check = Check.disabled;
185 
186 	@INI("Check for redundant attributes")
187 	string redundant_attributes_check = Check.enabled;
188 
189 	@INI("Check public declarations without a documented unittest")
190 	string has_public_example = Check.disabled;
191 
192 	@INI("Check for asserts without an explanatory message")
193 	string assert_without_msg = Check.disabled;
194 
195 	@INI("Check indent of if constraints")
196 	string if_constraints_indent = Check.disabled;
197 
198 	@INI("Module-specific filters")
199 	ModuleFilters filters;
200 }
201 
202 private template ModuleFiltersMixin(A)
203 {
204 	const string ModuleFiltersMixin = () {
205 		string s;
206 		foreach (mem; __traits(allMembers, StaticAnalysisConfig))
207 			static if (is(typeof(__traits(getMember, StaticAnalysisConfig, mem)) == string))
208 				s ~= `@INI("Exclude/Import modules") string[] ` ~ mem ~ ";\n";
209 
210     	return s;
211 	}();
212 }
213 
214 @INI("ModuleFilters. +std.,-std.internal")
215 struct ModuleFilters
216 {
217 	mixin(ModuleFiltersMixin!int);
218 }