OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 import 'package:yaml/yaml.dart'; | |
6 | |
7 /** | |
8 * Parse the given map into a lint config. | |
9 */ | |
10 LintConfig parseConfig(Map optionsMap) { | |
11 if (optionsMap != null) { | |
12 var options = optionsMap['linter']; | |
13 // Quick check of basic contract. | |
14 if (options is Map) { | |
15 return new LintConfig.parseMap(options); | |
16 } | |
17 } | |
18 return null; | |
19 } | |
20 | |
21 /** | |
22 * Process the given option [fileContents] and produce a corresponding | |
23 * [LintConfig]. | |
24 */ | |
25 LintConfig processAnalysisOptionsFile(String fileContents, {String fileUrl}) { | |
26 var yaml = loadYamlNode(fileContents, sourceUrl: fileUrl); | |
27 if (yaml is YamlMap) { | |
28 return parseConfig(yaml); | |
29 } | |
30 return null; | |
31 } | |
32 | |
33 /** | |
34 * The configuration of lint rules within an analysis options file. | |
35 */ | |
36 abstract class LintConfig { | |
37 factory LintConfig.parse(String source, {String sourceUrl}) => | |
38 new _LintConfig().._parse(source, sourceUrl: sourceUrl); | |
39 | |
40 factory LintConfig.parseMap(Map map) => new _LintConfig().._parseMap(map); | |
41 | |
42 List<String> get fileExcludes; | |
43 List<String> get fileIncludes; | |
44 List<RuleConfig> get ruleConfigs; | |
45 } | |
46 | |
47 /** | |
48 * The configuration of a single lint rule within an analysis options file. | |
49 */ | |
50 abstract class RuleConfig { | |
51 Map<String, dynamic> args = <String, dynamic>{}; | |
52 String get group; | |
53 String get name; | |
54 | |
55 // Provisional | |
56 bool disables(String ruleName) => | |
57 ruleName == name && args['enabled'] == false; | |
58 | |
59 bool enables(String ruleName) => ruleName == name && args['enabled'] == true; | |
60 } | |
61 | |
62 class _LintConfig implements LintConfig { | |
63 @override | |
64 final fileIncludes = <String>[]; | |
65 @override | |
66 final fileExcludes = <String>[]; | |
67 @override | |
68 final ruleConfigs = <RuleConfig>[]; | |
69 | |
70 void addAsListOrString(value, List<String> list) { | |
71 if (value is List) { | |
72 value.forEach((v) => list.add(v)); | |
73 } else if (value is String) { | |
74 list.add(value); | |
75 } | |
76 } | |
77 | |
78 bool asBool(scalar) { | |
79 if (scalar is bool) { | |
80 return scalar; | |
81 } | |
82 if (scalar is String) { | |
83 if (scalar == 'true') { | |
84 return true; | |
85 } | |
86 if (scalar == 'false') { | |
87 return false; | |
88 } | |
89 } | |
90 return null; | |
91 } | |
92 | |
93 String asString(scalar) { | |
94 if (scalar is String) { | |
95 return scalar; | |
96 } | |
97 return null; | |
98 } | |
99 | |
100 Map<String, dynamic> parseArgs(args) { | |
101 bool enabled = asBool(args); | |
102 if (enabled != null) { | |
103 return {'enabled': enabled}; | |
104 } | |
105 return null; | |
106 } | |
107 | |
108 void _parse(String src, {String sourceUrl}) { | |
109 var yaml = loadYamlNode(src, sourceUrl: sourceUrl); | |
110 if (yaml is YamlMap) { | |
111 _parseYaml(yaml); | |
112 } | |
113 } | |
114 | |
115 void _parseMap(Map options) { | |
116 //TODO(pq): unify map parsing. | |
117 if (options is YamlMap) { | |
118 _parseYaml(options); | |
119 } else { | |
120 _parseRawMap(options); | |
121 } | |
122 } | |
123 | |
124 void _parseRawMap(Map options) { | |
125 options.forEach((k, v) { | |
126 if (k is! String) { | |
127 return; | |
128 } | |
129 String key = k; | |
130 switch (key) { | |
131 case 'files': | |
132 if (v is Map) { | |
133 addAsListOrString(v['include'], fileIncludes); | |
134 addAsListOrString(v['exclude'], fileExcludes); | |
135 } | |
136 break; | |
137 | |
138 case 'rules': | |
139 // - unnecessary_getters | |
140 // - camel_case_types | |
141 if (v is List) { | |
142 v.forEach((rule) { | |
143 var config = new _RuleConfig(); | |
144 config.name = asString(rule); | |
145 config.args = {'enabled': true}; | |
146 ruleConfigs.add(config); | |
147 }); | |
148 } | |
149 | |
150 // {unnecessary_getters: false, camel_case_types: true} | |
151 if (v is Map) { | |
152 v.forEach((key, value) { | |
153 // style_guide: {unnecessary_getters: false, camel_case_types: tru
e} | |
154 if (value is Map) { | |
155 value.forEach((rule, args) { | |
156 // unnecessary_getters: false | |
157 var config = new _RuleConfig(); | |
158 config.group = key; | |
159 config.name = asString(rule); | |
160 config.args = parseArgs(args); | |
161 ruleConfigs.add(config); | |
162 }); | |
163 } else { | |
164 //{unnecessary_getters: false} | |
165 value = asBool(value); | |
166 if (value != null) { | |
167 var config = new _RuleConfig(); | |
168 config.name = asString(key); | |
169 config.args = {'enabled': value}; | |
170 ruleConfigs.add(config); | |
171 } | |
172 } | |
173 }); | |
174 } | |
175 break; | |
176 } | |
177 }); | |
178 } | |
179 | |
180 void _parseYaml(YamlMap yaml) { | |
181 yaml.nodes.forEach((k, v) { | |
182 if (k is! YamlScalar) { | |
183 return; | |
184 } | |
185 YamlScalar key = k; | |
186 switch (key.toString()) { | |
187 case 'files': | |
188 if (v is YamlMap) { | |
189 addAsListOrString(v['include'], fileIncludes); | |
190 addAsListOrString(v['exclude'], fileExcludes); | |
191 } | |
192 break; | |
193 | |
194 case 'rules': | |
195 | |
196 // - unnecessary_getters | |
197 // - camel_case_types | |
198 if (v is List) { | |
199 (v as List).forEach((rule) { | |
200 var config = new _RuleConfig(); | |
201 config.name = asString(rule); | |
202 config.args = {'enabled': true}; | |
203 ruleConfigs.add(config); | |
204 }); | |
205 } | |
206 | |
207 // style_guide: {unnecessary_getters: false, camel_case_types: true} | |
208 if (v is YamlMap) { | |
209 v.forEach((key, value) { | |
210 //{unnecessary_getters: false} | |
211 if (value is bool) { | |
212 var config = new _RuleConfig(); | |
213 config.name = asString(key); | |
214 config.args = {'enabled': value}; | |
215 ruleConfigs.add(config); | |
216 } | |
217 | |
218 // style_guide: {unnecessary_getters: false, camel_case_types: tru
e} | |
219 if (value is YamlMap) { | |
220 value.forEach((rule, args) { | |
221 // TODO: verify format | |
222 // unnecessary_getters: false | |
223 var config = new _RuleConfig(); | |
224 config.group = key; | |
225 config.name = asString(rule); | |
226 config.args = parseArgs(args); | |
227 ruleConfigs.add(config); | |
228 }); | |
229 } | |
230 }); | |
231 } | |
232 break; | |
233 } | |
234 }); | |
235 } | |
236 } | |
237 | |
238 class _RuleConfig extends RuleConfig { | |
239 @override | |
240 String group; | |
241 @override | |
242 String name; | |
243 } | |
OLD | NEW |