OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library analyzer.src.task.options; | 5 library analyzer.src.task.options; |
6 | 6 |
7 import 'package:analyzer/analyzer.dart'; | 7 import 'package:analyzer/analyzer.dart'; |
8 import 'package:analyzer/plugin/options.dart'; | 8 import 'package:analyzer/plugin/options.dart'; |
9 import 'package:analyzer/source/analysis_options_provider.dart'; | 9 import 'package:analyzer/source/analysis_options_provider.dart'; |
10 import 'package:analyzer/src/generated/engine.dart'; | 10 import 'package:analyzer/src/generated/engine.dart'; |
11 import 'package:analyzer/src/generated/java_engine.dart'; | 11 import 'package:analyzer/src/generated/java_engine.dart'; |
12 import 'package:analyzer/src/generated/source.dart'; | 12 import 'package:analyzer/src/generated/source.dart'; |
13 import 'package:analyzer/src/task/general.dart'; | 13 import 'package:analyzer/src/task/general.dart'; |
14 import 'package:analyzer/task/general.dart'; | 14 import 'package:analyzer/task/general.dart'; |
15 import 'package:analyzer/task/model.dart'; | 15 import 'package:analyzer/task/model.dart'; |
16 import 'package:source_span/source_span.dart'; | 16 import 'package:source_span/source_span.dart'; |
17 import 'package:yaml/yaml.dart'; | 17 import 'package:yaml/yaml.dart'; |
18 | 18 |
19 /// The errors produced while parsing `.analysis_options` files. | 19 /// The errors produced while parsing `.analysis_options` files. |
20 /// | 20 /// |
21 /// The list will be empty if there were no errors, but will not be `null`. | 21 /// The list will be empty if there were no errors, but will not be `null`. |
22 final ListResultDescriptor<AnalysisError> ANALYSIS_OPTIONS_ERRORS = | 22 final ListResultDescriptor<AnalysisError> ANALYSIS_OPTIONS_ERRORS = |
23 new ListResultDescriptor<AnalysisError>( | 23 new ListResultDescriptor<AnalysisError>( |
24 'ANALYSIS_OPTIONS_ERRORS', AnalysisError.NO_ERRORS); | 24 'ANALYSIS_OPTIONS_ERRORS', AnalysisError.NO_ERRORS); |
25 | 25 |
26 /// `analyzer` analysis options constants. | 26 /// `analyzer` analysis options constants. |
27 class AnalyzerOptions { | 27 class AnalyzerOptions { |
| 28 static const String analyzer = 'analyzer'; |
28 static const String errors = 'errors'; | 29 static const String errors = 'errors'; |
29 static const String exclude = 'exclude'; | 30 static const String exclude = 'exclude'; |
30 static const String plugins = 'plugins'; | 31 static const String plugins = 'plugins'; |
31 static const String strong_mode = 'strong-mode'; | 32 static const String strong_mode = 'strong-mode'; |
32 | 33 |
33 /// Ways to say `ignore`. | 34 /// Ways to say `ignore`. |
34 static const List<String> ignoreSynonyms = const ['ignore', 'false']; | 35 static const List<String> ignoreSynonyms = const ['ignore', 'false']; |
35 | 36 |
| 37 /// Ways to say `include`. |
| 38 static const List<String> includeSynonyms = const ['include', 'true']; |
| 39 |
36 /// Supported top-level `analyzer` options. | 40 /// Supported top-level `analyzer` options. |
37 static const List<String> top_level = const [ | 41 static const List<String> top_level = const [ |
38 errors, | 42 errors, |
39 exclude, | 43 exclude, |
40 plugins, | 44 plugins, |
41 strong_mode | 45 strong_mode |
42 ]; | 46 ]; |
43 } | 47 } |
44 | 48 |
| 49 /// Validates `analyzer` error filter options. |
| 50 class ErrorFilterOptionValidator extends OptionsValidator { |
| 51 /// Pretty list of legal includes. |
| 52 static final String legalIncludes = StringUtilities.printListOfQuotedNames( |
| 53 new List.from(AnalyzerOptions.ignoreSynonyms) |
| 54 ..addAll(AnalyzerOptions.includeSynonyms)); |
| 55 |
| 56 @override |
| 57 void validate(ErrorReporter reporter, Map<String, YamlNode> options) { |
| 58 YamlMap analyzer = options[AnalyzerOptions.analyzer]; |
| 59 if (analyzer == null) { |
| 60 // No options for analyzer. |
| 61 return; |
| 62 } |
| 63 |
| 64 YamlNode filters = analyzer[AnalyzerOptions.errors]; |
| 65 |
| 66 if (filters is YamlMap) { |
| 67 String value; |
| 68 filters.nodes.forEach((k, v) { |
| 69 if (k is YamlScalar) { |
| 70 value = k.value?.toString()?.toUpperCase(); |
| 71 if (!ErrorCode.values.any((ErrorCode code) => code.name == value)) { |
| 72 reporter.reportErrorForSpan( |
| 73 AnalysisOptionsWarningCode.UNRECOGNIZED_ERROR_CODE, |
| 74 k.span, |
| 75 [k.value?.toString()]); |
| 76 } |
| 77 } |
| 78 if (v is YamlScalar) { |
| 79 value = v.value?.toString()?.toLowerCase(); |
| 80 if (!AnalyzerOptions.ignoreSynonyms.contains(value) && |
| 81 !AnalyzerOptions.includeSynonyms.contains(value)) { |
| 82 reporter.reportErrorForSpan( |
| 83 AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES, |
| 84 v.span, |
| 85 [AnalyzerOptions.errors, v.value?.toString(), legalIncludes]); |
| 86 } |
| 87 |
| 88 value = v.value?.toString()?.toLowerCase(); |
| 89 } |
| 90 }); |
| 91 } |
| 92 } |
| 93 } |
| 94 |
45 /// Validates `analyzer` top-level options. | 95 /// Validates `analyzer` top-level options. |
46 class AnalyzerOptionsValidator extends TopLevelOptionValidator { | 96 class TopLevelAnalyzerOptionsValidator extends TopLevelOptionValidator { |
47 AnalyzerOptionsValidator() : super('analyzer', AnalyzerOptions.top_level); | 97 TopLevelAnalyzerOptionsValidator() |
| 98 : super(AnalyzerOptions.analyzer, AnalyzerOptions.top_level); |
| 99 } |
| 100 |
| 101 /// Validates `analyzer` options. |
| 102 class AnalyzerOptionsValidator extends CompositeValidator { |
| 103 AnalyzerOptionsValidator() |
| 104 : super([ |
| 105 new TopLevelAnalyzerOptionsValidator(), |
| 106 new ErrorFilterOptionValidator() |
| 107 ]); |
48 } | 108 } |
49 | 109 |
50 /// Convenience class for composing validators. | 110 /// Convenience class for composing validators. |
51 class CompositeValidator extends OptionsValidator { | 111 class CompositeValidator extends OptionsValidator { |
52 final List<OptionsValidator> validators; | 112 final List<OptionsValidator> validators; |
53 CompositeValidator(this.validators); | 113 CompositeValidator(this.validators); |
54 | 114 |
55 @override | 115 @override |
56 void validate(ErrorReporter reporter, Map<String, YamlNode> options) => | 116 void validate(ErrorReporter reporter, Map<String, YamlNode> options) => |
57 validators.forEach((v) => v.validate(reporter, options)); | 117 validators.forEach((v) => v.validate(reporter, options)); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 return recorder.errors; | 210 return recorder.errors; |
151 } | 211 } |
152 } | 212 } |
153 | 213 |
154 /// Validates top-level options. For example, | 214 /// Validates top-level options. For example, |
155 /// plugin: | 215 /// plugin: |
156 /// top-level-option: true | 216 /// top-level-option: true |
157 class TopLevelOptionValidator extends OptionsValidator { | 217 class TopLevelOptionValidator extends OptionsValidator { |
158 final String pluginName; | 218 final String pluginName; |
159 final List<String> supportedOptions; | 219 final List<String> supportedOptions; |
| 220 String _valueProposal; |
| 221 AnalysisOptionsWarningCode _warningCode; |
| 222 TopLevelOptionValidator(this.pluginName, this.supportedOptions) { |
| 223 assert(supportedOptions != null && !supportedOptions.isEmpty); |
| 224 if (supportedOptions.length > 1) { |
| 225 _valueProposal = StringUtilities.printListOfQuotedNames(supportedOptions); |
| 226 _warningCode = |
| 227 AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES; |
| 228 } else { |
| 229 _valueProposal = "'${supportedOptions.join()}'"; |
| 230 _warningCode = |
| 231 AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUE; |
| 232 } |
| 233 } |
160 | 234 |
161 TopLevelOptionValidator(this.pluginName, this.supportedOptions); | |
162 @override | 235 @override |
163 void validate(ErrorReporter reporter, Map<String, YamlNode> options) { | 236 void validate(ErrorReporter reporter, Map<String, YamlNode> options) { |
164 YamlNode node = options[pluginName]; | 237 YamlNode node = options[pluginName]; |
165 if (node is YamlMap) { | 238 if (node is YamlMap) { |
166 node.nodes.forEach((k, v) { | 239 node.nodes.forEach((k, v) { |
167 if (k is YamlScalar) { | 240 if (k is YamlScalar) { |
168 if (!supportedOptions.contains(k.value)) { | 241 if (!supportedOptions.contains(k.value)) { |
169 reporter.reportErrorForSpan( | 242 reporter.reportErrorForSpan( |
170 AnalysisOptionsWarningCode.UNSUPPORTED_OPTION, | 243 _warningCode, k.span, [pluginName, k.value, _valueProposal]); |
171 k.span, | |
172 [pluginName, k.value]); | |
173 } | 244 } |
174 } | 245 } |
175 //TODO(pq): consider an error if the node is not a Scalar. | 246 //TODO(pq): consider an error if the node is not a Scalar. |
176 }); | 247 }); |
177 } | 248 } |
178 } | 249 } |
179 } | 250 } |
OLD | NEW |