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 /// Returns a config with all the checks disabled.
44 StaticAnalysisConfig disabledConfig()
45 {
46 	StaticAnalysisConfig config;
47 	foreach (mem; __traits(allMembers, StaticAnalysisConfig))
48 	{
49 		static if (is(typeof(__traits(getMember, StaticAnalysisConfig, mem))))
50 		static if (is(typeof(__traits(getMember, config, mem)) == string))
51 			__traits(getMember, config, mem) = Check.disabled;
52 	}
53 	return config;
54 }
55 
56 @INI("Configure which static analysis checks are enabled", "analysis.config.StaticAnalysisConfig")
57 struct StaticAnalysisConfig
58 {
59 	@INI("Check variable, class, struct, interface, union, and function names against the Phobos style guide")
60 	string style_check = Check.enabled;
61 
62 	@INI("Check for array literals that cause unnecessary allocation")
63 	string enum_array_literal_check = Check.enabled;
64 
65 	@INI("Check for poor exception handling practices")
66 	string exception_check = Check.enabled;
67 
68 	@INI("Check for use of the deprecated 'delete' keyword")
69 	string delete_check = Check.enabled;
70 
71 	@INI("Check for use of the deprecated floating point operators")
72 	string float_operator_check = Check.enabled;
73 
74 	@INI("Check number literals for readability")
75 	string number_style_check = Check.enabled;
76 
77 	@INI("Checks that opEquals, opCmp, toHash, and toString are either const, immutable, or inout.")
78 	string object_const_check = Check.enabled;
79 
80 	@INI("Checks for .. expressions where the left side is larger than the right.")
81 	string backwards_range_check = Check.enabled;
82 
83 	@INI("Checks for if statements whose 'then' block is the same as the 'else' block")
84 	string if_else_same_check = Check.enabled;
85 
86 	@INI("Checks for some problems with constructors")
87 	string constructor_check = Check.enabled;
88 
89 	@INI("Checks for unused variables and function parameters")
90 	string unused_variable_check = Check.enabled;
91 
92 	@INI("Checks for unused labels")
93 	string unused_label_check = Check.enabled;
94 
95 	@INI("Checks for duplicate attributes")
96 	string duplicate_attribute = Check.enabled;
97 
98 	@INI("Checks that opEquals and toHash are both defined or neither are defined")
99 	string opequals_tohash_check = Check.enabled;
100 
101 	@INI("Checks for subtraction from .length properties")
102 	string length_subtraction_check = Check.enabled;
103 
104 	@INI("Checks for methods or properties whose names conflict with built-in properties")
105 	string builtin_property_names_check = Check.enabled;
106 
107 	@INI("Checks for confusing code in inline asm statements")
108 	string asm_style_check = Check.enabled;
109 
110 	@INI("Checks for confusing logical operator precedence")
111 	string logical_precedence_check = Check.enabled;
112 
113 	@INI("Checks for undocumented public declarations")
114 	string undocumented_declaration_check = Check.enabled;
115 
116 	@INI("Checks for poor placement of function attributes")
117 	string function_attribute_check = Check.enabled;
118 
119 	@INI("Checks for use of the comma operator")
120 	string comma_expression_check = Check.enabled;
121 
122 	@INI("Checks for local imports that are too broad")
123 	string local_import_check = Check.enabled;
124 
125 	@INI("Checks for variables that could be declared immutable")
126 	string could_be_immutable_check = Check.enabled;
127 
128 	@INI("Checks for redundant expressions in if statements")
129 	string redundant_if_check = Check.enabled;
130 
131 	@INI("Checks for redundant parenthesis")
132 	string redundant_parens_check = Check.enabled;
133 
134 	@INI("Checks for mismatched argument and parameter names")
135 	string mismatched_args_check = Check.enabled;
136 
137 	@INI("Checks for labels with the same name as variables")
138 	string label_var_same_name_check = Check.enabled;
139 
140 	@INI("Checks for lines longer than 120 characters")
141 	string long_line_check = Check.enabled;
142 
143 	@INI("Checks for assignment to auto-ref function parameters")
144 	string auto_ref_assignment_check = Check.enabled;
145 
146 	@INI("Checks for incorrect infinite range definitions")
147 	string incorrect_infinite_range_check = Check.enabled;
148 
149 	@INI("Checks for asserts that are always true")
150 	string useless_assert_check = Check.enabled;
151 
152 	@INI("Check for uses of the old-style alias syntax")
153 	string alias_syntax_check = Check.enabled;
154 
155 	@INI("Checks for else if that should be else static if")
156 	string static_if_else_check = Check.enabled;
157 
158 	@INI("Check for unclear lambda syntax")
159 	string lambda_return_check = Check.enabled;
160 
161 	@INI("Check for auto function without return statement")
162 	string auto_function_check = Check.enabled;
163 
164 	@INI("Check for sortedness of imports")
165 	string imports_sortedness = Check.disabled;
166 
167 	@INI("Check for explicitly annotated unittests")
168 	string explicitly_annotated_unittests = Check.disabled;
169 
170 	@INI("Check for properly documented public functions (Returns, Params)")
171 	string properly_documented_public_functions = Check.disabled;
172 
173 	@INI("Check for useless usage of the final attribute")
174 	string final_attribute_check = Check.enabled;
175 
176 	@INI("Check for virtual calls in the class constructors")
177 	string vcall_in_ctor = Check.enabled;
178 
179 	@INI("Check for useless user defined initializers")
180 	string useless_initializer = Check.enabled;
181 
182 	@INI("Check allman brace style")
183 	string allman_braces_check = Check.disabled;
184 
185 	@INI("Check for redundant attributes")
186 	string redundant_attributes_check = Check.enabled;
187 
188 	@INI("Check public declarations without a documented unittest")
189 	string has_public_example = Check.disabled;
190 
191 	@INI("Check for asserts without an explanatory message")
192 	string assert_without_msg = Check.disabled;
193 
194 	@INI("Check indent of if constraints")
195 	string if_constraints_indent = Check.disabled;
196 
197 	@INI("Check for @trusted applied to a bigger scope than a single function")
198 	string trust_too_much = Check.enabled;
199 
200 	@INI("Check for redundant storage classes on variable declarations")
201 	string redundant_storage_classes = Check.enabled;
202 
203 	@INI("Module-specific filters")
204 	ModuleFilters filters;
205 }
206 
207 private template ModuleFiltersMixin(A)
208 {
209 	const string ModuleFiltersMixin = () {
210 		string s;
211 		foreach (mem; __traits(allMembers, StaticAnalysisConfig))
212 			static if (is(typeof(__traits(getMember, StaticAnalysisConfig, mem)) == string))
213 				s ~= `@INI("Exclude/Import modules") string[] ` ~ mem ~ ";\n";
214 
215 		return s;
216 	}();
217 }
218 
219 @INI("ModuleFilters for selectively enabling (+std) and disabling (-std.internal) individual checks", "analysis.config.ModuleFilters")
220 struct ModuleFilters
221 {
222 	mixin(ModuleFiltersMixin!int);
223 }