| 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 library analyzer.src.task.options; |
| 6 |
| 7 import 'dart:collection'; |
| 8 |
| 9 import 'package:analyzer/analyzer.dart'; |
| 10 import 'package:analyzer/plugin/options.dart'; |
| 11 import 'package:analyzer/source/analysis_options_provider.dart'; |
| 12 import 'package:analyzer/source/error_processor.dart'; |
| 13 import 'package:analyzer/src/context/context.dart'; |
| 14 import 'package:analyzer/src/generated/engine.dart'; |
| 15 import 'package:analyzer/src/generated/java_engine.dart'; |
| 16 import 'package:analyzer/src/generated/source.dart'; |
| 17 import 'package:analyzer/src/generated/utilities_general.dart'; |
| 18 import 'package:analyzer/src/task/general.dart'; |
| 19 import 'package:analyzer/src/util/yaml.dart'; |
| 20 import 'package:analyzer/task/general.dart'; |
| 21 import 'package:analyzer/task/model.dart'; |
| 22 import 'package:source_span/source_span.dart'; |
| 23 import 'package:yaml/yaml.dart'; |
| 24 |
| 25 /// The errors produced while parsing an analysis options file. |
| 26 /// |
| 27 /// The list will be empty if there were no errors, but will not be `null`. |
| 28 final ListResultDescriptor<AnalysisError> ANALYSIS_OPTIONS_ERRORS = |
| 29 new ListResultDescriptor<AnalysisError>( |
| 30 'ANALYSIS_OPTIONS_ERRORS', AnalysisError.NO_ERRORS); |
| 31 |
| 32 /** |
| 33 * The descriptor used to associate error processors with analysis contexts in |
| 34 * configuration data. |
| 35 */ |
| 36 final ListResultDescriptor<ErrorProcessor> CONFIGURED_ERROR_PROCESSORS = |
| 37 new ListResultDescriptor<ErrorProcessor>( |
| 38 'configured.errors', const <ErrorProcessor>[]); |
| 39 |
| 40 final _OptionsProcessor _processor = new _OptionsProcessor(); |
| 41 |
| 42 void applyToAnalysisOptions( |
| 43 AnalysisOptionsImpl options, Map<String, Object> optionMap) { |
| 44 _processor.applyToAnalysisOptions(options, optionMap); |
| 45 } |
| 46 |
| 47 /// Configure this [context] based on configuration details specified in |
| 48 /// the given [options]. If [options] is `null`, default values are applied. |
| 49 void configureContextOptions( |
| 50 AnalysisContext context, Map<String, Object> options) => |
| 51 _processor.configure(context, options); |
| 52 |
| 53 /// `analyzer` analysis options constants. |
| 54 class AnalyzerOptions { |
| 55 static const String analyzer = 'analyzer'; |
| 56 static const String enableAssertInitializer = 'enableAssertInitializer'; |
| 57 static const String enableAsync = 'enableAsync'; |
| 58 static const String enableGenericMethods = 'enableGenericMethods'; |
| 59 static const String enableInitializingFormalAccess = |
| 60 'enableInitializingFormalAccess'; |
| 61 static const String enableStrictCallChecks = 'enableStrictCallChecks'; |
| 62 static const String enableSuperMixins = 'enableSuperMixins'; |
| 63 |
| 64 static const String errors = 'errors'; |
| 65 static const String exclude = 'exclude'; |
| 66 static const String language = 'language'; |
| 67 static const String plugins = 'plugins'; |
| 68 static const String strong_mode = 'strong-mode'; |
| 69 |
| 70 // Strong mode options, see AnalysisOptionsImpl for documentation. |
| 71 static const String implicitCasts = 'implicit-casts'; |
| 72 static const String implicitDynamic = 'implicit-dynamic'; |
| 73 |
| 74 /// Ways to say `ignore`. |
| 75 static const List<String> ignoreSynonyms = const ['ignore', 'false']; |
| 76 |
| 77 /// Valid error `severity`s. |
| 78 static final List<String> severities = |
| 79 new List.unmodifiable(severityMap.keys); |
| 80 |
| 81 /// Ways to say `include`. |
| 82 static const List<String> includeSynonyms = const ['include', 'true']; |
| 83 |
| 84 /// Ways to say `true` or `false`. |
| 85 static const List<String> trueOrFalse = const ['true', 'false']; |
| 86 |
| 87 /// Supported top-level `analyzer` options. |
| 88 static const List<String> topLevel = const [ |
| 89 errors, |
| 90 exclude, |
| 91 language, |
| 92 plugins, |
| 93 strong_mode |
| 94 ]; |
| 95 |
| 96 /// Supported `analyzer` language configuration options. |
| 97 static const List<String> languageOptions = const [ |
| 98 enableAssertInitializer, |
| 99 enableAsync, |
| 100 enableGenericMethods, |
| 101 enableStrictCallChecks, |
| 102 enableSuperMixins |
| 103 ]; |
| 104 } |
| 105 |
| 106 /// Validates `analyzer` options. |
| 107 class AnalyzerOptionsValidator extends CompositeValidator { |
| 108 AnalyzerOptionsValidator() |
| 109 : super([ |
| 110 new TopLevelAnalyzerOptionsValidator(), |
| 111 new StrongModeOptionValueValidator(), |
| 112 new ErrorFilterOptionValidator(), |
| 113 new LanguageOptionValidator() |
| 114 ]); |
| 115 } |
| 116 |
| 117 /// Convenience class for composing validators. |
| 118 class CompositeValidator extends OptionsValidator { |
| 119 final List<OptionsValidator> validators; |
| 120 CompositeValidator(this.validators); |
| 121 |
| 122 @override |
| 123 void validate(ErrorReporter reporter, Map<String, YamlNode> options) => |
| 124 validators.forEach((v) => v.validate(reporter, options)); |
| 125 } |
| 126 |
| 127 /// Builds error reports with value proposals. |
| 128 class ErrorBuilder { |
| 129 String proposal; |
| 130 AnalysisOptionsWarningCode code; |
| 131 |
| 132 /// Create a builder for the given [supportedOptions]. |
| 133 ErrorBuilder(List<String> supportedOptions) { |
| 134 assert(supportedOptions != null && !supportedOptions.isEmpty); |
| 135 if (supportedOptions.length > 1) { |
| 136 proposal = StringUtilities.printListOfQuotedNames(supportedOptions); |
| 137 code = pluralProposalCode; |
| 138 } else { |
| 139 proposal = "'${supportedOptions.join()}'"; |
| 140 code = singularProposalCode; |
| 141 } |
| 142 } |
| 143 AnalysisOptionsWarningCode get pluralProposalCode => |
| 144 AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES; |
| 145 |
| 146 AnalysisOptionsWarningCode get singularProposalCode => |
| 147 AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUE; |
| 148 |
| 149 /// Report an unsupported [node] value, defined in the given [scopeName]. |
| 150 void reportError(ErrorReporter reporter, String scopeName, YamlNode node) { |
| 151 reporter |
| 152 .reportErrorForSpan(code, node.span, [scopeName, node.value, proposal]); |
| 153 } |
| 154 } |
| 155 |
| 156 /// Validates `analyzer` error filter options. |
| 157 class ErrorFilterOptionValidator extends OptionsValidator { |
| 158 /// Legal values. |
| 159 static final List<String> legalValues = |
| 160 new List.from(AnalyzerOptions.ignoreSynonyms) |
| 161 ..addAll(AnalyzerOptions.includeSynonyms) |
| 162 ..addAll(AnalyzerOptions.severities); |
| 163 |
| 164 /// Pretty String listing legal values. |
| 165 static final String legalValueString = |
| 166 StringUtilities.printListOfQuotedNames(legalValues); |
| 167 |
| 168 /// Lazily populated set of error codes (hashed for speedy lookup). |
| 169 static HashSet<String> _errorCodes; |
| 170 |
| 171 /// Legal error code names. |
| 172 static Set<String> get errorCodes { |
| 173 if (_errorCodes == null) { |
| 174 _errorCodes = new HashSet<String>(); |
| 175 // Engine codes. |
| 176 _errorCodes.addAll(ErrorCode.values.map((ErrorCode code) => code.name)); |
| 177 } |
| 178 return _errorCodes; |
| 179 } |
| 180 |
| 181 @override |
| 182 void validate(ErrorReporter reporter, Map<String, YamlNode> options) { |
| 183 var analyzer = options[AnalyzerOptions.analyzer]; |
| 184 if (analyzer is YamlMap) { |
| 185 var filters = analyzer[AnalyzerOptions.errors]; |
| 186 if (filters is YamlMap) { |
| 187 String value; |
| 188 filters.nodes.forEach((k, v) { |
| 189 if (k is YamlScalar) { |
| 190 value = toUpperCase(k.value); |
| 191 if (!errorCodes.contains(value)) { |
| 192 reporter.reportErrorForSpan( |
| 193 AnalysisOptionsWarningCode.UNRECOGNIZED_ERROR_CODE, |
| 194 k.span, |
| 195 [k.value?.toString()]); |
| 196 } |
| 197 } |
| 198 if (v is YamlScalar) { |
| 199 value = toLowerCase(v.value); |
| 200 if (!legalValues.contains(value)) { |
| 201 reporter.reportErrorForSpan( |
| 202 AnalysisOptionsWarningCode |
| 203 .UNSUPPORTED_OPTION_WITH_LEGAL_VALUES, |
| 204 v.span, |
| 205 [ |
| 206 AnalyzerOptions.errors, |
| 207 v.value?.toString(), |
| 208 legalValueString |
| 209 ]); |
| 210 } |
| 211 } |
| 212 }); |
| 213 } |
| 214 } |
| 215 } |
| 216 } |
| 217 |
| 218 /// A task that generates errors for an analysis options file. |
| 219 class GenerateOptionsErrorsTask extends SourceBasedAnalysisTask { |
| 220 /// The name of the input whose value is the content of the file. |
| 221 static const String CONTENT_INPUT_NAME = 'CONTENT_INPUT_NAME'; |
| 222 |
| 223 /// The task descriptor describing this kind of task. |
| 224 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( |
| 225 'GenerateOptionsErrorsTask', |
| 226 createTask, |
| 227 buildInputs, |
| 228 <ResultDescriptor>[ANALYSIS_OPTIONS_ERRORS, LINE_INFO], |
| 229 suitabilityFor: suitabilityFor); |
| 230 |
| 231 final AnalysisOptionsProvider optionsProvider = new AnalysisOptionsProvider(); |
| 232 |
| 233 GenerateOptionsErrorsTask(AnalysisContext context, AnalysisTarget target) |
| 234 : super(context, target); |
| 235 |
| 236 @override |
| 237 TaskDescriptor get descriptor => DESCRIPTOR; |
| 238 |
| 239 Source get source => target.source; |
| 240 |
| 241 @override |
| 242 void internalPerform() { |
| 243 String content = getRequiredInput(CONTENT_INPUT_NAME); |
| 244 |
| 245 List<AnalysisError> errors = <AnalysisError>[]; |
| 246 |
| 247 try { |
| 248 Map<String, YamlNode> options = |
| 249 optionsProvider.getOptionsFromString(content); |
| 250 errors.addAll(_validate(options)); |
| 251 } on OptionsFormatException catch (e) { |
| 252 SourceSpan span = e.span; |
| 253 var error = new AnalysisError(source, span.start.column + 1, span.length, |
| 254 AnalysisOptionsErrorCode.PARSE_ERROR, [e.message]); |
| 255 errors.add(error); |
| 256 } |
| 257 |
| 258 // |
| 259 // Record outputs. |
| 260 // |
| 261 outputs[ANALYSIS_OPTIONS_ERRORS] = errors; |
| 262 outputs[LINE_INFO] = computeLineInfo(content); |
| 263 } |
| 264 |
| 265 List<AnalysisError> _validate(Map<String, YamlNode> options) => |
| 266 new OptionsFileValidator(source).validate(options); |
| 267 |
| 268 /// Return a map from the names of the inputs of this kind of task to the |
| 269 /// task input descriptors describing those inputs for a task with the |
| 270 /// given [target]. |
| 271 static Map<String, TaskInput> buildInputs(AnalysisTarget source) => |
| 272 <String, TaskInput>{CONTENT_INPUT_NAME: CONTENT.of(source)}; |
| 273 |
| 274 /// Compute [LineInfo] for the given [content]. |
| 275 static LineInfo computeLineInfo(String content) { |
| 276 List<int> lineStarts = StringUtilities.computeLineStarts(content); |
| 277 return new LineInfo(lineStarts); |
| 278 } |
| 279 |
| 280 /// Create a task based on the given [target] in the given [context]. |
| 281 static GenerateOptionsErrorsTask createTask( |
| 282 AnalysisContext context, AnalysisTarget target) => |
| 283 new GenerateOptionsErrorsTask(context, target); |
| 284 |
| 285 /** |
| 286 * Return an indication of how suitable this task is for the given [target]. |
| 287 */ |
| 288 static TaskSuitability suitabilityFor(AnalysisTarget target) { |
| 289 if (target is Source && |
| 290 (target.shortName == AnalysisEngine.ANALYSIS_OPTIONS_FILE || |
| 291 target.shortName == AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE)) { |
| 292 return TaskSuitability.HIGHEST; |
| 293 } |
| 294 return TaskSuitability.NONE; |
| 295 } |
| 296 } |
| 297 |
| 298 /// Validates `analyzer` language configuration options. |
| 299 class LanguageOptionValidator extends OptionsValidator { |
| 300 ErrorBuilder builder = new ErrorBuilder(AnalyzerOptions.languageOptions); |
| 301 ErrorBuilder trueOrFalseBuilder = new TrueOrFalseValueErrorBuilder(); |
| 302 |
| 303 @override |
| 304 void validate(ErrorReporter reporter, Map<String, YamlNode> options) { |
| 305 var analyzer = options[AnalyzerOptions.analyzer]; |
| 306 if (analyzer is YamlMap) { |
| 307 var language = analyzer[AnalyzerOptions.language]; |
| 308 if (language is YamlMap) { |
| 309 language.nodes.forEach((k, v) { |
| 310 String key, value; |
| 311 bool validKey = false; |
| 312 if (k is YamlScalar) { |
| 313 key = k.value?.toString(); |
| 314 if (!AnalyzerOptions.languageOptions.contains(key)) { |
| 315 builder.reportError(reporter, AnalyzerOptions.language, k); |
| 316 } else { |
| 317 // If we have a valid key, go on and check the value. |
| 318 validKey = true; |
| 319 } |
| 320 } |
| 321 if (validKey && v is YamlScalar) { |
| 322 value = toLowerCase(v.value); |
| 323 if (!AnalyzerOptions.trueOrFalse.contains(value)) { |
| 324 trueOrFalseBuilder.reportError(reporter, key, v); |
| 325 } |
| 326 } |
| 327 }); |
| 328 } |
| 329 } |
| 330 } |
| 331 } |
| 332 |
| 333 /// Validates `linter` top-level options. |
| 334 /// TODO(pq): move into `linter` package and plugin. |
| 335 class LinterOptionsValidator extends TopLevelOptionValidator { |
| 336 LinterOptionsValidator() : super('linter', const ['rules']); |
| 337 } |
| 338 |
| 339 /// Validates options defined in an analysis options file. |
| 340 class OptionsFileValidator { |
| 341 // TODO(pq): move to an extension point. |
| 342 final List<OptionsValidator> _validators = [ |
| 343 new AnalyzerOptionsValidator(), |
| 344 new LinterOptionsValidator() |
| 345 ]; |
| 346 |
| 347 final Source source; |
| 348 OptionsFileValidator(this.source) { |
| 349 _validators.addAll(AnalysisEngine.instance.optionsPlugin.optionsValidators); |
| 350 } |
| 351 |
| 352 List<AnalysisError> validate(Map<String, YamlNode> options) { |
| 353 RecordingErrorListener recorder = new RecordingErrorListener(); |
| 354 ErrorReporter reporter = new ErrorReporter(recorder, source); |
| 355 _validators.forEach((OptionsValidator v) => v.validate(reporter, options)); |
| 356 return recorder.errors; |
| 357 } |
| 358 } |
| 359 |
| 360 /// Validates `analyzer` strong-mode value configuration options. |
| 361 class StrongModeOptionValueValidator extends OptionsValidator { |
| 362 ErrorBuilder trueOrFalseBuilder = new TrueOrFalseValueErrorBuilder(); |
| 363 |
| 364 @override |
| 365 void validate(ErrorReporter reporter, Map<String, YamlNode> options) { |
| 366 var analyzer = options[AnalyzerOptions.analyzer]; |
| 367 if (analyzer is YamlMap) { |
| 368 var v = analyzer.nodes[AnalyzerOptions.strong_mode]; |
| 369 if (v is YamlScalar) { |
| 370 var value = toLowerCase(v.value); |
| 371 if (!AnalyzerOptions.trueOrFalse.contains(value)) { |
| 372 trueOrFalseBuilder.reportError( |
| 373 reporter, AnalyzerOptions.strong_mode, v); |
| 374 } |
| 375 } |
| 376 } |
| 377 } |
| 378 } |
| 379 |
| 380 /// Validates `analyzer` top-level options. |
| 381 class TopLevelAnalyzerOptionsValidator extends TopLevelOptionValidator { |
| 382 TopLevelAnalyzerOptionsValidator() |
| 383 : super(AnalyzerOptions.analyzer, AnalyzerOptions.topLevel); |
| 384 } |
| 385 |
| 386 /// Validates top-level options. For example, |
| 387 /// plugin: |
| 388 /// top-level-option: true |
| 389 class TopLevelOptionValidator extends OptionsValidator { |
| 390 final String pluginName; |
| 391 final List<String> supportedOptions; |
| 392 String _valueProposal; |
| 393 AnalysisOptionsWarningCode _warningCode; |
| 394 TopLevelOptionValidator(this.pluginName, this.supportedOptions) { |
| 395 assert(supportedOptions != null && !supportedOptions.isEmpty); |
| 396 if (supportedOptions.length > 1) { |
| 397 _valueProposal = StringUtilities.printListOfQuotedNames(supportedOptions); |
| 398 _warningCode = |
| 399 AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUES; |
| 400 } else { |
| 401 _valueProposal = "'${supportedOptions.join()}'"; |
| 402 _warningCode = |
| 403 AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUE; |
| 404 } |
| 405 } |
| 406 |
| 407 @override |
| 408 void validate(ErrorReporter reporter, Map<String, YamlNode> options) { |
| 409 YamlNode node = options[pluginName]; |
| 410 if (node is YamlMap) { |
| 411 node.nodes.forEach((k, v) { |
| 412 if (k is YamlScalar) { |
| 413 if (!supportedOptions.contains(k.value)) { |
| 414 reporter.reportErrorForSpan( |
| 415 _warningCode, k.span, [pluginName, k.value, _valueProposal]); |
| 416 } |
| 417 } |
| 418 //TODO(pq): consider an error if the node is not a Scalar. |
| 419 }); |
| 420 } |
| 421 } |
| 422 } |
| 423 |
| 424 /// An error-builder that knows about `true` and `false` legal values. |
| 425 class TrueOrFalseValueErrorBuilder extends ErrorBuilder { |
| 426 TrueOrFalseValueErrorBuilder() : super(AnalyzerOptions.trueOrFalse); |
| 427 @override |
| 428 AnalysisOptionsWarningCode get pluralProposalCode => |
| 429 AnalysisOptionsWarningCode.UNSUPPORTED_VALUE; |
| 430 } |
| 431 |
| 432 class _OptionsProcessor { |
| 433 static final Map<String, Object> defaults = {'analyzer': {}}; |
| 434 |
| 435 /** |
| 436 * Apply the options in the given [optionMap] to the given analysis [options]. |
| 437 */ |
| 438 void applyToAnalysisOptions( |
| 439 AnalysisOptionsImpl options, Map<String, Object> optionMap) { |
| 440 if (optionMap == null) { |
| 441 return; |
| 442 } |
| 443 var analyzer = optionMap[AnalyzerOptions.analyzer]; |
| 444 if (analyzer is Map) { |
| 445 // Process strong mode option. |
| 446 var strongMode = analyzer[AnalyzerOptions.strong_mode]; |
| 447 _applyStrongOptions(options, strongMode); |
| 448 |
| 449 // Process language options. |
| 450 var language = analyzer[AnalyzerOptions.language]; |
| 451 _applyLanguageOptions(options, language); |
| 452 } |
| 453 } |
| 454 |
| 455 /// Configure [context] based on the given [options] (which can be `null` |
| 456 /// to restore [defaults]). |
| 457 void configure(AnalysisContext context, Map<String, Object> options) { |
| 458 if (options == null) { |
| 459 options = defaults; |
| 460 } |
| 461 |
| 462 var analyzer = options[AnalyzerOptions.analyzer]; |
| 463 if (analyzer is Map) { |
| 464 // Set strong mode (default is false). |
| 465 var strongMode = analyzer[AnalyzerOptions.strong_mode]; |
| 466 setStrongMode(context, strongMode); |
| 467 |
| 468 // Set filters. |
| 469 var filters = analyzer[AnalyzerOptions.errors]; |
| 470 setProcessors(context, filters); |
| 471 |
| 472 // Process language options. |
| 473 var language = analyzer[AnalyzerOptions.language]; |
| 474 setLanguageOptions(context, language); |
| 475 |
| 476 // Process excludes. |
| 477 var excludes = analyzer[AnalyzerOptions.exclude]; |
| 478 setExcludes(context, excludes); |
| 479 } |
| 480 } |
| 481 |
| 482 void setExcludes(AnalysisContext context, Object excludes) { |
| 483 if (excludes is YamlList) { |
| 484 List<String> excludeList = toStringList(excludes); |
| 485 if (excludeList != null) { |
| 486 context.setConfigurationData(CONTEXT_EXCLUDES, excludeList); |
| 487 } |
| 488 } |
| 489 } |
| 490 |
| 491 void setLanguageOption( |
| 492 AnalysisContext context, Object feature, Object value) { |
| 493 if (feature == AnalyzerOptions.enableAssertInitializer) { |
| 494 if (isTrue(value)) { |
| 495 AnalysisOptionsImpl options = |
| 496 new AnalysisOptionsImpl.from(context.analysisOptions); |
| 497 options.enableAssertInitializer = true; |
| 498 context.analysisOptions = options; |
| 499 } |
| 500 } |
| 501 if (feature == AnalyzerOptions.enableStrictCallChecks) { |
| 502 if (isTrue(value)) { |
| 503 AnalysisOptionsImpl options = |
| 504 new AnalysisOptionsImpl.from(context.analysisOptions); |
| 505 options.enableStrictCallChecks = true; |
| 506 context.analysisOptions = options; |
| 507 } |
| 508 } |
| 509 if (feature == AnalyzerOptions.enableSuperMixins) { |
| 510 if (isTrue(value)) { |
| 511 AnalysisOptionsImpl options = |
| 512 new AnalysisOptionsImpl.from(context.analysisOptions); |
| 513 options.enableSuperMixins = true; |
| 514 context.analysisOptions = options; |
| 515 } |
| 516 } |
| 517 if (feature == AnalyzerOptions.enableGenericMethods) { |
| 518 if (isTrue(value)) { |
| 519 AnalysisOptionsImpl options = |
| 520 new AnalysisOptionsImpl.from(context.analysisOptions); |
| 521 options.enableGenericMethods = true; |
| 522 context.analysisOptions = options; |
| 523 } |
| 524 } |
| 525 } |
| 526 |
| 527 void setLanguageOptions(AnalysisContext context, Object configs) { |
| 528 if (configs is YamlMap) { |
| 529 configs.nodes.forEach((k, v) { |
| 530 if (k is YamlScalar && v is YamlScalar) { |
| 531 String feature = k.value?.toString(); |
| 532 setLanguageOption(context, feature, v.value); |
| 533 } |
| 534 }); |
| 535 } else if (configs is Map) { |
| 536 configs.forEach((k, v) => setLanguageOption(context, k, v)); |
| 537 } |
| 538 } |
| 539 |
| 540 void setProcessors(AnalysisContext context, Object codes) { |
| 541 ErrorConfig config = new ErrorConfig(codes); |
| 542 context.setConfigurationData( |
| 543 CONFIGURED_ERROR_PROCESSORS, config.processors); |
| 544 } |
| 545 |
| 546 void setStrongMode(AnalysisContext context, Object strongMode) { |
| 547 if (strongMode is Map) { |
| 548 AnalysisOptionsImpl options = |
| 549 new AnalysisOptionsImpl.from(context.analysisOptions); |
| 550 _applyStrongOptions(options, strongMode); |
| 551 context.analysisOptions = options; |
| 552 } else { |
| 553 strongMode = strongMode is bool ? strongMode : false; |
| 554 if (context.analysisOptions.strongMode != strongMode) { |
| 555 AnalysisOptionsImpl options = |
| 556 new AnalysisOptionsImpl.from(context.analysisOptions); |
| 557 options.strongMode = strongMode; |
| 558 context.analysisOptions = options; |
| 559 } |
| 560 } |
| 561 } |
| 562 |
| 563 void _applyLanguageOption( |
| 564 AnalysisOptionsImpl options, Object feature, Object value) { |
| 565 bool boolValue = toBool(value); |
| 566 if (boolValue != null) { |
| 567 if (feature == AnalyzerOptions.enableAssertInitializer) { |
| 568 options.enableAssertInitializer = boolValue; |
| 569 } else if (feature == AnalyzerOptions.enableInitializingFormalAccess) { |
| 570 options.enableInitializingFormalAccess = boolValue; |
| 571 } else if (feature == AnalyzerOptions.enableSuperMixins) { |
| 572 options.enableSuperMixins = boolValue; |
| 573 } else if (feature == AnalyzerOptions.enableGenericMethods) { |
| 574 options.enableGenericMethods = boolValue; |
| 575 } |
| 576 } |
| 577 } |
| 578 |
| 579 void _applyLanguageOptions(AnalysisOptionsImpl options, Object configs) { |
| 580 if (configs is YamlMap) { |
| 581 configs.nodes.forEach((key, value) { |
| 582 if (key is YamlScalar && value is YamlScalar) { |
| 583 String feature = key.value?.toString(); |
| 584 _applyLanguageOption(options, feature, value.value); |
| 585 } |
| 586 }); |
| 587 } else if (configs is Map) { |
| 588 configs |
| 589 .forEach((key, value) => _applyLanguageOption(options, key, value)); |
| 590 } |
| 591 } |
| 592 |
| 593 void _applyStrongModeOption( |
| 594 AnalysisOptionsImpl options, Object feature, Object value) { |
| 595 bool boolValue = toBool(value); |
| 596 if (boolValue != null) { |
| 597 if (feature == AnalyzerOptions.implicitCasts) { |
| 598 options.implicitCasts = boolValue; |
| 599 } |
| 600 if (feature == AnalyzerOptions.implicitDynamic) { |
| 601 options.implicitDynamic = boolValue; |
| 602 } |
| 603 } |
| 604 } |
| 605 |
| 606 void _applyStrongOptions(AnalysisOptionsImpl options, Object config) { |
| 607 if (config is YamlMap) { |
| 608 options.strongMode = true; |
| 609 config.nodes.forEach((k, v) { |
| 610 if (k is YamlScalar && v is YamlScalar) { |
| 611 _applyStrongModeOption(options, k.value?.toString(), v.value); |
| 612 } |
| 613 }); |
| 614 } else if (config is Map) { |
| 615 options.strongMode = true; |
| 616 config.forEach((k, v) => _applyStrongModeOption(options, k, v)); |
| 617 } else { |
| 618 options.strongMode = config is bool ? config : false; |
| 619 } |
| 620 } |
| 621 } |
| OLD | NEW |