OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2017, 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 import 'package:analyzer/file_system/file_system.dart' as resource; |
| 6 import 'package:analyzer/file_system/memory_file_system.dart' as resource; |
| 7 import 'package:analyzer/src/context/context.dart'; |
| 8 import 'package:analyzer/src/generated/engine.dart'; |
| 9 import 'package:analyzer/src/generated/sdk.dart'; |
| 10 import 'package:analyzer/src/generated/source.dart'; |
| 11 import 'package:analyzer/src/summary/idl.dart' show PackageBundle; |
| 12 import 'package:analyzer/src/summary/summary_file_builder.dart'; |
| 13 |
| 14 /** |
| 15 * A utility class that will create a Mock SDK on the virtual disk managed by a |
| 16 * memory resource provider. |
| 17 */ |
| 18 class MockSdk implements DartSdk { |
| 19 static const MockSdkLibrary LIB_CORE = const MockSdkLibrary( |
| 20 'dart:core', |
| 21 '/lib/core/core.dart', |
| 22 ''' |
| 23 library dart.core; |
| 24 |
| 25 import 'dart:async'; |
| 26 import 'dart:_internal'; |
| 27 |
| 28 class Object { |
| 29 const Object() {} |
| 30 bool operator ==(other) => identical(this, other); |
| 31 String toString() => 'a string'; |
| 32 int get hashCode => 0; |
| 33 Type get runtimeType => null; |
| 34 dynamic noSuchMethod(Invocation invocation) => null; |
| 35 } |
| 36 |
| 37 class Function {} |
| 38 class StackTrace {} |
| 39 class Symbol {} |
| 40 class Type {} |
| 41 |
| 42 abstract class Comparable<T> { |
| 43 int compareTo(T other); |
| 44 } |
| 45 |
| 46 abstract class String implements Comparable<String> { |
| 47 external factory String.fromCharCodes(Iterable<int> charCodes, |
| 48 [int start = 0, int end]); |
| 49 bool get isEmpty => false; |
| 50 bool get isNotEmpty => false; |
| 51 int get length => 0; |
| 52 String toUpperCase(); |
| 53 List<int> get codeUnits; |
| 54 } |
| 55 |
| 56 class bool extends Object {} |
| 57 |
| 58 abstract class num implements Comparable<num> { |
| 59 bool operator <(num other); |
| 60 bool operator <=(num other); |
| 61 bool operator >(num other); |
| 62 bool operator >=(num other); |
| 63 num operator +(num other); |
| 64 num operator -(num other); |
| 65 num operator *(num other); |
| 66 num operator /(num other); |
| 67 int operator ^(int other); |
| 68 int operator &(int other); |
| 69 int operator |(int other); |
| 70 int operator <<(int other); |
| 71 int operator >>(int other); |
| 72 int operator ~/(num other); |
| 73 num operator %(num other); |
| 74 int operator ~(); |
| 75 int toInt(); |
| 76 double toDouble(); |
| 77 num abs(); |
| 78 int round(); |
| 79 } |
| 80 |
| 81 abstract class int extends num { |
| 82 bool get isEven => false; |
| 83 int operator -(); |
| 84 external static int parse(String source, |
| 85 { int radix, |
| 86 int onError(String source) }); |
| 87 } |
| 88 |
| 89 abstract class double extends num { |
| 90 static const double NAN = 0.0 / 0.0; |
| 91 static const double INFINITY = 1.0 / 0.0; |
| 92 static const double NEGATIVE_INFINITY = -INFINITY; |
| 93 static const double MIN_POSITIVE = 5e-324; |
| 94 static const double MAX_FINITE = 1.7976931348623157e+308; |
| 95 |
| 96 double remainder(num other); |
| 97 double operator +(num other); |
| 98 double operator -(num other); |
| 99 double operator *(num other); |
| 100 double operator %(num other); |
| 101 double operator /(num other); |
| 102 int operator ~/(num other); |
| 103 double operator -(); |
| 104 double abs(); |
| 105 double get sign; |
| 106 int round(); |
| 107 int floor(); |
| 108 int ceil(); |
| 109 int truncate(); |
| 110 double roundToDouble(); |
| 111 double floorToDouble(); |
| 112 double ceilToDouble(); |
| 113 double truncateToDouble(); |
| 114 external static double parse(String source, |
| 115 [double onError(String source)]); |
| 116 } |
| 117 |
| 118 class DateTime extends Object {} |
| 119 class Null extends Object {} |
| 120 |
| 121 class Deprecated extends Object { |
| 122 final String expires; |
| 123 const Deprecated(this.expires); |
| 124 } |
| 125 const Object deprecated = const Deprecated("next release"); |
| 126 |
| 127 class Iterator<E> { |
| 128 bool moveNext(); |
| 129 E get current; |
| 130 } |
| 131 |
| 132 abstract class Iterable<E> { |
| 133 Iterator<E> get iterator; |
| 134 bool get isEmpty; |
| 135 Iterable/*<R>*/ map/*<R>*/(/*=R*/ f(E e)); |
| 136 } |
| 137 |
| 138 class List<E> implements Iterable<E> { |
| 139 List(); |
| 140 void add(E value) {} |
| 141 void addAll(Iterable<E> iterable) {} |
| 142 E operator [](int index) => null; |
| 143 void operator []=(int index, E value) {} |
| 144 Iterator<E> get iterator => null; |
| 145 void clear() {} |
| 146 |
| 147 bool get isEmpty => false; |
| 148 E get first => null; |
| 149 E get last => null; |
| 150 |
| 151 Iterable/*<R>*/ map/*<R>*/(/*=R*/ f(E e)) => null; |
| 152 |
| 153 /*=R*/ fold/*<R>*/(/*=R*/ initialValue, |
| 154 /*=R*/ combine(/*=R*/ previousValue, E element)) => null; |
| 155 |
| 156 } |
| 157 |
| 158 abstract class Map<K, V> extends Object { |
| 159 bool containsKey(Object key); |
| 160 Iterable<K> get keys; |
| 161 } |
| 162 |
| 163 external bool identical(Object a, Object b); |
| 164 |
| 165 void print(Object object) {} |
| 166 |
| 167 class Uri { |
| 168 static List<int> parseIPv6Address(String host, [int start = 0, int end]) { |
| 169 int parseHex(int start, int end) { |
| 170 return 0; |
| 171 } |
| 172 return null; |
| 173 } |
| 174 } |
| 175 '''); |
| 176 |
| 177 static const MockSdkLibrary LIB_ASYNC = const MockSdkLibrary( |
| 178 'dart:async', |
| 179 '/lib/async/async.dart', |
| 180 ''' |
| 181 library dart.async; |
| 182 |
| 183 import 'dart:math'; |
| 184 |
| 185 class Future<T> { |
| 186 factory Future(computation()) => null; |
| 187 factory Future.delayed(Duration duration, [T computation()]) => null; |
| 188 factory Future.value([value]) => null; |
| 189 static Future wait(List<Future> futures) => null; |
| 190 } |
| 191 |
| 192 class FutureOr<T> {} |
| 193 |
| 194 class Stream<T> {} |
| 195 abstract class StreamTransformer<S, T> {} |
| 196 '''); |
| 197 |
| 198 static const MockSdkLibrary LIB_COLLECTION = const MockSdkLibrary( |
| 199 'dart:collection', |
| 200 '/lib/collection/collection.dart', |
| 201 ''' |
| 202 library dart.collection; |
| 203 |
| 204 abstract class HashMap<K, V> implements Map<K, V> {} |
| 205 abstract class LinkedHashMap<K, V> implements Map<K, V> {} |
| 206 '''); |
| 207 |
| 208 static const MockSdkLibrary LIB_CONVERT = const MockSdkLibrary( |
| 209 'dart:convert', |
| 210 '/lib/convert/convert.dart', |
| 211 ''' |
| 212 library dart.convert; |
| 213 |
| 214 import 'dart:async'; |
| 215 |
| 216 abstract class Converter<S, T> implements StreamTransformer {} |
| 217 class JsonDecoder extends Converter<String, Object> {} |
| 218 '''); |
| 219 |
| 220 static const MockSdkLibrary LIB_MATH = const MockSdkLibrary( |
| 221 'dart:math', |
| 222 '/lib/math/math.dart', |
| 223 ''' |
| 224 library dart.math; |
| 225 const double E = 2.718281828459045; |
| 226 const double PI = 3.1415926535897932; |
| 227 const double LN10 = 2.302585092994046; |
| 228 T min<T extends num>(T a, T b) => null; |
| 229 T max<T extends num>(T a, T b) => null; |
| 230 external double cos(num radians); |
| 231 external num pow(num x, num exponent); |
| 232 external double sin(num radians); |
| 233 external double sqrt(num x); |
| 234 class Random { |
| 235 bool nextBool() => true; |
| 236 double nextDouble() => 2.0; |
| 237 int nextInt() => 1; |
| 238 } |
| 239 '''); |
| 240 |
| 241 static const MockSdkLibrary LIB_HTML = const MockSdkLibrary( |
| 242 'dart:html', |
| 243 '/lib/html/dartium/html_dartium.dart', |
| 244 ''' |
| 245 library dart.html; |
| 246 class HtmlElement {} |
| 247 '''); |
| 248 |
| 249 static const MockSdkLibrary LIB_INTERNAL = const MockSdkLibrary( |
| 250 'dart:_internal', |
| 251 '/lib/internal/internal.dart', |
| 252 ''' |
| 253 library dart._internal; |
| 254 external void printToConsole(String line); |
| 255 '''); |
| 256 |
| 257 static const List<SdkLibrary> LIBRARIES = const [ |
| 258 LIB_CORE, |
| 259 LIB_ASYNC, |
| 260 LIB_COLLECTION, |
| 261 LIB_CONVERT, |
| 262 LIB_MATH, |
| 263 LIB_HTML, |
| 264 LIB_INTERNAL, |
| 265 ]; |
| 266 |
| 267 static const String librariesContent = r''' |
| 268 const Map<String, LibraryInfo> libraries = const { |
| 269 "async": const LibraryInfo("async/async.dart"), |
| 270 "collection": const LibraryInfo("collection/collection.dart"), |
| 271 "convert": const LibraryInfo("convert/convert.dart"), |
| 272 "core": const LibraryInfo("core/core.dart"), |
| 273 "html": const LibraryInfo("html/dartium/html_dartium.dart"), |
| 274 "math": const LibraryInfo("math/math.dart"), |
| 275 "_internal": const LibraryInfo("internal/internal.dart"), |
| 276 }; |
| 277 '''; |
| 278 |
| 279 final resource.MemoryResourceProvider provider; |
| 280 |
| 281 /** |
| 282 * The [AnalysisContext] which is used for all of the sources. |
| 283 */ |
| 284 InternalAnalysisContext _analysisContext; |
| 285 |
| 286 /** |
| 287 * The cached linked bundle of the SDK. |
| 288 */ |
| 289 PackageBundle _bundle; |
| 290 |
| 291 MockSdk( |
| 292 {bool generateSummaryFiles: false, |
| 293 resource.ResourceProvider resourceProvider}) |
| 294 : provider = resourceProvider ?? new resource.MemoryResourceProvider() { |
| 295 LIBRARIES.forEach((SdkLibrary library) { |
| 296 provider.newFile(library.path, (library as MockSdkLibrary).content); |
| 297 }); |
| 298 provider.newFile( |
| 299 provider.convertPath( |
| 300 '/lib/_internal/sdk_library_metadata/lib/libraries.dart'), |
| 301 librariesContent); |
| 302 if (generateSummaryFiles) { |
| 303 List<int> bytes = _computeLinkedBundleBytes(); |
| 304 provider.newFileWithBytes( |
| 305 provider.convertPath('/lib/_internal/spec.sum'), bytes); |
| 306 provider.newFileWithBytes( |
| 307 provider.convertPath('/lib/_internal/strong.sum'), bytes); |
| 308 } |
| 309 } |
| 310 |
| 311 @override |
| 312 AnalysisContext get context { |
| 313 if (_analysisContext == null) { |
| 314 _analysisContext = new SdkAnalysisContext(null); |
| 315 SourceFactory factory = new SourceFactory([new DartUriResolver(this)]); |
| 316 _analysisContext.sourceFactory = factory; |
| 317 } |
| 318 return _analysisContext; |
| 319 } |
| 320 |
| 321 @override |
| 322 List<SdkLibrary> get sdkLibraries => LIBRARIES; |
| 323 |
| 324 @override |
| 325 String get sdkVersion => throw unimplemented; |
| 326 |
| 327 UnimplementedError get unimplemented => new UnimplementedError(); |
| 328 |
| 329 @override |
| 330 List<String> get uris { |
| 331 List<String> uris = <String>[]; |
| 332 for (SdkLibrary library in LIBRARIES) { |
| 333 uris.add(library.shortName); |
| 334 } |
| 335 return uris; |
| 336 } |
| 337 |
| 338 @override |
| 339 Source fromFileUri(Uri uri) { |
| 340 String filePath = provider.pathContext.fromUri(uri); |
| 341 for (SdkLibrary library in sdkLibraries) { |
| 342 String libraryPath = provider.convertPath(library.path); |
| 343 if (filePath == libraryPath) { |
| 344 try { |
| 345 resource.File file = provider.getResource(filePath); |
| 346 Uri dartUri = Uri.parse(library.shortName); |
| 347 return file.createSource(dartUri); |
| 348 } catch (exception) { |
| 349 return null; |
| 350 } |
| 351 } |
| 352 String libraryRootPath = provider.pathContext.dirname(libraryPath) + |
| 353 provider.pathContext.separator; |
| 354 if (filePath.startsWith(libraryRootPath)) { |
| 355 String pathInLibrary = filePath.substring(libraryRootPath.length); |
| 356 String uriStr = '${library.shortName}/$pathInLibrary'; |
| 357 try { |
| 358 resource.File file = provider.getResource(filePath); |
| 359 Uri dartUri = Uri.parse(uriStr); |
| 360 return file.createSource(dartUri); |
| 361 } catch (exception) { |
| 362 return null; |
| 363 } |
| 364 } |
| 365 } |
| 366 return null; |
| 367 } |
| 368 |
| 369 @override |
| 370 PackageBundle getLinkedBundle() { |
| 371 if (_bundle == null) { |
| 372 resource.File summaryFile = |
| 373 provider.getFile(provider.convertPath('/lib/_internal/spec.sum')); |
| 374 List<int> bytes; |
| 375 if (summaryFile.exists) { |
| 376 bytes = summaryFile.readAsBytesSync(); |
| 377 } else { |
| 378 bytes = _computeLinkedBundleBytes(); |
| 379 } |
| 380 _bundle = new PackageBundle.fromBuffer(bytes); |
| 381 } |
| 382 return _bundle; |
| 383 } |
| 384 |
| 385 @override |
| 386 SdkLibrary getSdkLibrary(String dartUri) { |
| 387 // getSdkLibrary() is only used to determine whether a library is internal |
| 388 // to the SDK. The mock SDK doesn't have any internals, so it's safe to |
| 389 // return null. |
| 390 return null; |
| 391 } |
| 392 |
| 393 @override |
| 394 Source mapDartUri(String dartUri) { |
| 395 const Map<String, String> uriToPath = const { |
| 396 "dart:core": "/lib/core/core.dart", |
| 397 "dart:html": "/lib/html/dartium/html_dartium.dart", |
| 398 "dart:async": "/lib/async/async.dart", |
| 399 "dart:collection": "/lib/collection/collection.dart", |
| 400 "dart:convert": "/lib/convert/convert.dart", |
| 401 "dart:math": "/lib/math/math.dart", |
| 402 "dart:_internal": "/lib/internal/internal.dart", |
| 403 }; |
| 404 |
| 405 String path = uriToPath[dartUri]; |
| 406 if (path != null) { |
| 407 resource.File file = provider.getResource(path); |
| 408 Uri uri = new Uri(scheme: 'dart', path: dartUri.substring(5)); |
| 409 return file.createSource(uri); |
| 410 } |
| 411 |
| 412 // If we reach here then we tried to use a dartUri that's not in the |
| 413 // table above. |
| 414 return null; |
| 415 } |
| 416 |
| 417 /** |
| 418 * Compute the bytes of the linked bundle associated with this SDK. |
| 419 */ |
| 420 List<int> _computeLinkedBundleBytes() { |
| 421 List<Source> librarySources = sdkLibraries |
| 422 .map((SdkLibrary library) => mapDartUri(library.shortName)) |
| 423 .toList(); |
| 424 return new SummaryBuilder( |
| 425 librarySources, context, context.analysisOptions.strongMode) |
| 426 .build(); |
| 427 } |
| 428 } |
| 429 |
| 430 class MockSdkLibrary implements SdkLibrary { |
| 431 @override |
| 432 final String shortName; |
| 433 |
| 434 @override |
| 435 final String path; |
| 436 |
| 437 final String content; |
| 438 |
| 439 const MockSdkLibrary(this.shortName, this.path, this.content); |
| 440 |
| 441 @override |
| 442 String get category => throw unimplemented; |
| 443 |
| 444 @override |
| 445 bool get isDart2JsLibrary => throw unimplemented; |
| 446 |
| 447 @override |
| 448 bool get isDocumented => throw unimplemented; |
| 449 |
| 450 @override |
| 451 bool get isImplementation => false; |
| 452 |
| 453 @override |
| 454 bool get isInternal => shortName.startsWith('dart:_'); |
| 455 |
| 456 @override |
| 457 bool get isShared => throw unimplemented; |
| 458 |
| 459 @override |
| 460 bool get isVmLibrary => throw unimplemented; |
| 461 |
| 462 UnimplementedError get unimplemented => new UnimplementedError(); |
| 463 } |
OLD | NEW |