| 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 // TODO(jmesserly): this file needs to be refactored, it's a port from | 5 // TODO(jmesserly): this file needs to be refactored, it's a port from |
| 6 // package:dev_compiler's tests | 6 // package:dev_compiler's tests |
| 7 library analyzer.test.src.task.strong.strong_test_helper; | 7 library analyzer.test.src.task.strong.strong_test_helper; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/visitor.dart'; | 10 import 'package:analyzer/dart/ast/visitor.dart'; |
| 11 import 'package:analyzer/dart/element/element.dart'; | 11 import 'package:analyzer/dart/element/element.dart'; |
| 12 import 'package:analyzer/file_system/file_system.dart'; | 12 import 'package:analyzer/file_system/file_system.dart'; |
| 13 import 'package:analyzer/file_system/memory_file_system.dart'; | 13 import 'package:analyzer/file_system/memory_file_system.dart'; |
| 14 import 'package:analyzer/src/context/context.dart' show SdkAnalysisContext; | |
| 15 import 'package:analyzer/src/generated/engine.dart'; | 14 import 'package:analyzer/src/generated/engine.dart'; |
| 16 import 'package:analyzer/src/generated/error.dart'; | 15 import 'package:analyzer/src/generated/error.dart'; |
| 17 import 'package:analyzer/src/generated/sdk.dart'; | |
| 18 import 'package:analyzer/src/generated/source.dart'; | 16 import 'package:analyzer/src/generated/source.dart'; |
| 19 import 'package:analyzer/src/generated/type_system.dart'; | 17 import 'package:analyzer/src/generated/type_system.dart'; |
| 20 import 'package:analyzer/src/task/strong/checker.dart'; | 18 import 'package:analyzer/src/task/strong/checker.dart'; |
| 21 import 'package:logging/logging.dart'; | 19 import 'package:logging/logging.dart'; |
| 22 import 'package:source_span/source_span.dart'; | 20 import 'package:source_span/source_span.dart'; |
| 23 import 'package:unittest/unittest.dart'; | 21 import 'package:unittest/unittest.dart'; |
| 24 | 22 |
| 23 import '../../context/mock_sdk.dart'; |
| 25 | 24 |
| 26 MemoryResourceProvider files; | 25 MemoryResourceProvider files; |
| 27 bool _checkCalled; | 26 bool _checkCalled; |
| 28 | 27 |
| 29 initStrongModeTests() { | 28 initStrongModeTests() { |
| 30 setUp(() { | 29 setUp(() { |
| 31 AnalysisEngine.instance.processRequiredPlugins(); | 30 AnalysisEngine.instance.processRequiredPlugins(); |
| 32 files = new MemoryResourceProvider(); | 31 files = new MemoryResourceProvider(); |
| 33 _checkCalled = false; | 32 _checkCalled = false; |
| 34 }); | 33 }); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 /// errors/warnings/hints match the expected value. | 72 /// errors/warnings/hints match the expected value. |
| 74 /// | 73 /// |
| 75 /// See [addFile] for more information about how to encode expectations in | 74 /// See [addFile] for more information about how to encode expectations in |
| 76 /// the file text. | 75 /// the file text. |
| 77 void check() { | 76 void check() { |
| 78 _checkCalled = true; | 77 _checkCalled = true; |
| 79 | 78 |
| 80 expect(files.getFile('/main.dart').exists, true, | 79 expect(files.getFile('/main.dart').exists, true, |
| 81 reason: '`/main.dart` is missing'); | 80 reason: '`/main.dart` is missing'); |
| 82 | 81 |
| 83 var uriResolver = new TestUriResolver(files); | 82 var uriResolver = new _TestUriResolver(files); |
| 84 // Enable task model strong mode | 83 // Enable task model strong mode |
| 85 var context = AnalysisEngine.instance.createAnalysisContext(); | 84 var context = AnalysisEngine.instance.createAnalysisContext(); |
| 86 context.analysisOptions.strongMode = true; | 85 context.analysisOptions.strongMode = true; |
| 87 context.analysisOptions.strongModeHints = true; | 86 context.analysisOptions.strongModeHints = true; |
| 88 context.sourceFactory = new SourceFactory([ | 87 context.sourceFactory = new SourceFactory([ |
| 89 new MockDartSdk(_mockSdkSources, reportMissing: true).resolver, | 88 new DartUriResolver(new MockSdk()), |
| 90 uriResolver | 89 uriResolver |
| 91 ]); | 90 ]); |
| 92 | 91 |
| 93 // Run the checker on /main.dart. | 92 // Run the checker on /main.dart. |
| 94 Source mainSource = uriResolver.resolveAbsolute(new Uri.file('/main.dart')); | 93 Source mainSource = uriResolver.resolveAbsolute(new Uri.file('/main.dart')); |
| 95 var initialLibrary = | 94 var initialLibrary = |
| 96 context.resolveCompilationUnit2(mainSource, mainSource); | 95 context.resolveCompilationUnit2(mainSource, mainSource); |
| 97 | 96 |
| 98 var collector = new _ErrorCollector(); | 97 var collector = new _ErrorCollector(); |
| 99 var checker = new CodeChecker( | 98 var checker = new CodeChecker( |
| (...skipping 20 matching lines...) Expand all Loading... |
| 120 error.errorCode.name.startsWith('STRONG_MODE_INFERRED_TYPE')) | 119 error.errorCode.name.startsWith('STRONG_MODE_INFERRED_TYPE')) |
| 121 .toList(); | 120 .toList(); |
| 122 errors.addAll(analyzerErrors); | 121 errors.addAll(analyzerErrors); |
| 123 checker.visitCompilationUnit(resolved); | 122 checker.visitCompilationUnit(resolved); |
| 124 | 123 |
| 125 new _ExpectedErrorVisitor(errors).validate(resolved); | 124 new _ExpectedErrorVisitor(errors).validate(resolved); |
| 126 } | 125 } |
| 127 } | 126 } |
| 128 } | 127 } |
| 129 | 128 |
| 130 /// Sample mock SDK sources. | |
| 131 final Map<String, String> _mockSdkSources = { | |
| 132 // The list of types below is derived from: | |
| 133 // * types we use via our smoke queries, including HtmlElement and | |
| 134 // types from `_typeHandlers` (deserialize.dart) | |
| 135 // * types that are used internally by the resolver (see | |
| 136 // _initializeFrom in resolver.dart). | |
| 137 'dart:core': ''' | |
| 138 library dart.core; | |
| 139 | |
| 140 void print(Object o) {} | |
| 141 | |
| 142 class Object { | |
| 143 int get hashCode {} | |
| 144 Type get runtimeType {} | |
| 145 String toString(){} | |
| 146 bool ==(other){} | |
| 147 } | |
| 148 class Function {} | |
| 149 class StackTrace {} | |
| 150 class Symbol {} | |
| 151 class Type {} | |
| 152 | |
| 153 class String { | |
| 154 String operator +(String other) {} | |
| 155 String substring(int len) {} | |
| 156 } | |
| 157 class bool {} | |
| 158 class num { | |
| 159 num operator +(num other) {} | |
| 160 } | |
| 161 class int extends num { | |
| 162 bool operator<(num other) {} | |
| 163 int operator-() {} | |
| 164 } | |
| 165 class double extends num {} | |
| 166 class DateTime {} | |
| 167 class Null {} | |
| 168 | |
| 169 class Deprecated { | |
| 170 final String expires; | |
| 171 const Deprecated(this.expires); | |
| 172 } | |
| 173 const Object deprecated = const Deprecated("next release"); | |
| 174 class _Override { const _Override(); } | |
| 175 const Object override = const _Override(); | |
| 176 class _Proxy { const _Proxy(); } | |
| 177 const Object proxy = const _Proxy(); | |
| 178 | |
| 179 class Iterable<E> { | |
| 180 Iterable/*<R>*/ map/*<R>*/(/*=R*/ f(E e)); | |
| 181 | |
| 182 /*=R*/ fold/*<R>*/(/*=R*/ initialValue, | |
| 183 /*=R*/ combine(/*=R*/ previousValue, E element)); | |
| 184 } | |
| 185 class List<E> implements Iterable<E> { | |
| 186 List([int length]); | |
| 187 List.filled(int length, E fill); | |
| 188 } | |
| 189 class Map<K, V> { | |
| 190 Iterable<K> get keys {} | |
| 191 } | |
| 192 ''', | |
| 193 'dart:async': ''' | |
| 194 library dart.async; | |
| 195 class Future<T> { | |
| 196 Future(computation()) {} | |
| 197 Future.value(T t) {} | |
| 198 static Future<List/*<T>*/> wait/*<T>*/( | |
| 199 Iterable<Future/*<T>*/> futures) => null; | |
| 200 Future/*<R>*/ then/*<R>*/(/*=R*/ onValue(T value)) => null; | |
| 201 } | |
| 202 class Stream<T> {} | |
| 203 ''', | |
| 204 'dart:html': ''' | |
| 205 library dart.html; | |
| 206 class HtmlElement {} | |
| 207 ''', | |
| 208 'dart:math': ''' | |
| 209 library dart.math; | |
| 210 class Random { | |
| 211 bool nextBool() {} | |
| 212 } | |
| 213 num/*=T*/ min/*<T extends num>*/(num/*=T*/ a, num/*=T*/ b) => null; | |
| 214 num/*=T*/ max/*<T extends num>*/(num/*=T*/ a, num/*=T*/ b) => null; | |
| 215 ''', | |
| 216 | |
| 217 'dart:_foreign_helper': ''' | |
| 218 library dart._foreign_helper; | |
| 219 | |
| 220 JS(String typeDescription, String codeTemplate, | |
| 221 [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11]) | |
| 222 {} | |
| 223 ''' | |
| 224 }; | |
| 225 | |
| 226 SourceSpanWithContext createSpanHelper( | 129 SourceSpanWithContext createSpanHelper( |
| 227 LineInfo lineInfo, int start, int end, Source source, String content) { | 130 LineInfo lineInfo, int start, int end, Source source, String content) { |
| 228 var startLoc = locationForOffset(lineInfo, source.uri, start); | 131 var startLoc = locationForOffset(lineInfo, source.uri, start); |
| 229 var endLoc = locationForOffset(lineInfo, source.uri, end); | 132 var endLoc = locationForOffset(lineInfo, source.uri, end); |
| 230 | 133 |
| 231 var lineStart = startLoc.offset - startLoc.column; | 134 var lineStart = startLoc.offset - startLoc.column; |
| 232 // Find the end of the line. This is not exposed directly on LineInfo, but | 135 // Find the end of the line. This is not exposed directly on LineInfo, but |
| 233 // we can find it pretty easily. | 136 // we can find it pretty easily. |
| 234 // TODO(jmesserly): for now we do the simple linear scan. Ideally we can get | 137 // TODO(jmesserly): for now we do the simple linear scan. Ideally we can get |
| 235 // some help from the LineInfo API. | 138 // some help from the LineInfo API. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 if (seen.contains(lib)) return; | 173 if (seen.contains(lib)) return; |
| 271 seen.add(lib); | 174 seen.add(lib); |
| 272 results.add(lib); | 175 results.add(lib); |
| 273 lib.importedLibraries.forEach(find); | 176 lib.importedLibraries.forEach(find); |
| 274 lib.exportedLibraries.forEach(find); | 177 lib.exportedLibraries.forEach(find); |
| 275 } | 178 } |
| 276 find(start); | 179 find(start); |
| 277 return results; | 180 return results; |
| 278 } | 181 } |
| 279 | 182 |
| 280 /// Dart SDK which contains a mock implementation of the SDK libraries. May be | 183 class _TestUriResolver extends ResourceUriResolver { |
| 281 /// used to speed up execution when most of the core libraries is not needed. | |
| 282 class MockDartSdk implements DartSdk { | |
| 283 final Map<Uri, _MockSdkSource> _sources = {}; | |
| 284 final bool reportMissing; | |
| 285 final Map<String, SdkLibrary> _libs = {}; | |
| 286 final String sdkVersion = '0'; | |
| 287 final AnalysisContext context = new SdkAnalysisContext(); | |
| 288 DartUriResolver _resolver; | |
| 289 MockDartSdk(Map<String, String> sources, {this.reportMissing}) { | |
| 290 sources.forEach((uriString, contents) { | |
| 291 var uri = Uri.parse(uriString); | |
| 292 _sources[uri] = new _MockSdkSource(uri, contents); | |
| 293 _libs[uriString] = new SdkLibraryImpl(uri.path) | |
| 294 ..setDart2JsLibrary() | |
| 295 ..setVmLibrary(); | |
| 296 }); | |
| 297 _resolver = new DartUriResolver(this); | |
| 298 context.sourceFactory = new SourceFactory([_resolver]); | |
| 299 } | |
| 300 DartUriResolver get resolver => _resolver; | |
| 301 | |
| 302 List<SdkLibrary> get sdkLibraries => _libs.values.toList(); | |
| 303 | |
| 304 List<String> get uris => _sources.keys.map((uri) => '$uri').toList(); | |
| 305 Source fromEncoding(UriKind kind, Uri uri) { | |
| 306 if (kind != UriKind.DART_URI) { | |
| 307 throw new UnsupportedError('expected dart: uri kind, got $kind.'); | |
| 308 } | |
| 309 return _getSource(uri); | |
| 310 } | |
| 311 | |
| 312 @override | |
| 313 Source fromFileUri(Uri uri) { | |
| 314 throw new UnsupportedError('MockDartSdk.fromFileUri'); | |
| 315 } | |
| 316 | |
| 317 SdkLibrary getSdkLibrary(String dartUri) => _libs[dartUri]; | |
| 318 | |
| 319 Source mapDartUri(String dartUri) => _getSource(Uri.parse(dartUri)); | |
| 320 | |
| 321 Source _getSource(Uri uri) { | |
| 322 var src = _sources[uri]; | |
| 323 if (src == null) { | |
| 324 if (reportMissing) print('warning: missing mock for $uri.'); | |
| 325 _sources[uri] = | |
| 326 src = new _MockSdkSource(uri, 'library dart.${uri.path};'); | |
| 327 } | |
| 328 return src; | |
| 329 } | |
| 330 } | |
| 331 | |
| 332 class TestUriResolver extends ResourceUriResolver { | |
| 333 final MemoryResourceProvider provider; | 184 final MemoryResourceProvider provider; |
| 334 TestUriResolver(provider) | 185 _TestUriResolver(provider) |
| 335 : provider = provider, | 186 : provider = provider, |
| 336 super(provider); | 187 super(provider); |
| 337 | 188 |
| 338 @override | 189 @override |
| 339 Source resolveAbsolute(Uri uri, [Uri actualUri]) { | 190 Source resolveAbsolute(Uri uri, [Uri actualUri]) { |
| 340 if (uri.scheme == 'package') { | 191 if (uri.scheme == 'package') { |
| 341 return (provider.getResource('/packages/' + uri.path) as File) | 192 return (provider.getResource('/packages/' + uri.path) as File) |
| 342 .createSource(uri); | 193 .createSource(uri); |
| 343 } | 194 } |
| 344 return super.resolveAbsolute(uri, actualUri); | 195 return super.resolveAbsolute(uri, actualUri); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 | 353 |
| 503 levelName = levelName.toLowerCase(); | 354 levelName = levelName.toLowerCase(); |
| 504 if (levelName == 'shout' || levelName == 'severe' || levelName == 'error') { | 355 if (levelName == 'shout' || levelName == 'severe' || levelName == 'error') { |
| 505 return RED_COLOR; | 356 return RED_COLOR; |
| 506 } | 357 } |
| 507 if (levelName == 'warning') return MAGENTA_COLOR; | 358 if (levelName == 'warning') return MAGENTA_COLOR; |
| 508 if (levelName == 'info') return CYAN_COLOR; | 359 if (levelName == 'info') return CYAN_COLOR; |
| 509 return null; | 360 return null; |
| 510 } | 361 } |
| 511 } | 362 } |
| 512 | |
| 513 class _MockSdkSource implements Source { | |
| 514 /// Absolute URI which this source can be imported from. | |
| 515 final Uri uri; | |
| 516 final String _contents; | |
| 517 | |
| 518 final int modificationStamp = 1; | |
| 519 | |
| 520 _MockSdkSource(this.uri, this._contents); | |
| 521 | |
| 522 TimestampedData<String> get contents => | |
| 523 new TimestampedData(modificationStamp, _contents); | |
| 524 | |
| 525 String get encoding => "${uriKind.encoding}$uri"; | |
| 526 | |
| 527 String get fullName => shortName; | |
| 528 | |
| 529 int get hashCode => uri.hashCode; | |
| 530 | |
| 531 bool get isInSystemLibrary => true; | |
| 532 | |
| 533 String get shortName => uri.path; | |
| 534 | |
| 535 Source get source => this; | |
| 536 | |
| 537 UriKind get uriKind => UriKind.DART_URI; | |
| 538 | |
| 539 bool exists() => true; | |
| 540 | |
| 541 Source resolveRelative(Uri relativeUri) => | |
| 542 throw new UnsupportedError('not expecting relative urls in dart: mocks'); | |
| 543 | |
| 544 Uri resolveRelativeUri(Uri relativeUri) => | |
| 545 throw new UnsupportedError('not expecting relative urls in dart: mocks'); | |
| 546 } | |
| OLD | NEW |