OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library analyzer.src.generated.sdk_io; | 5 library analyzer.src.generated.sdk2; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 import 'dart:io'; | 8 import 'dart:io' as io; |
9 | 9 |
10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| 11 import 'package:analyzer/file_system/file_system.dart'; |
11 import 'package:analyzer/src/context/context.dart'; | 12 import 'package:analyzer/src/context/context.dart'; |
12 import 'package:analyzer/src/dart/scanner/reader.dart'; | 13 import 'package:analyzer/src/dart/scanner/reader.dart'; |
13 import 'package:analyzer/src/dart/scanner/scanner.dart'; | 14 import 'package:analyzer/src/dart/scanner/scanner.dart'; |
14 import 'package:analyzer/src/generated/engine.dart'; | 15 import 'package:analyzer/src/generated/engine.dart'; |
15 import 'package:analyzer/src/generated/error.dart'; | 16 import 'package:analyzer/src/generated/error.dart'; |
16 import 'package:analyzer/src/generated/java_core.dart'; | 17 import 'package:analyzer/src/generated/java_core.dart'; |
17 import 'package:analyzer/src/generated/java_engine.dart'; | 18 import 'package:analyzer/src/generated/java_engine.dart'; |
18 import 'package:analyzer/src/generated/java_engine_io.dart'; | 19 import 'package:analyzer/src/generated/java_engine_io.dart'; |
19 import 'package:analyzer/src/generated/java_io.dart'; | |
20 import 'package:analyzer/src/generated/parser.dart'; | 20 import 'package:analyzer/src/generated/parser.dart'; |
21 import 'package:analyzer/src/generated/sdk.dart'; | 21 import 'package:analyzer/src/generated/sdk.dart'; |
22 import 'package:analyzer/src/generated/source_io.dart'; | 22 import 'package:analyzer/src/generated/source_io.dart'; |
23 import 'package:analyzer/src/summary/idl.dart' show PackageBundle; | 23 import 'package:analyzer/src/summary/idl.dart' show PackageBundle; |
24 import 'package:analyzer/src/summary/summary_sdk.dart'; | 24 import 'package:analyzer/src/summary/summary_sdk.dart'; |
25 import 'package:path/path.dart' as pathos; | 25 import 'package:path/path.dart' as pathos; |
| 26 import 'package:yaml/yaml.dart'; |
26 | 27 |
27 /** | 28 /** |
28 * An abstract implementation of a Dart SDK in which the available libraries are | 29 * An abstract implementation of a Dart SDK in which the available libraries are |
29 * stored in a library map. Subclasses are responsible for populating the | 30 * stored in a library map. Subclasses are responsible for populating the |
30 * library map. | 31 * library map. |
31 */ | 32 */ |
32 abstract class AbstractDartSdk implements DartSdk { | 33 abstract class AbstractDartSdk implements DartSdk { |
33 /** | 34 /** |
| 35 * The resource provider used to access the file system. |
| 36 */ |
| 37 ResourceProvider resourceProvider; |
| 38 |
| 39 /** |
34 * A mapping from Dart library URI's to the library represented by that URI. | 40 * A mapping from Dart library URI's to the library represented by that URI. |
35 */ | 41 */ |
36 LibraryMap libraryMap = new LibraryMap(); | 42 LibraryMap libraryMap = new LibraryMap(); |
37 | 43 |
38 /** | 44 /** |
39 * The [AnalysisOptions] to use to create the [context]. | 45 * The [AnalysisOptions] to use to create the [context]. |
40 */ | 46 */ |
41 AnalysisOptions _analysisOptions; | 47 AnalysisOptions _analysisOptions; |
42 | 48 |
43 /** | 49 /** |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 * Specify whether SDK summary should be used. | 107 * Specify whether SDK summary should be used. |
102 */ | 108 */ |
103 void set useSummary(bool use) { | 109 void set useSummary(bool use) { |
104 if (_analysisContext != null) { | 110 if (_analysisContext != null) { |
105 throw new StateError( | 111 throw new StateError( |
106 'The "useSummary" flag cannot be changed after context creation.'); | 112 'The "useSummary" flag cannot be changed after context creation.'); |
107 } | 113 } |
108 _useSummary = use; | 114 _useSummary = use; |
109 } | 115 } |
110 | 116 |
111 /** | |
112 * Add the extensions from one or more sdk extension files to this sdk. The | |
113 * [extensions] should be a table mapping the names of extensions to the paths | |
114 * where those extensions can be found. | |
115 */ | |
116 void addExtensions(Map<String, String> extensions) { | |
117 extensions.forEach((String uri, String path) { | |
118 String shortName = uri.substring(uri.indexOf(':') + 1); | |
119 SdkLibraryImpl library = new SdkLibraryImpl(shortName); | |
120 library.path = path; | |
121 libraryMap.setLibrary(uri, library); | |
122 }); | |
123 } | |
124 | |
125 @override | 117 @override |
126 Source fromFileUri(Uri uri) { | 118 Source fromFileUri(Uri uri) { |
127 JavaFile file = new JavaFile.fromUri(uri); | 119 File file = resourceProvider.getFile(uri.toFilePath(windows: false)); |
128 | 120 |
129 String path = _getPath(file); | 121 String path = _getPath(file); |
130 if (path == null) { | 122 if (path == null) { |
131 return null; | 123 return null; |
132 } | 124 } |
133 try { | 125 try { |
134 return new FileBasedSource(file, parseUriWithException(path)); | 126 return file.createSource(parseUriWithException(path)); |
135 } on URISyntaxException catch (exception, stackTrace) { | 127 } on URISyntaxException catch (exception, stackTrace) { |
136 AnalysisEngine.instance.logger.logInformation( | 128 AnalysisEngine.instance.logger.logInformation( |
137 "Failed to create URI: $path", | 129 "Failed to create URI: $path", |
138 new CaughtException(exception, stackTrace)); | 130 new CaughtException(exception, stackTrace)); |
139 } | 131 } |
140 return null; | 132 return null; |
141 } | 133 } |
142 | 134 |
143 String getRelativePathFromFile(JavaFile file); | 135 String getRelativePathFromFile(File file); |
144 | 136 |
145 @override | 137 @override |
146 SdkLibrary getSdkLibrary(String dartUri) => libraryMap.getLibrary(dartUri); | 138 SdkLibrary getSdkLibrary(String dartUri) => libraryMap.getLibrary(dartUri); |
147 | 139 |
148 /** | 140 /** |
149 * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise. | 141 * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise. |
150 * This method should not be used outside of `analyzer` and `analyzer_cli` | 142 * This method should not be used outside of `analyzer` and `analyzer_cli` |
151 * packages. | 143 * packages. |
152 */ | 144 */ |
153 PackageBundle getSummarySdkBundle(bool strongMode); | 145 PackageBundle getSummarySdkBundle(bool strongMode); |
154 | 146 |
155 FileBasedSource internalMapDartUri(String dartUri) { | 147 Source internalMapDartUri(String dartUri) { |
156 // TODO(brianwilkerson) Figure out how to unify the implementations in the | 148 // TODO(brianwilkerson) Figure out how to unify the implementations in the |
157 // two subclasses. | 149 // two subclasses. |
158 String libraryName; | 150 String libraryName; |
159 String relativePath; | 151 String relativePath; |
160 int index = dartUri.indexOf('/'); | 152 int index = dartUri.indexOf('/'); |
161 if (index >= 0) { | 153 if (index >= 0) { |
162 libraryName = dartUri.substring(0, index); | 154 libraryName = dartUri.substring(0, index); |
163 relativePath = dartUri.substring(index + 1); | 155 relativePath = dartUri.substring(index + 1); |
164 } else { | 156 } else { |
165 libraryName = dartUri; | 157 libraryName = dartUri; |
166 relativePath = ""; | 158 relativePath = ""; |
167 } | 159 } |
168 SdkLibrary library = getSdkLibrary(libraryName); | 160 SdkLibrary library = getSdkLibrary(libraryName); |
169 if (library == null) { | 161 if (library == null) { |
170 return null; | 162 return null; |
171 } | 163 } |
172 String srcPath; | 164 String srcPath; |
173 if (relativePath.isEmpty) { | 165 if (relativePath.isEmpty) { |
174 srcPath = library.path; | 166 srcPath = library.path; |
175 } else { | 167 } else { |
176 String libraryPath = library.path; | 168 String libraryPath = library.path; |
177 int index = libraryPath.lastIndexOf(JavaFile.separator); | 169 int index = libraryPath.lastIndexOf(resourceProvider.pathContext.separator
); |
178 if (index == -1) { | 170 if (index == -1) { |
179 index = libraryPath.lastIndexOf('/'); | 171 index = libraryPath.lastIndexOf('/'); |
180 if (index == -1) { | 172 if (index == -1) { |
181 return null; | 173 return null; |
182 } | 174 } |
183 } | 175 } |
184 String prefix = libraryPath.substring(0, index + 1); | 176 String prefix = libraryPath.substring(0, index + 1); |
185 srcPath = '$prefix$relativePath'; | 177 srcPath = '$prefix$relativePath'; |
186 } | 178 } |
187 String filePath = srcPath.replaceAll('/', JavaFile.separator); | 179 String filePath = srcPath.replaceAll('/', resourceProvider.pathContext.separ
ator); |
188 try { | 180 try { |
189 JavaFile file = new JavaFile(filePath); | 181 File file = resourceProvider.getFile(filePath); |
190 return new FileBasedSource(file, parseUriWithException(dartUri)); | 182 return file.createSource(parseUriWithException(dartUri)); |
191 } on URISyntaxException { | 183 } on URISyntaxException { |
192 return null; | 184 return null; |
193 } | 185 } |
194 } | 186 } |
195 | 187 |
196 @override | 188 @override |
197 Source mapDartUri(String dartUri) { | 189 Source mapDartUri(String dartUri) { |
198 Source source = _uriToSourceMap[dartUri]; | 190 Source source = _uriToSourceMap[dartUri]; |
199 if (source == null) { | 191 if (source == null) { |
200 source = internalMapDartUri(dartUri); | 192 source = internalMapDartUri(dartUri); |
201 _uriToSourceMap[dartUri] = source; | 193 _uriToSourceMap[dartUri] = source; |
202 } | 194 } |
203 return source; | 195 return source; |
204 } | 196 } |
205 | 197 |
206 String _getPath(JavaFile file) { | 198 String _getPath(File file) { |
207 List<SdkLibrary> libraries = libraryMap.sdkLibraries; | 199 List<SdkLibrary> libraries = libraryMap.sdkLibraries; |
208 int length = libraries.length; | 200 int length = libraries.length; |
209 List<String> paths = new List(length); | 201 List<String> paths = new List(length); |
210 String filePath = getRelativePathFromFile(file); | 202 String filePath = getRelativePathFromFile(file); |
211 if (filePath == null) { | 203 if (filePath == null) { |
212 return null; | 204 return null; |
213 } | 205 } |
214 for (int i = 0; i < length; i++) { | 206 for (int i = 0; i < length; i++) { |
215 SdkLibrary library = libraries[i]; | 207 SdkLibrary library = libraries[i]; |
216 String libraryPath = library.path.replaceAll('/', JavaFile.separator); | 208 String libraryPath = library.path.replaceAll('/', resourceProvider.pathCon
text.separator); |
217 if (filePath == libraryPath) { | 209 if (filePath == libraryPath) { |
218 return library.shortName; | 210 return library.shortName; |
219 } | 211 } |
220 paths[i] = libraryPath; | 212 paths[i] = libraryPath; |
221 } | 213 } |
222 for (int i = 0; i < length; i++) { | 214 for (int i = 0; i < length; i++) { |
223 SdkLibrary library = libraries[i]; | 215 SdkLibrary library = libraries[i]; |
224 String libraryPath = paths[i]; | 216 String libraryPath = paths[i]; |
225 int index = libraryPath.lastIndexOf(JavaFile.separator); | 217 int index = libraryPath.lastIndexOf(resourceProvider.pathContext.separator
); |
226 if (index >= 0) { | 218 if (index >= 0) { |
227 String prefix = libraryPath.substring(0, index + 1); | 219 String prefix = libraryPath.substring(0, index + 1); |
228 if (filePath.startsWith(prefix)) { | 220 if (filePath.startsWith(prefix)) { |
229 String relPath = filePath | 221 String relPath = filePath |
230 .substring(prefix.length) | 222 .substring(prefix.length) |
231 .replaceAll(JavaFile.separator, '/'); | 223 .replaceAll(resourceProvider.pathContext.separator, '/'); |
232 return '${library.shortName}/$relPath'; | 224 return '${library.shortName}/$relPath'; |
233 } | 225 } |
234 } | 226 } |
235 } | 227 } |
236 return null; | 228 return null; |
237 } | 229 } |
238 } | 230 } |
239 | 231 |
240 /** | 232 /** |
| 233 * An SDK backed by URI mappings derived from an `_embedder.yaml` file. |
| 234 */ |
| 235 class EmbedderSdk extends AbstractDartSdk { |
| 236 static const String _DART_COLON_PREFIX = 'dart:'; |
| 237 |
| 238 static const String _EMBEDDED_LIB_MAP_KEY = 'embedded_libs'; |
| 239 final Map<String, String> _urlMappings = new HashMap<String, String>(); |
| 240 |
| 241 EmbedderSdk( |
| 242 ResourceProvider resourceProvider, Map<Folder, YamlMap> embedderYamls) { |
| 243 this.resourceProvider = resourceProvider; |
| 244 embedderYamls?.forEach(_processEmbedderYaml); |
| 245 } |
| 246 |
| 247 @override |
| 248 // TODO(danrubel) Determine SDK version |
| 249 String get sdkVersion => '0'; |
| 250 |
| 251 /** |
| 252 * The url mappings for this SDK. |
| 253 */ |
| 254 Map<String, String> get urlMappings => _urlMappings; |
| 255 |
| 256 @override |
| 257 String getRelativePathFromFile(File file) => file.path; |
| 258 |
| 259 @override |
| 260 PackageBundle getSummarySdkBundle(bool strongMode) => null; |
| 261 |
| 262 @override |
| 263 Source internalMapDartUri(String dartUri) { |
| 264 String libraryName; |
| 265 String relativePath; |
| 266 int index = dartUri.indexOf('/'); |
| 267 if (index >= 0) { |
| 268 libraryName = dartUri.substring(0, index); |
| 269 relativePath = dartUri.substring(index + 1); |
| 270 } else { |
| 271 libraryName = dartUri; |
| 272 relativePath = ""; |
| 273 } |
| 274 SdkLibrary library = getSdkLibrary(libraryName); |
| 275 if (library == null) { |
| 276 return null; |
| 277 } |
| 278 String srcPath; |
| 279 if (relativePath.isEmpty) { |
| 280 srcPath = library.path; |
| 281 } else { |
| 282 String libraryPath = library.path; |
| 283 int index = libraryPath.lastIndexOf(resourceProvider.pathContext.separator
); |
| 284 if (index == -1) { |
| 285 index = libraryPath.lastIndexOf('/'); |
| 286 if (index == -1) { |
| 287 return null; |
| 288 } |
| 289 } |
| 290 String prefix = libraryPath.substring(0, index + 1); |
| 291 srcPath = '$prefix$relativePath'; |
| 292 } |
| 293 String filePath = srcPath.replaceAll('/', resourceProvider.pathContext.separ
ator); |
| 294 try { |
| 295 File file = resourceProvider.getFile(filePath); |
| 296 return file.createSource(parseUriWithException(dartUri)); |
| 297 } on URISyntaxException { |
| 298 return null; |
| 299 } |
| 300 } |
| 301 |
| 302 /** |
| 303 * Install the mapping from [name] to [libDir]/[file]. |
| 304 */ |
| 305 void _processEmbeddedLibs(String name, String file, Folder libDir) { |
| 306 if (!name.startsWith(_DART_COLON_PREFIX)) { |
| 307 // SDK libraries must begin with 'dart:'. |
| 308 return; |
| 309 } |
| 310 String libPath = libDir.canonicalizePath(file); |
| 311 _urlMappings[name] = libPath; |
| 312 SdkLibraryImpl library = new SdkLibraryImpl(name); |
| 313 library.path = libPath; |
| 314 libraryMap.setLibrary(name, library); |
| 315 } |
| 316 |
| 317 /** |
| 318 * Given the 'embedderYamls' from [EmbedderYamlLocator] check each one for the |
| 319 * top level key 'embedded_libs'. Under the 'embedded_libs' key are key value |
| 320 * pairs. Each key is a 'dart:' library uri and each value is a path |
| 321 * (relative to the directory containing `_embedder.yaml`) to a dart script |
| 322 * for the given library. For example: |
| 323 * |
| 324 * embedded_libs: |
| 325 * 'dart:io': '../../sdk/io/io.dart' |
| 326 * |
| 327 * If a key doesn't begin with `dart:` it is ignored. |
| 328 */ |
| 329 void _processEmbedderYaml(Folder libDir, YamlMap map) { |
| 330 YamlNode embedded_libs = map[_EMBEDDED_LIB_MAP_KEY]; |
| 331 if (embedded_libs is YamlMap) { |
| 332 embedded_libs.forEach((k, v) => _processEmbeddedLibs(k, v, libDir)); |
| 333 } |
| 334 } |
| 335 } |
| 336 |
| 337 /** |
241 * A Dart SDK installed in a specified directory. Typical Dart SDK layout is | 338 * A Dart SDK installed in a specified directory. Typical Dart SDK layout is |
242 * something like... | 339 * something like... |
243 * | 340 * |
244 * dart-sdk/ | 341 * dart-sdk/ |
245 * bin/ | 342 * bin/ |
246 * dart[.exe] <-- VM | 343 * dart[.exe] <-- VM |
247 * lib/ | 344 * lib/ |
248 * core/ | 345 * core/ |
249 * core.dart | 346 * core.dart |
250 * ... other core library files ... | 347 * ... other core library files ... |
251 * ... other libraries ... | 348 * ... other libraries ... |
252 * util/ | 349 * util/ |
253 * ... Dart utilities ... | 350 * ... Dart utilities ... |
254 * Chromium/ <-- Dartium typically exists in a sibling directory | 351 * Chromium/ <-- Dartium typically exists in a sibling directory |
255 */ | 352 */ |
256 class DirectoryBasedDartSdk extends AbstractDartSdk { | 353 class FolderBasedDartSdk extends AbstractDartSdk { |
257 /** | |
258 * The default SDK, or `null` if the default SDK either has not yet been | |
259 * created or cannot be created for some reason. | |
260 */ | |
261 static DirectoryBasedDartSdk _DEFAULT_SDK; | |
262 | |
263 /** | 354 /** |
264 * The name of the directory within the SDK directory that contains | 355 * The name of the directory within the SDK directory that contains |
265 * executables. | 356 * executables. |
266 */ | 357 */ |
267 static String _BIN_DIRECTORY_NAME = "bin"; | 358 static String _BIN_DIRECTORY_NAME = "bin"; |
268 | 359 |
269 /** | 360 /** |
270 * The name of the directory on non-Mac that contains dartium. | |
271 */ | |
272 static String _DARTIUM_DIRECTORY_NAME = "chromium"; | |
273 | |
274 /** | |
275 * The name of the dart2js executable on non-windows operating systems. | |
276 */ | |
277 static String _DART2JS_EXECUTABLE_NAME = "dart2js"; | |
278 | |
279 /** | |
280 * The name of the file containing the dart2js executable on Windows. | |
281 */ | |
282 static String _DART2JS_EXECUTABLE_NAME_WIN = "dart2js.bat"; | |
283 | |
284 /** | |
285 * The name of the file containing the Dartium executable on Linux. | |
286 */ | |
287 static String _DARTIUM_EXECUTABLE_NAME_LINUX = "chrome"; | |
288 | |
289 /** | |
290 * The name of the file containing the Dartium executable on Macintosh. | |
291 */ | |
292 static String _DARTIUM_EXECUTABLE_NAME_MAC = | |
293 "Chromium.app/Contents/MacOS/Chromium"; | |
294 | |
295 /** | |
296 * The name of the file containing the Dartium executable on Windows. | |
297 */ | |
298 static String _DARTIUM_EXECUTABLE_NAME_WIN = "Chrome.exe"; | |
299 | |
300 /** | |
301 * The name of the [System] property whose value is the path to the default | |
302 * Dart SDK directory. | |
303 */ | |
304 static String _DEFAULT_DIRECTORY_PROPERTY_NAME = "com.google.dart.sdk"; | |
305 | |
306 /** | |
307 * The name of the directory within the SDK directory that contains | 361 * The name of the directory within the SDK directory that contains |
308 * documentation for the libraries. | 362 * documentation for the libraries. |
309 */ | 363 */ |
310 static String _DOCS_DIRECTORY_NAME = "docs"; | 364 static String _DOCS_DIRECTORY_NAME = "docs"; |
311 | 365 |
312 /** | 366 /** |
313 * The suffix added to the name of a library to derive the name of the file | |
314 * containing the documentation for that library. | |
315 */ | |
316 static String _DOC_FILE_SUFFIX = "_api.json"; | |
317 | |
318 /** | |
319 * The name of the directory within the SDK directory that contains the | 367 * The name of the directory within the SDK directory that contains the |
320 * sdk_library_metadata directory. | 368 * sdk_library_metadata directory. |
321 */ | 369 */ |
322 static String _INTERNAL_DIR = "_internal"; | 370 static String _INTERNAL_DIR = "_internal"; |
323 | 371 |
324 /** | 372 /** |
325 * The name of the sdk_library_metadata directory that contains the package | 373 * The name of the sdk_library_metadata directory that contains the package |
326 * holding the libraries.dart file. | 374 * holding the libraries.dart file. |
327 */ | 375 */ |
328 static String _SDK_LIBRARY_METADATA_DIR = "sdk_library_metadata"; | 376 static String _SDK_LIBRARY_METADATA_DIR = "sdk_library_metadata"; |
(...skipping 25 matching lines...) Expand all Loading... |
354 */ | 402 */ |
355 static String _PUB_EXECUTABLE_NAME = "pub"; | 403 static String _PUB_EXECUTABLE_NAME = "pub"; |
356 | 404 |
357 /** | 405 /** |
358 * The name of the file within the SDK directory that contains the version | 406 * The name of the file within the SDK directory that contains the version |
359 * number of the SDK. | 407 * number of the SDK. |
360 */ | 408 */ |
361 static String _VERSION_FILE_NAME = "version"; | 409 static String _VERSION_FILE_NAME = "version"; |
362 | 410 |
363 /** | 411 /** |
364 * The name of the file containing the VM executable on the Windows operating | |
365 * system. | |
366 */ | |
367 static String _VM_EXECUTABLE_NAME_WIN = "dart.exe"; | |
368 | |
369 /** | |
370 * The name of the file containing the VM executable on non-Windows operating | |
371 * systems. | |
372 */ | |
373 static String _VM_EXECUTABLE_NAME = "dart"; | |
374 | |
375 /** | |
376 * Return the default Dart SDK, or `null` if the directory containing the | |
377 * default SDK cannot be determined (or does not exist). | |
378 */ | |
379 static DirectoryBasedDartSdk get defaultSdk { | |
380 if (_DEFAULT_SDK == null) { | |
381 JavaFile sdkDirectory = defaultSdkDirectory; | |
382 if (sdkDirectory == null) { | |
383 return null; | |
384 } | |
385 _DEFAULT_SDK = new DirectoryBasedDartSdk(sdkDirectory); | |
386 } | |
387 return _DEFAULT_SDK; | |
388 } | |
389 | |
390 /** | |
391 * Return the default directory for the Dart SDK, or `null` if the directory | |
392 * cannot be determined (or does not exist). The default directory is provided | |
393 * by a system property named `com.google.dart.sdk`. | |
394 */ | |
395 static JavaFile get defaultSdkDirectory { | |
396 String sdkProperty = | |
397 JavaSystemIO.getProperty(_DEFAULT_DIRECTORY_PROPERTY_NAME); | |
398 if (sdkProperty == null) { | |
399 return null; | |
400 } | |
401 JavaFile sdkDirectory = new JavaFile(sdkProperty); | |
402 if (!sdkDirectory.exists()) { | |
403 return null; | |
404 } | |
405 return sdkDirectory; | |
406 } | |
407 | |
408 /** | |
409 * The directory containing the SDK. | 412 * The directory containing the SDK. |
410 */ | 413 */ |
411 JavaFile _sdkDirectory; | 414 Folder _sdkDirectory; |
412 | 415 |
413 /** | 416 /** |
414 * The directory within the SDK directory that contains the libraries. | 417 * The directory within the SDK directory that contains the libraries. |
415 */ | 418 */ |
416 JavaFile _libraryDirectory; | 419 Folder _libraryDirectory; |
417 | 420 |
418 /** | 421 /** |
419 * The revision number of this SDK, or `"0"` if the revision number cannot be | 422 * The revision number of this SDK, or `"0"` if the revision number cannot be |
420 * discovered. | 423 * discovered. |
421 */ | 424 */ |
422 String _sdkVersion; | 425 String _sdkVersion; |
423 | 426 |
424 /** | 427 /** |
425 * The file containing the dart2js executable. | |
426 */ | |
427 JavaFile _dart2jsExecutable; | |
428 | |
429 /** | |
430 * The file containing the Dartium executable. | |
431 */ | |
432 JavaFile _dartiumExecutable; | |
433 | |
434 /** | |
435 * The file containing the pub executable. | 428 * The file containing the pub executable. |
436 */ | 429 */ |
437 JavaFile _pubExecutable; | 430 File _pubExecutable; |
438 | |
439 /** | |
440 * The file containing the VM executable. | |
441 */ | |
442 JavaFile _vmExecutable; | |
443 | 431 |
444 /** | 432 /** |
445 * Initialize a newly created SDK to represent the Dart SDK installed in the | 433 * Initialize a newly created SDK to represent the Dart SDK installed in the |
446 * [sdkDirectory]. The flag [useDart2jsPaths] is `true` if the dart2js path | 434 * [sdkDirectory]. The flag [useDart2jsPaths] is `true` if the dart2js path |
447 * should be used when it is available | 435 * should be used when it is available |
448 */ | 436 */ |
449 DirectoryBasedDartSdk(JavaFile sdkDirectory, [bool useDart2jsPaths = false]) { | 437 FolderBasedDartSdk(ResourceProvider resourceProvider, this._sdkDirectory, |
450 this._sdkDirectory = sdkDirectory.getAbsoluteFile(); | 438 [bool useDart2jsPaths = false]) { |
| 439 this.resourceProvider = resourceProvider; |
451 libraryMap = initialLibraryMap(useDart2jsPaths); | 440 libraryMap = initialLibraryMap(useDart2jsPaths); |
452 } | 441 } |
453 | 442 |
454 /** | 443 /** |
455 * Return the file containing the dart2js executable, or `null` if it does not | |
456 * exist. | |
457 */ | |
458 JavaFile get dart2JsExecutable { | |
459 if (_dart2jsExecutable == null) { | |
460 _dart2jsExecutable = _verifyExecutable(new JavaFile.relative( | |
461 new JavaFile.relative(_sdkDirectory, _BIN_DIRECTORY_NAME), | |
462 OSUtilities.isWindows() | |
463 ? _DART2JS_EXECUTABLE_NAME_WIN | |
464 : _DART2JS_EXECUTABLE_NAME)); | |
465 } | |
466 return _dart2jsExecutable; | |
467 } | |
468 | |
469 /** | |
470 * Return the name of the file containing the Dartium executable. | |
471 */ | |
472 String get dartiumBinaryName { | |
473 if (OSUtilities.isWindows()) { | |
474 return _DARTIUM_EXECUTABLE_NAME_WIN; | |
475 } else if (OSUtilities.isMac()) { | |
476 return _DARTIUM_EXECUTABLE_NAME_MAC; | |
477 } else { | |
478 return _DARTIUM_EXECUTABLE_NAME_LINUX; | |
479 } | |
480 } | |
481 | |
482 /** | |
483 * Return the file containing the Dartium executable, or `null` if it does not | |
484 * exist. | |
485 */ | |
486 JavaFile get dartiumExecutable { | |
487 if (_dartiumExecutable == null) { | |
488 _dartiumExecutable = _verifyExecutable( | |
489 new JavaFile.relative(dartiumWorkingDirectory, dartiumBinaryName)); | |
490 } | |
491 return _dartiumExecutable; | |
492 } | |
493 | |
494 /** | |
495 * Return the directory where dartium can be found (the directory that will be | |
496 * the working directory is Dartium is invoked without changing the default). | |
497 */ | |
498 JavaFile get dartiumWorkingDirectory => | |
499 getDartiumWorkingDirectory(_sdkDirectory.getParentFile()); | |
500 | |
501 /** | |
502 * Return the directory containing the SDK. | 444 * Return the directory containing the SDK. |
503 */ | 445 */ |
504 JavaFile get directory => _sdkDirectory; | 446 Folder get directory => _sdkDirectory; |
505 | 447 |
506 /** | 448 /** |
507 * Return the directory containing documentation for the SDK. | 449 * Return the directory containing documentation for the SDK. |
508 */ | 450 */ |
509 JavaFile get docDirectory => | 451 Folder get docDirectory => |
510 new JavaFile.relative(_sdkDirectory, _DOCS_DIRECTORY_NAME); | 452 _sdkDirectory.getChildAssumingFolder(_DOCS_DIRECTORY_NAME); |
511 | |
512 /** | |
513 * Return `true` if this SDK includes documentation. | |
514 */ | |
515 bool get hasDocumentation => docDirectory.exists(); | |
516 | |
517 /** | |
518 * Return `true` if the Dartium binary is available. | |
519 */ | |
520 bool get isDartiumInstalled => dartiumExecutable != null; | |
521 | 453 |
522 /** | 454 /** |
523 * Return the directory within the SDK directory that contains the libraries. | 455 * Return the directory within the SDK directory that contains the libraries. |
524 */ | 456 */ |
525 JavaFile get libraryDirectory { | 457 Folder get libraryDirectory { |
526 if (_libraryDirectory == null) { | 458 if (_libraryDirectory == null) { |
527 _libraryDirectory = | 459 _libraryDirectory = |
528 new JavaFile.relative(_sdkDirectory, _LIB_DIRECTORY_NAME); | 460 _sdkDirectory.getChildAssumingFolder(_LIB_DIRECTORY_NAME); |
529 } | 461 } |
530 return _libraryDirectory; | 462 return _libraryDirectory; |
531 } | 463 } |
532 | 464 |
533 /** | 465 /** |
534 * Return the file containing the Pub executable, or `null` if it does not exi
st. | 466 * Return the file containing the Pub executable, or `null` if it does not exi
st. |
535 */ | 467 */ |
536 JavaFile get pubExecutable { | 468 File get pubExecutable { |
537 if (_pubExecutable == null) { | 469 if (_pubExecutable == null) { |
538 _pubExecutable = _verifyExecutable(new JavaFile.relative( | 470 _pubExecutable = _sdkDirectory |
539 new JavaFile.relative(_sdkDirectory, _BIN_DIRECTORY_NAME), | 471 .getChildAssumingFolder(_BIN_DIRECTORY_NAME) |
540 OSUtilities.isWindows() | 472 .getChildAssumingFile(OSUtilities.isWindows() |
541 ? _PUB_EXECUTABLE_NAME_WIN | 473 ? _PUB_EXECUTABLE_NAME_WIN |
542 : _PUB_EXECUTABLE_NAME)); | 474 : _PUB_EXECUTABLE_NAME); |
543 } | 475 } |
544 return _pubExecutable; | 476 return _pubExecutable; |
545 } | 477 } |
546 | 478 |
547 /** | 479 /** |
548 * Return the revision number of this SDK, or `"0"` if the revision number | 480 * Return the revision number of this SDK, or `"0"` if the revision number |
549 * cannot be discovered. | 481 * cannot be discovered. |
550 */ | 482 */ |
551 @override | 483 @override |
552 String get sdkVersion { | 484 String get sdkVersion { |
553 if (_sdkVersion == null) { | 485 if (_sdkVersion == null) { |
554 _sdkVersion = DartSdk.DEFAULT_VERSION; | 486 _sdkVersion = DartSdk.DEFAULT_VERSION; |
555 JavaFile revisionFile = | 487 File revisionFile = |
556 new JavaFile.relative(_sdkDirectory, _VERSION_FILE_NAME); | 488 _sdkDirectory.getChildAssumingFile(_VERSION_FILE_NAME); |
557 try { | 489 try { |
558 String revision = revisionFile.readAsStringSync(); | 490 String revision = revisionFile.readAsStringSync(); |
559 if (revision != null) { | 491 if (revision != null) { |
560 _sdkVersion = revision.trim(); | 492 _sdkVersion = revision.trim(); |
561 } | 493 } |
562 } on FileSystemException { | 494 } on FileSystemException { |
563 // Fall through to return the default. | 495 // Fall through to return the default. |
564 } | 496 } |
565 } | 497 } |
566 return _sdkVersion; | 498 return _sdkVersion; |
567 } | 499 } |
568 | 500 |
569 /** | 501 /** |
570 * Return the name of the file containing the VM executable. | |
571 */ | |
572 String get vmBinaryName { | |
573 if (OSUtilities.isWindows()) { | |
574 return _VM_EXECUTABLE_NAME_WIN; | |
575 } else { | |
576 return _VM_EXECUTABLE_NAME; | |
577 } | |
578 } | |
579 | |
580 /** | |
581 * Return the file containing the VM executable, or `null` if it does not | |
582 * exist. | |
583 */ | |
584 JavaFile get vmExecutable { | |
585 if (_vmExecutable == null) { | |
586 _vmExecutable = _verifyExecutable(new JavaFile.relative( | |
587 new JavaFile.relative(_sdkDirectory, _BIN_DIRECTORY_NAME), | |
588 vmBinaryName)); | |
589 } | |
590 return _vmExecutable; | |
591 } | |
592 | |
593 /** | |
594 * Determine the search order for trying to locate the [_LIBRARIES_FILE]. | 502 * Determine the search order for trying to locate the [_LIBRARIES_FILE]. |
595 */ | 503 */ |
596 Iterable<JavaFile> get _libraryMapLocations sync* { | 504 Iterable<File> get _libraryMapLocations sync* { |
597 yield new JavaFile.relative( | 505 yield libraryDirectory |
598 new JavaFile.relative( | 506 .getChildAssumingFolder(_INTERNAL_DIR) |
599 new JavaFile.relative( | 507 .getChildAssumingFolder(_SDK_LIBRARY_METADATA_DIR) |
600 new JavaFile.relative(libraryDirectory, _INTERNAL_DIR), | 508 .getChildAssumingFolder(_SDK_LIBRARY_METADATA_LIB_DIR) |
601 _SDK_LIBRARY_METADATA_DIR), | 509 .getChildAssumingFile(_LIBRARIES_FILE); |
602 _SDK_LIBRARY_METADATA_LIB_DIR), | 510 yield libraryDirectory |
603 _LIBRARIES_FILE); | 511 .getChildAssumingFolder(_INTERNAL_DIR) |
604 yield new JavaFile.relative( | 512 .getChildAssumingFile(_LIBRARIES_FILE); |
605 new JavaFile.relative(libraryDirectory, _INTERNAL_DIR), | |
606 _LIBRARIES_FILE); | |
607 } | |
608 | |
609 /** | |
610 * Return the directory where dartium can be found (the directory that will be | |
611 * the working directory if Dartium is invoked without changing the default), | |
612 * assuming that the Editor was installed in the [installDir]. | |
613 */ | |
614 JavaFile getDartiumWorkingDirectory(JavaFile installDir) => | |
615 new JavaFile.relative(installDir, _DARTIUM_DIRECTORY_NAME); | |
616 | |
617 /** | |
618 * Return the auxiliary documentation file for the library with the given | |
619 * [libraryName], or `null` if no such file exists. | |
620 */ | |
621 JavaFile getDocFileFor(String libraryName) { | |
622 JavaFile dir = docDirectory; | |
623 if (!dir.exists()) { | |
624 return null; | |
625 } | |
626 JavaFile libDir = new JavaFile.relative(dir, libraryName); | |
627 JavaFile docFile = | |
628 new JavaFile.relative(libDir, "$libraryName$_DOC_FILE_SUFFIX"); | |
629 if (docFile.exists()) { | |
630 return docFile; | |
631 } | |
632 return null; | |
633 } | 513 } |
634 | 514 |
635 @override | 515 @override |
636 String getRelativePathFromFile(JavaFile file) { | 516 String getRelativePathFromFile(File file) { |
637 String filePath = file.getAbsolutePath(); | 517 String filePath = file.path; |
638 String libPath = libraryDirectory.getAbsolutePath(); | 518 String libPath = libraryDirectory.path; |
639 if (!filePath.startsWith("$libPath${JavaFile.separator}")) { | 519 if (!filePath.startsWith("$libPath${resourceProvider.pathContext.separator}"
)) { |
640 return null; | 520 return null; |
641 } | 521 } |
642 return filePath.substring(libPath.length + 1); | 522 return filePath.substring(libPath.length + 1); |
643 } | 523 } |
644 | 524 |
645 /** | 525 /** |
646 * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise. | 526 * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise. |
647 * This method should not be used outside of `analyzer` and `analyzer_cli` | 527 * This method should not be used outside of `analyzer` and `analyzer_cli` |
648 * packages. | 528 * packages. |
649 */ | 529 */ |
650 PackageBundle getSummarySdkBundle(bool strongMode) { | 530 PackageBundle getSummarySdkBundle(bool strongMode) { |
651 String rootPath = directory.getAbsolutePath(); | 531 String rootPath = directory.path; |
652 String name = strongMode ? 'strong.sum' : 'spec.sum'; | 532 String name = strongMode ? 'strong.sum' : 'spec.sum'; |
653 String path = pathos.join(rootPath, 'lib', '_internal', name); | 533 String path = resourceProvider.pathContext.join(rootPath, 'lib', '_internal'
, name); |
654 try { | 534 try { |
655 File file = new File(path); | 535 File file = resourceProvider.getFile(path); |
656 if (file.existsSync()) { | 536 if (file.exists) { |
657 List<int> bytes = file.readAsBytesSync(); | 537 List<int> bytes = file.readAsBytesSync(); |
658 return new PackageBundle.fromBuffer(bytes); | 538 return new PackageBundle.fromBuffer(bytes); |
659 } | 539 } |
660 } catch (exception, stackTrace) { | 540 } catch (exception, stackTrace) { |
661 AnalysisEngine.instance.logger.logError( | 541 AnalysisEngine.instance.logger.logError( |
662 'Failed to load SDK analysis summary from $path', | 542 'Failed to load SDK analysis summary from $path', |
663 new CaughtException(exception, stackTrace)); | 543 new CaughtException(exception, stackTrace)); |
664 } | 544 } |
665 return null; | 545 return null; |
666 } | 546 } |
667 | 547 |
668 /** | 548 /** |
669 * Read all of the configuration files to initialize the library maps. The | 549 * Read all of the configuration files to initialize the library maps. The |
670 * flag [useDart2jsPaths] is `true` if the dart2js path should be used when it | 550 * flag [useDart2jsPaths] is `true` if the dart2js path should be used when it |
671 * is available. Return the initialized library map. | 551 * is available. Return the initialized library map. |
672 */ | 552 */ |
673 LibraryMap initialLibraryMap(bool useDart2jsPaths) { | 553 LibraryMap initialLibraryMap(bool useDart2jsPaths) { |
674 List<String> searchedPaths = <String>[]; | 554 List<String> searchedPaths = <String>[]; |
675 var lastStackTrace = null; | 555 var lastStackTrace = null; |
676 var lastException = null; | 556 var lastException = null; |
677 for (JavaFile librariesFile in _libraryMapLocations) { | 557 for (File librariesFile in _libraryMapLocations) { |
678 try { | 558 try { |
679 String contents = librariesFile.readAsStringSync(); | 559 String contents = librariesFile.readAsStringSync(); |
680 return new SdkLibrariesReader(useDart2jsPaths) | 560 return new SdkLibrariesReader(useDart2jsPaths) |
681 .readFromFile(librariesFile, contents); | 561 .readFromFile(librariesFile, contents); |
682 } catch (exception, stackTrace) { | 562 } catch (exception, stackTrace) { |
683 searchedPaths.add(librariesFile.getAbsolutePath()); | 563 searchedPaths.add(librariesFile.path); |
684 lastException = exception; | 564 lastException = exception; |
685 lastStackTrace = stackTrace; | 565 lastStackTrace = stackTrace; |
686 } | 566 } |
687 } | 567 } |
688 AnalysisEngine.instance.logger.logError( | 568 AnalysisEngine.instance.logger.logError( |
689 "Could not initialize the library map from $searchedPaths", | 569 "Could not initialize the library map from $searchedPaths", |
690 new CaughtException(lastException, lastStackTrace)); | 570 new CaughtException(lastException, lastStackTrace)); |
691 return new LibraryMap(); | 571 return new LibraryMap(); |
692 } | 572 } |
693 | 573 |
694 @override | 574 @override |
695 FileBasedSource internalMapDartUri(String dartUri) { | 575 Source internalMapDartUri(String dartUri) { |
696 String libraryName; | 576 String libraryName; |
697 String relativePath; | 577 String relativePath; |
698 int index = dartUri.indexOf('/'); | 578 int index = dartUri.indexOf('/'); |
699 if (index >= 0) { | 579 if (index >= 0) { |
700 libraryName = dartUri.substring(0, index); | 580 libraryName = dartUri.substring(0, index); |
701 relativePath = dartUri.substring(index + 1); | 581 relativePath = dartUri.substring(index + 1); |
702 } else { | 582 } else { |
703 libraryName = dartUri; | 583 libraryName = dartUri; |
704 relativePath = ""; | 584 relativePath = ""; |
705 } | 585 } |
706 SdkLibrary library = getSdkLibrary(libraryName); | 586 SdkLibrary library = getSdkLibrary(libraryName); |
707 if (library == null) { | 587 if (library == null) { |
708 return null; | 588 return null; |
709 } | 589 } |
710 try { | 590 try { |
711 JavaFile file = new JavaFile.relative(libraryDirectory, library.path); | 591 File file = libraryDirectory.getChildAssumingFile(library.path); |
712 if (!relativePath.isEmpty) { | 592 if (!relativePath.isEmpty) { |
713 file = file.getParentFile(); | 593 file = file.parent.getChildAssumingFile(relativePath); |
714 file = new JavaFile.relative(file, relativePath); | |
715 } | 594 } |
716 return new FileBasedSource(file, parseUriWithException(dartUri)); | 595 return file.createSource(parseUriWithException(dartUri)); |
717 } on URISyntaxException { | 596 } on URISyntaxException { |
718 return null; | 597 return null; |
719 } | 598 } |
720 } | 599 } |
721 | 600 |
722 /** | 601 /** |
723 * Return the given [file] if it exists and is executable, or `null` if it | 602 * Return the default directory for the Dart SDK, or `null` if the directory |
724 * does not exist or is not executable. | 603 * cannot be determined (or does not exist). The default directory is provided |
| 604 * by a system property named `com.google.dart.sdk`. |
725 */ | 605 */ |
726 JavaFile _verifyExecutable(JavaFile file) => | 606 static Folder defaultSdkDirectory(ResourceProvider resourceProvider) { |
727 file.isExecutable() ? file : null; | 607 // TODO(brianwilkerson) This is currently only being used in the analysis |
| 608 // server's Driver class to find the default SDK. The command-line analyzer |
| 609 // uses cli_utils to find the SDK. Not sure why they're different. |
| 610 String sdkProperty = getSdkProperty(resourceProvider); |
| 611 if (sdkProperty == null) { |
| 612 return null; |
| 613 } |
| 614 Folder sdkDirectory = resourceProvider.getFolder(sdkProperty); |
| 615 if (!sdkDirectory.exists) { |
| 616 return null; |
| 617 } |
| 618 return sdkDirectory; |
| 619 } |
| 620 |
| 621 static String getSdkProperty(ResourceProvider resourceProvider) { |
| 622 String exec = io.Platform.executable; |
| 623 if (exec.length == 0) { |
| 624 return null; |
| 625 } |
| 626 pathos.Context pathContext = resourceProvider.pathContext; |
| 627 // Might be "xcodebuild/ReleaseIA32/dart" with "sdk" sibling |
| 628 String outDir = pathContext.dirname(pathContext.dirname(exec)); |
| 629 String sdkPath = pathContext.join(pathContext.dirname(outDir), "sdk"); |
| 630 if (resourceProvider.getFolder(sdkPath).exists) { |
| 631 return sdkPath; |
| 632 } |
| 633 // probably be "dart-sdk/bin/dart" |
| 634 return pathContext.dirname(pathContext.dirname(exec)); |
| 635 } |
728 } | 636 } |
729 | 637 |
730 /** | 638 /** |
731 * An object used to read and parse the libraries file | 639 * An object used to read and parse the libraries file |
732 * (dart-sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart) for informat
ion | 640 * (dart-sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart) for informat
ion |
733 * about the libraries in an SDK. The library information is represented as a | 641 * about the libraries in an SDK. The library information is represented as a |
734 * Dart file containing a single top-level variable whose value is a const map. | 642 * Dart file containing a single top-level variable whose value is a const map. |
735 * The keys of the map are the names of libraries defined in the SDK and the | 643 * The keys of the map are the names of libraries defined in the SDK and the |
736 * values in the map are info objects defining the library. For example, a | 644 * values in the map are info objects defining the library. For example, a |
737 * subset of a typical SDK might have a libraries file that looks like the | 645 * subset of a typical SDK might have a libraries file that looks like the |
(...skipping 22 matching lines...) Expand all Loading... |
760 /** | 668 /** |
761 * Initialize a newly created library reader to use the dart2js path if | 669 * Initialize a newly created library reader to use the dart2js path if |
762 * [_useDart2jsPaths] is `true`. | 670 * [_useDart2jsPaths] is `true`. |
763 */ | 671 */ |
764 SdkLibrariesReader(this._useDart2jsPaths); | 672 SdkLibrariesReader(this._useDart2jsPaths); |
765 | 673 |
766 /** | 674 /** |
767 * Return the library map read from the given [file], given that the content | 675 * Return the library map read from the given [file], given that the content |
768 * of the file is already known to be [libraryFileContents]. | 676 * of the file is already known to be [libraryFileContents]. |
769 */ | 677 */ |
770 LibraryMap readFromFile(JavaFile file, String libraryFileContents) => | 678 LibraryMap readFromFile(File file, String libraryFileContents) => |
771 readFromSource(new FileBasedSource(file), libraryFileContents); | 679 readFromSource(file.createSource(), libraryFileContents); |
772 | 680 |
773 /** | 681 /** |
774 * Return the library map read from the given [source], given that the content | 682 * Return the library map read from the given [source], given that the content |
775 * of the file is already known to be [libraryFileContents]. | 683 * of the file is already known to be [libraryFileContents]. |
776 */ | 684 */ |
777 LibraryMap readFromSource(Source source, String libraryFileContents) { | 685 LibraryMap readFromSource(Source source, String libraryFileContents) { |
778 BooleanErrorListener errorListener = new BooleanErrorListener(); | 686 BooleanErrorListener errorListener = new BooleanErrorListener(); |
779 Scanner scanner = new Scanner( | 687 Scanner scanner = new Scanner( |
780 source, new CharSequenceReader(libraryFileContents), errorListener); | 688 source, new CharSequenceReader(libraryFileContents), errorListener); |
781 Parser parser = new Parser(source, errorListener); | 689 Parser parser = new Parser(source, errorListener); |
782 CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize()); | 690 CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize()); |
783 SdkLibrariesReader_LibraryBuilder libraryBuilder = | 691 SdkLibrariesReader_LibraryBuilder libraryBuilder = |
784 new SdkLibrariesReader_LibraryBuilder(_useDart2jsPaths); | 692 new SdkLibrariesReader_LibraryBuilder(_useDart2jsPaths); |
785 // If any syntactic errors were found then don't try to visit the AST | 693 // If any syntactic errors were found then don't try to visit the AST |
786 // structure. | 694 // structure. |
787 if (!errorListener.errorReported) { | 695 if (!errorListener.errorReported) { |
788 unit.accept(libraryBuilder); | 696 unit.accept(libraryBuilder); |
789 } | 697 } |
790 return libraryBuilder.librariesMap; | 698 return libraryBuilder.librariesMap; |
791 } | 699 } |
792 } | 700 } |
OLD | NEW |