| 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 /// Types needed to implement "strong" checking in the Dart analyzer. This is | 5 /// Types needed to implement "strong" checking in the Dart analyzer. This is |
| 6 /// intended to be used by `analyzer_cli` and `analysis_server` packages. | 6 /// intended to be used by `analyzer_cli` and `analysis_server` packages. |
| 7 library dev_compiler.strong_mode; | 7 library dev_compiler.strong_mode; |
| 8 | 8 |
| 9 import 'package:analyzer/src/generated/engine.dart' | 9 import 'package:analyzer/src/generated/engine.dart' |
| 10 show | 10 show |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 | 38 |
| 39 StrongChecker._(this._context, this._checker, this._reporter); | 39 StrongChecker._(this._context, this._checker, this._reporter); |
| 40 | 40 |
| 41 factory StrongChecker(AnalysisContext context, StrongModeOptions options) { | 41 factory StrongChecker(AnalysisContext context, StrongModeOptions options) { |
| 42 // TODO(vsm): Remove this once analyzer_cli is completely switched to the | 42 // TODO(vsm): Remove this once analyzer_cli is completely switched to the |
| 43 // task model. | 43 // task model. |
| 44 if (!AnalysisEngine | 44 if (!AnalysisEngine |
| 45 .instance.useTaskModel) enableDevCompilerInference(context, options); | 45 .instance.useTaskModel) enableDevCompilerInference(context, options); |
| 46 var rules = new RestrictedRules(context.typeProvider, options: options); | 46 var rules = new RestrictedRules(context.typeProvider, options: options); |
| 47 var reporter = new _ErrorCollector(options.hints); | 47 var reporter = new _ErrorCollector(options.hints); |
| 48 var checker = new CodeChecker(rules, reporter, options); | 48 var checker = new CodeChecker(rules, reporter); |
| 49 return new StrongChecker._(context, checker, reporter); | 49 return new StrongChecker._(context, checker, reporter); |
| 50 } | 50 } |
| 51 | 51 |
| 52 /// Computes and returns DDC errors for the [source]. | 52 /// Computes and returns DDC errors for the [source]. |
| 53 AnalysisErrorInfo computeErrors(Source source) { | 53 AnalysisErrorInfo computeErrors(Source source) { |
| 54 var errors = new List<AnalysisError>(); | 54 var errors = new List<AnalysisError>(); |
| 55 _reporter.errors = errors; | 55 _reporter.errors = errors; |
| 56 | 56 |
| 57 for (Source librarySource in _context.getLibrariesContaining(source)) { | 57 for (Source librarySource in _context.getLibrariesContaining(source)) { |
| 58 var resolved = _context.resolveCompilationUnit2(source, librarySource); | 58 var resolved = _context.resolveCompilationUnit2(source, librarySource); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 72 void onError(AnalysisError error) { | 72 void onError(AnalysisError error) { |
| 73 // Unless DDC hints are requested, filter them out. | 73 // Unless DDC hints are requested, filter them out. |
| 74 var HINT = ErrorSeverity.INFO.ordinal; | 74 var HINT = ErrorSeverity.INFO.ordinal; |
| 75 if (hints || error.errorCode.errorSeverity.ordinal > HINT) { | 75 if (hints || error.errorCode.errorSeverity.ordinal > HINT) { |
| 76 errors.add(error); | 76 errors.add(error); |
| 77 } | 77 } |
| 78 } | 78 } |
| 79 } | 79 } |
| 80 | 80 |
| 81 class StrongModeOptions { | 81 class StrongModeOptions { |
| 82 /// Whether to infer return types and field types from overridden members. | |
| 83 final bool inferFromOverrides; | |
| 84 static const inferFromOverridesDefault = true; | |
| 85 | |
| 86 /// Whether to infer types for consts and fields by looking at initializers on | 82 /// Whether to infer types for consts and fields by looking at initializers on |
| 87 /// the RHS. For example, in a constant declaration like: | 83 /// the RHS. For example, in a constant declaration like: |
| 88 /// | 84 /// |
| 89 /// const A = B; | 85 /// const A = B; |
| 90 /// | 86 /// |
| 91 /// We can infer the type of `A` based on the type of `B`. | 87 /// We can infer the type of `A` based on the type of `B`. |
| 92 /// | 88 /// |
| 93 /// The inference algorithm determines what variables depend on others, and | 89 /// The inference algorithm determines what variables depend on others, and |
| 94 /// computes types by visiting the variable dependency graph in topological | 90 /// computes types by visiting the variable dependency graph in topological |
| 95 /// order. This ensures that the inferred type is deterministic when applying | 91 /// order. This ensures that the inferred type is deterministic when applying |
| (...skipping 20 matching lines...) Expand all Loading... |
| 116 final List<String> nonnullableTypes; | 112 final List<String> nonnullableTypes; |
| 117 static const List<String> NONNULLABLE_TYPES = const <String>[]; | 113 static const List<String> NONNULLABLE_TYPES = const <String>[]; |
| 118 | 114 |
| 119 /// Whether to include hints about dynamic invokes and runtime checks. | 115 /// Whether to include hints about dynamic invokes and runtime checks. |
| 120 // TODO(jmesserly): this option is not used yet by DDC server mode or batch | 116 // TODO(jmesserly): this option is not used yet by DDC server mode or batch |
| 121 // compile to JS. | 117 // compile to JS. |
| 122 final bool hints; | 118 final bool hints; |
| 123 | 119 |
| 124 const StrongModeOptions( | 120 const StrongModeOptions( |
| 125 {this.hints: false, | 121 {this.hints: false, |
| 126 this.inferFromOverrides: inferFromOverridesDefault, | |
| 127 this.inferTransitively: inferTransitivelyDefault, | 122 this.inferTransitively: inferTransitivelyDefault, |
| 128 this.onlyInferConstsAndFinalFields: onlyInferConstAndFinalFieldsDefault, | 123 this.onlyInferConstsAndFinalFields: onlyInferConstAndFinalFieldsDefault, |
| 129 this.inferDownwards: inferDownwardsDefault, | 124 this.inferDownwards: inferDownwardsDefault, |
| 130 this.relaxedCasts: true, | 125 this.relaxedCasts: true, |
| 131 this.nonnullableTypes: StrongModeOptions.NONNULLABLE_TYPES}); | 126 this.nonnullableTypes: StrongModeOptions.NONNULLABLE_TYPES}); |
| 132 | 127 |
| 133 StrongModeOptions.fromArguments(ArgResults args, {String prefix: ''}) | 128 StrongModeOptions.fromArguments(ArgResults args, {String prefix: ''}) |
| 134 : relaxedCasts = args[prefix + 'relaxed-casts'], | 129 : relaxedCasts = args[prefix + 'relaxed-casts'], |
| 135 inferDownwards = args[prefix + 'infer-downwards'], | 130 inferDownwards = args[prefix + 'infer-downwards'], |
| 136 inferFromOverrides = args[prefix + 'infer-from-overrides'], | |
| 137 inferTransitively = args[prefix + 'infer-transitively'], | 131 inferTransitively = args[prefix + 'infer-transitively'], |
| 138 onlyInferConstsAndFinalFields = args[prefix + 'infer-only-finals'], | 132 onlyInferConstsAndFinalFields = args[prefix + 'infer-only-finals'], |
| 139 nonnullableTypes = _optionsToList(args[prefix + 'nonnullable'], | 133 nonnullableTypes = _optionsToList(args[prefix + 'nonnullable'], |
| 140 defaultValue: StrongModeOptions.NONNULLABLE_TYPES), | 134 defaultValue: StrongModeOptions.NONNULLABLE_TYPES), |
| 141 hints = args[prefix + 'hints']; | 135 hints = args[prefix + 'hints']; |
| 142 | 136 |
| 143 static ArgParser addArguments(ArgParser parser, | 137 static ArgParser addArguments(ArgParser parser, |
| 144 {String prefix: '', bool hide: false}) { | 138 {String prefix: '', bool hide: false}) { |
| 145 return parser | 139 return parser |
| 146 ..addFlag(prefix + 'hints', | 140 ..addFlag(prefix + 'hints', |
| 147 help: 'Display hints about dynamic casts and dispatch operations', | 141 help: 'Display hints about dynamic casts and dispatch operations', |
| 148 defaultsTo: false, | 142 defaultsTo: false, |
| 149 hide: hide) | 143 hide: hide) |
| 150 ..addFlag(prefix + 'relaxed-casts', | 144 ..addFlag(prefix + 'relaxed-casts', |
| 151 help: 'Cast between Dart assignable types', | 145 help: 'Cast between Dart assignable types', |
| 152 defaultsTo: true, | 146 defaultsTo: true, |
| 153 hide: hide) | 147 hide: hide) |
| 154 ..addOption(prefix + 'nonnullable', | 148 ..addOption(prefix + 'nonnullable', |
| 155 abbr: prefix == '' ? 'n' : null, | 149 abbr: prefix == '' ? 'n' : null, |
| 156 help: 'Comma separated string of non-nullable types', | 150 help: 'Comma separated string of non-nullable types', |
| 157 defaultsTo: null, | 151 defaultsTo: null, |
| 158 hide: hide) | 152 hide: hide) |
| 159 ..addFlag(prefix + 'infer-downwards', | 153 ..addFlag(prefix + 'infer-downwards', |
| 160 help: 'Infer types downwards from local context', | 154 help: 'Infer types downwards from local context', |
| 161 defaultsTo: inferDownwardsDefault, | 155 defaultsTo: inferDownwardsDefault, |
| 162 hide: hide) | 156 hide: hide) |
| 163 ..addFlag(prefix + 'infer-from-overrides', | |
| 164 help: 'Infer unspecified types of fields and return types from\n' | |
| 165 'definitions in supertypes', | |
| 166 defaultsTo: inferFromOverridesDefault, | |
| 167 hide: hide) | |
| 168 ..addFlag(prefix + 'infer-transitively', | 157 ..addFlag(prefix + 'infer-transitively', |
| 169 help: 'Infer consts/fields from definitions in other libraries', | 158 help: 'Infer consts/fields from definitions in other libraries', |
| 170 defaultsTo: inferTransitivelyDefault, | 159 defaultsTo: inferTransitivelyDefault, |
| 171 hide: hide) | 160 hide: hide) |
| 172 ..addFlag(prefix + 'infer-only-finals', | 161 ..addFlag(prefix + 'infer-only-finals', |
| 173 help: 'Do not infer non-const or non-final fields', | 162 help: 'Do not infer non-const or non-final fields', |
| 174 defaultsTo: onlyInferConstAndFinalFieldsDefault, | 163 defaultsTo: onlyInferConstAndFinalFieldsDefault, |
| 175 hide: hide); | 164 hide: hide); |
| 176 } | 165 } |
| 177 | 166 |
| 178 bool operator ==(Object other) { | 167 bool operator ==(Object other) { |
| 179 if (other is! StrongModeOptions) return false; | 168 if (other is! StrongModeOptions) return false; |
| 180 StrongModeOptions s = other; | 169 StrongModeOptions s = other; |
| 181 return inferFromOverrides == s.inferFromOverrides && | 170 return inferTransitively == s.inferTransitively && |
| 182 inferTransitively == s.inferTransitively && | |
| 183 onlyInferConstsAndFinalFields == s.onlyInferConstsAndFinalFields && | 171 onlyInferConstsAndFinalFields == s.onlyInferConstsAndFinalFields && |
| 184 inferDownwards == s.inferDownwards && | 172 inferDownwards == s.inferDownwards && |
| 185 relaxedCasts == s.relaxedCasts && | 173 relaxedCasts == s.relaxedCasts && |
| 186 nonnullableTypes.length == s.nonnullableTypes.length && | 174 nonnullableTypes.length == s.nonnullableTypes.length && |
| 187 new Set.from(nonnullableTypes).containsAll(s.nonnullableTypes); | 175 new Set.from(nonnullableTypes).containsAll(s.nonnullableTypes); |
| 188 } | 176 } |
| 189 } | 177 } |
| 190 | 178 |
| 191 List<String> _optionsToList(String option, | 179 List<String> _optionsToList(String option, |
| 192 {List<String> defaultValue: const <String>[]}) { | 180 {List<String> defaultValue: const <String>[]}) { |
| 193 if (option == null) { | 181 if (option == null) { |
| 194 return defaultValue; | 182 return defaultValue; |
| 195 } else if (option.isEmpty) { | 183 } else if (option.isEmpty) { |
| 196 return <String>[]; | 184 return <String>[]; |
| 197 } else { | 185 } else { |
| 198 return option.split(','); | 186 return option.split(','); |
| 199 } | 187 } |
| 200 } | 188 } |
| OLD | NEW |