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 linter.src.sdk; | |
6 | |
7 import 'package:analyzer/file_system/file_system.dart' as resource; | |
8 import 'package:analyzer/file_system/memory_file_system.dart' as resource; | |
9 import 'package:analyzer/src/context/cache.dart' | |
10 show AnalysisCache, CachePartition; | |
11 import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl; | |
12 import 'package:analyzer/src/generated/engine.dart' | |
13 show AnalysisEngine, ChangeSet; | |
14 import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary; | |
15 import 'package:analyzer/src/generated/source.dart' | |
16 show DartUriResolver, Source, SourceFactory; | |
17 import 'package:analyzer/src/summary/idl.dart'; | |
18 | |
19 /// Mock SDK for testing purposes. | |
20 class MockSdk implements DartSdk { | |
21 static const _MockSdkLibrary LIB_CORE = const _MockSdkLibrary( | |
22 'dart:core', | |
23 '/lib/core/core.dart', | |
24 ''' | |
25 library dart.core; | |
26 | |
27 import 'dart:async'; | |
28 | |
29 class Object { | |
30 bool operator ==(other) => identical(this, other); | |
31 String toString() => 'a string'; | |
32 int get hashCode => 0; | |
33 } | |
34 | |
35 class Function {} | |
36 class StackTrace {} | |
37 class Symbol {} | |
38 class Type {} | |
39 | |
40 abstract class Comparable<T> { | |
41 int compareTo(T other); | |
42 } | |
43 | |
44 abstract class String implements Comparable<String> { | |
45 external factory String.fromCharCodes(Iterable<int> charCodes, | |
46 [int start = 0, int end]); | |
47 bool get isEmpty => false; | |
48 bool get isNotEmpty => false; | |
49 int get length => 0; | |
50 String toUpperCase(); | |
51 List<int> get codeUnits; | |
52 } | |
53 | |
54 class bool extends Object {} | |
55 abstract class num implements Comparable<num> { | |
56 bool operator <(num other); | |
57 bool operator <=(num other); | |
58 bool operator >(num other); | |
59 bool operator >=(num other); | |
60 num operator +(num other); | |
61 num operator -(num other); | |
62 num operator *(num other); | |
63 num operator /(num other); | |
64 int toInt(); | |
65 num abs(); | |
66 int round(); | |
67 } | |
68 abstract class int extends num { | |
69 bool get isEven => false; | |
70 int operator -(); | |
71 external static int parse(String source, | |
72 { int radix, | |
73 int onError(String source) }); | |
74 } | |
75 class double extends num {} | |
76 class DateTime extends Object {} | |
77 class Null extends Object {} | |
78 | |
79 class Deprecated extends Object { | |
80 final String expires; | |
81 const Deprecated(this.expires); | |
82 } | |
83 const Object deprecated = const Deprecated("next release"); | |
84 | |
85 class Iterator<E> { | |
86 bool moveNext(); | |
87 E get current; | |
88 } | |
89 | |
90 abstract class Iterable<E> { | |
91 Iterator<E> get iterator; | |
92 bool get isEmpty; | |
93 bool get isNotEmpty; | |
94 } | |
95 | |
96 abstract class List<E> implements Iterable<E> { | |
97 void add(E value); | |
98 E operator [](int index); | |
99 void operator []=(int index, E value); | |
100 Iterator<E> get iterator => null; | |
101 void clear(); | |
102 bool get isEmpty; | |
103 bool get isNotEmpty; | |
104 } | |
105 | |
106 abstract class Map<K, V> extends Object { | |
107 Iterable<K> get keys; | |
108 bool get isEmpty; | |
109 bool get isNotEmpty; | |
110 } | |
111 | |
112 external bool identical(Object a, Object b); | |
113 | |
114 void print(Object object) {} | |
115 | |
116 class _Override { | |
117 const _Override(); | |
118 } | |
119 const Object override = const _Override(); | |
120 | |
121 | |
122 abstract class RegExp { | |
123 external factory RegExp(String source, {bool multiLine: false, | |
124 bool caseSensitive: true}); | |
125 '''); | |
126 | |
127 static const _MockSdkLibrary LIB_ASYNC = const _MockSdkLibrary( | |
128 'dart:async', | |
129 '/lib/async/async.dart', | |
130 ''' | |
131 library dart.async; | |
132 | |
133 import 'dart:math'; | |
134 | |
135 part 'stream.dart'; | |
136 | |
137 class Future<T> { | |
138 factory Future.delayed(Duration duration, [T computation()]) => null; | |
139 factory Future.value([value]) => null; | |
140 static Future wait(List<Future> futures) => null; | |
141 } | |
142 ''', | |
143 const <_MockSdkFile>[ | |
144 const _MockSdkFile( | |
145 '/lib/async/stream.dart', | |
146 r''' | |
147 part of dart.async; | |
148 class Stream<T> {} | |
149 abstract class StreamTransformer<S, T> {} | |
150 ''') | |
151 ]); | |
152 | |
153 static const _MockSdkLibrary LIB_COLLECTION = const _MockSdkLibrary( | |
154 'dart:collection', | |
155 '/lib/collection/collection.dart', | |
156 ''' | |
157 library dart.collection; | |
158 | |
159 abstract class HashMap<K, V> implements Map<K, V> {} | |
160 '''); | |
161 | |
162 static const _MockSdkLibrary LIB_CONVERT = const _MockSdkLibrary( | |
163 'dart:convert', | |
164 '/lib/convert/convert.dart', | |
165 ''' | |
166 library dart.convert; | |
167 | |
168 import 'dart:async'; | |
169 | |
170 abstract class Converter<S, T> implements StreamTransformer {} | |
171 class JsonDecoder extends Converter<String, Object> {} | |
172 '''); | |
173 | |
174 static const _MockSdkLibrary LIB_MATH = const _MockSdkLibrary( | |
175 'dart:math', | |
176 '/lib/math/math.dart', | |
177 ''' | |
178 library dart.math; | |
179 const double E = 2.718281828459045; | |
180 const double PI = 3.1415926535897932; | |
181 const double LN10 = 2.302585092994046; | |
182 num min(num a, num b) => 0; | |
183 num max(num a, num b) => 0; | |
184 external double cos(num x); | |
185 external double sin(num x); | |
186 external double sqrt(num x); | |
187 class Random { | |
188 bool nextBool() => true; | |
189 double nextDouble() => 2.0; | |
190 int nextInt() => 1; | |
191 } | |
192 '''); | |
193 | |
194 static const _MockSdkLibrary LIB_HTML = const _MockSdkLibrary( | |
195 'dart:html', | |
196 '/lib/html/dartium/html_dartium.dart', | |
197 ''' | |
198 library dart.html; | |
199 class HtmlElement {} | |
200 '''); | |
201 | |
202 static const List<SdkLibrary> LIBRARIES = const [ | |
203 LIB_CORE, | |
204 LIB_ASYNC, | |
205 LIB_COLLECTION, | |
206 LIB_CONVERT, | |
207 LIB_MATH, | |
208 LIB_HTML, | |
209 ]; | |
210 | |
211 final resource.MemoryResourceProvider provider = | |
212 new resource.MemoryResourceProvider(); | |
213 | |
214 /// The [AnalysisContextImpl] which is used for all of the sources. | |
215 AnalysisContextImpl _analysisContext; | |
216 | |
217 MockSdk() { | |
218 LIBRARIES.forEach((SdkLibrary library) { | |
219 if (library is _MockSdkLibrary) { | |
220 provider.newFile(library.path, library.content); | |
221 library.parts.forEach((file) { | |
222 provider.newFile(file.path, file.content); | |
223 }); | |
224 } | |
225 }); | |
226 } | |
227 | |
228 @override | |
229 AnalysisContextImpl get context { | |
230 if (_analysisContext == null) { | |
231 _analysisContext = new _SdkAnalysisContext(this); | |
232 SourceFactory factory = new SourceFactory([new DartUriResolver(this)]); | |
233 _analysisContext.sourceFactory = factory; | |
234 ChangeSet changeSet = new ChangeSet(); | |
235 for (String uri in uris) { | |
236 Source source = factory.forUri(uri); | |
237 changeSet.addedSource(source); | |
238 } | |
239 _analysisContext.applyChanges(changeSet); | |
240 } | |
241 return _analysisContext; | |
242 } | |
243 | |
244 @override | |
245 List<SdkLibrary> get sdkLibraries => LIBRARIES; | |
246 | |
247 @override | |
248 String get sdkVersion => throw unimplemented; | |
249 | |
250 UnimplementedError get unimplemented => new UnimplementedError(); | |
251 | |
252 @override | |
253 List<String> get uris { | |
254 List<String> uris = <String>[]; | |
255 for (SdkLibrary library in LIBRARIES) { | |
256 uris.add(library.shortName); | |
257 } | |
258 return uris; | |
259 } | |
260 | |
261 @override | |
262 Source fromFileUri(Uri uri) { | |
263 String filePath = uri.path; | |
264 String libPath = '/lib'; | |
265 if (!filePath.startsWith("$libPath/")) { | |
266 return null; | |
267 } | |
268 for (SdkLibrary library in LIBRARIES) { | |
269 String libraryPath = library.path; | |
270 if (filePath.replaceAll('\\', '/') == libraryPath) { | |
271 try { | |
272 resource.File file = provider.getResource(uri.path); | |
273 Uri dartUri = Uri.parse(library.shortName); | |
274 return file.createSource(dartUri); | |
275 } catch (exception) { | |
276 return null; | |
277 } | |
278 } | |
279 if (filePath.startsWith("$libraryPath/")) { | |
280 String pathInLibrary = filePath.substring(libraryPath.length + 1); | |
281 String path = '${library.shortName}/$pathInLibrary'; | |
282 try { | |
283 resource.File file = provider.getResource(uri.path); | |
284 Uri dartUri = new Uri(scheme: 'dart', path: path); | |
285 return file.createSource(dartUri); | |
286 } catch (exception) { | |
287 return null; | |
288 } | |
289 } | |
290 } | |
291 return null; | |
292 } | |
293 | |
294 @override | |
295 PackageBundle getLinkedBundle() => null; | |
296 | |
297 @override | |
298 SdkLibrary getSdkLibrary(String dartUri) { | |
299 // getSdkLibrary() is only used to determine whether a library is internal | |
300 // to the SDK. The mock SDK doesn't have any internals, so it's safe to | |
301 // return null. | |
302 return null; | |
303 } | |
304 | |
305 @override | |
306 Source mapDartUri(String dartUri) { | |
307 const Map<String, String> uriToPath = const { | |
308 "dart:core": "/lib/core/core.dart", | |
309 "dart:html": "/lib/html/dartium/html_dartium.dart", | |
310 "dart:async": "/lib/async/async.dart", | |
311 "dart:async/stream.dart": "/lib/async/stream.dart", | |
312 "dart:collection": "/lib/collection/collection.dart", | |
313 "dart:convert": "/lib/convert/convert.dart", | |
314 "dart:math": "/lib/math/math.dart" | |
315 }; | |
316 | |
317 String path = uriToPath[dartUri]; | |
318 if (path != null) { | |
319 resource.File file = provider.getResource(path); | |
320 Uri uri = new Uri(scheme: 'dart', path: dartUri.substring(5)); | |
321 return file.createSource(uri); | |
322 } | |
323 | |
324 // If we reach here then we tried to use a dartUri that's not in the | |
325 // table above. | |
326 return null; | |
327 } | |
328 } | |
329 | |
330 class _MockSdkFile { | |
331 final String path; | |
332 final String content; | |
333 | |
334 const _MockSdkFile(this.path, this.content); | |
335 } | |
336 | |
337 class _MockSdkLibrary implements SdkLibrary { | |
338 @override | |
339 final String shortName; | |
340 @override | |
341 final String path; | |
342 final String content; | |
343 final List<_MockSdkFile> parts; | |
344 | |
345 const _MockSdkLibrary(this.shortName, this.path, this.content, | |
346 [this.parts = const <_MockSdkFile>[]]); | |
347 | |
348 @override | |
349 String get category => throw unimplemented; | |
350 | |
351 @override | |
352 bool get isDart2JsLibrary => throw unimplemented; | |
353 | |
354 @override | |
355 bool get isDocumented => throw unimplemented; | |
356 | |
357 @override | |
358 bool get isImplementation => throw unimplemented; | |
359 | |
360 @override | |
361 bool get isInternal => throw unimplemented; | |
362 | |
363 @override | |
364 bool get isShared => throw unimplemented; | |
365 | |
366 @override | |
367 bool get isVmLibrary => throw unimplemented; | |
368 | |
369 UnimplementedError get unimplemented => new UnimplementedError(); | |
370 } | |
371 | |
372 /// An [AnalysisContextImpl] that only contains sources for a Dart SDK. | |
373 class _SdkAnalysisContext extends AnalysisContextImpl { | |
374 final DartSdk sdk; | |
375 | |
376 _SdkAnalysisContext(this.sdk); | |
377 | |
378 @override | |
379 AnalysisCache createCacheFromSourceFactory(SourceFactory factory) { | |
380 if (factory == null) { | |
381 return super.createCacheFromSourceFactory(factory); | |
382 } | |
383 return new AnalysisCache( | |
384 <CachePartition>[AnalysisEngine.instance.partitionManager.forSdk(sdk)]); | |
385 } | |
386 } | |
OLD | NEW |