| 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 |