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 |