| 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/context/declared_variables.dart'; |
| 6 import 'package:analyzer/dart/ast/ast.dart'; |
| 7 import 'package:analyzer/dart/element/element.dart' show CompilationUnitElement; |
| 8 import 'package:analyzer/error/error.dart'; |
| 9 import 'package:analyzer/src/context/context.dart'; |
| 10 import 'package:analyzer/src/dart/analysis/byte_store.dart'; |
| 11 import 'package:analyzer/src/dart/analysis/driver.dart'; |
| 12 import 'package:analyzer/src/dart/analysis/file_state.dart'; |
| 13 import 'package:analyzer/src/generated/engine.dart' |
| 14 show AnalysisContext, AnalysisEngine, AnalysisOptions; |
| 15 import 'package:analyzer/src/generated/source.dart'; |
| 16 import 'package:analyzer/src/summary/format.dart'; |
| 17 import 'package:analyzer/src/summary/idl.dart'; |
| 18 import 'package:analyzer/src/summary/link.dart'; |
| 19 import 'package:analyzer/src/summary/package_bundle_reader.dart'; |
| 20 import 'package:analyzer/src/task/dart.dart' show COMPILATION_UNIT_ELEMENT; |
| 21 import 'package:analyzer/task/dart.dart' show LibrarySpecificUnit; |
| 22 |
| 23 /** |
| 24 * Context information necessary to analyze one or more libraries within an |
| 25 * [AnalysisDriver]. |
| 26 * |
| 27 * Currently this is implemented as a wrapper around [AnalysisContext]. |
| 28 * TODO(paulberry): make a front end API that this can make use of instead. |
| 29 */ |
| 30 class LibraryContext { |
| 31 /** |
| 32 * The [AnalysisContext] which is used to do the analysis. |
| 33 */ |
| 34 final AnalysisContext _analysisContext; |
| 35 |
| 36 /** |
| 37 * Create a [LibraryContext] which is prepared to analyze [library]. |
| 38 */ |
| 39 factory LibraryContext.forSingleLibrary( |
| 40 FileState library, |
| 41 PerformanceLog logger, |
| 42 PackageBundle sdkBundle, |
| 43 ByteStore byteStore, |
| 44 AnalysisOptions options, |
| 45 DeclaredVariables declaredVariables, |
| 46 SourceFactory sourceFactory, |
| 47 FileSystemState fsState) { |
| 48 return logger.run('Create library context', () { |
| 49 Map<String, FileState> libraries = <String, FileState>{}; |
| 50 SummaryDataStore store = new SummaryDataStore(const <String>[]); |
| 51 |
| 52 if (sdkBundle != null) { |
| 53 store.addBundle(null, sdkBundle); |
| 54 } |
| 55 |
| 56 void appendLibraryFiles(FileState library) { |
| 57 if (!libraries.containsKey(library.uriStr)) { |
| 58 // Serve 'dart:' URIs from the SDK bundle. |
| 59 if (sdkBundle != null && library.uri.scheme == 'dart') { |
| 60 return; |
| 61 } |
| 62 |
| 63 libraries[library.uriStr] = library; |
| 64 |
| 65 // Append the defining unit. |
| 66 store.addUnlinkedUnit(library.uriStr, library.unlinked); |
| 67 |
| 68 // Append parts. |
| 69 for (FileState part in library.partedFiles) { |
| 70 store.addUnlinkedUnit(part.uriStr, part.unlinked); |
| 71 } |
| 72 |
| 73 // Append referenced libraries. |
| 74 library.importedFiles.forEach(appendLibraryFiles); |
| 75 library.exportedFiles.forEach(appendLibraryFiles); |
| 76 } |
| 77 } |
| 78 |
| 79 logger.run('Append library files', () { |
| 80 return appendLibraryFiles(library); |
| 81 }); |
| 82 |
| 83 Set<String> libraryUrisToLink = new Set<String>(); |
| 84 logger.run('Load linked bundles', () { |
| 85 for (FileState library in libraries.values) { |
| 86 if (library.exists) { |
| 87 String key = '${library.transitiveSignature}.linked'; |
| 88 List<int> bytes = byteStore.get(key); |
| 89 if (bytes != null) { |
| 90 LinkedLibrary linked = new LinkedLibrary.fromBuffer(bytes); |
| 91 store.addLinkedLibrary(library.uriStr, linked); |
| 92 } else { |
| 93 libraryUrisToLink.add(library.uriStr); |
| 94 } |
| 95 } |
| 96 } |
| 97 int numOfLoaded = libraries.length - libraryUrisToLink.length; |
| 98 logger.writeln('Loaded $numOfLoaded linked bundles.'); |
| 99 }); |
| 100 |
| 101 Map<String, LinkedLibraryBuilder> linkedLibraries = {}; |
| 102 logger.run('Link bundles', () { |
| 103 linkedLibraries = link(libraryUrisToLink, (String uri) { |
| 104 LinkedLibrary linkedLibrary = store.linkedMap[uri]; |
| 105 return linkedLibrary; |
| 106 }, (String uri) { |
| 107 UnlinkedUnit unlinkedUnit = store.unlinkedMap[uri]; |
| 108 return unlinkedUnit; |
| 109 }, (_) => null, options.strongMode); |
| 110 logger.writeln('Linked ${linkedLibraries.length} bundles.'); |
| 111 }); |
| 112 |
| 113 linkedLibraries.forEach((uri, linkedBuilder) { |
| 114 FileState library = libraries[uri]; |
| 115 String key = '${library.transitiveSignature}.linked'; |
| 116 List<int> bytes = linkedBuilder.toBuffer(); |
| 117 LinkedLibrary linked = new LinkedLibrary.fromBuffer(bytes); |
| 118 store.addLinkedLibrary(uri, linked); |
| 119 byteStore.put(key, bytes); |
| 120 }); |
| 121 |
| 122 var analysisContext = _createAnalysisContext( |
| 123 options, declaredVariables, sourceFactory, fsState, store); |
| 124 |
| 125 return new LibraryContext._(analysisContext); |
| 126 }); |
| 127 } |
| 128 |
| 129 LibraryContext._(this._analysisContext); |
| 130 |
| 131 /** |
| 132 * Computes a [CompilationUnitElement] for the given library/unit pair. |
| 133 */ |
| 134 CompilationUnitElement computeUnitElement( |
| 135 Source librarySource, Source unitSource) { |
| 136 return _analysisContext.computeResult( |
| 137 new LibrarySpecificUnit(librarySource, unitSource), |
| 138 COMPILATION_UNIT_ELEMENT); |
| 139 } |
| 140 |
| 141 /** |
| 142 * Cleans up any persistent resources used by this [LibraryContext]. |
| 143 * |
| 144 * Should be called once the [LibraryContext] is no longer needed. |
| 145 */ |
| 146 void dispose() { |
| 147 _analysisContext.dispose(); |
| 148 } |
| 149 |
| 150 /** |
| 151 * Computes a resolved [CompilationUnit] and a list of [AnalysisError]s for |
| 152 * the given library/unit pair. |
| 153 */ |
| 154 ResolutionResult resolveUnit(Source librarySource, Source unitSource) { |
| 155 CompilationUnit resolvedUnit = |
| 156 _analysisContext.resolveCompilationUnit2(unitSource, librarySource); |
| 157 List<AnalysisError> errors = _analysisContext.computeErrors(unitSource); |
| 158 return new ResolutionResult(resolvedUnit, errors); |
| 159 } |
| 160 |
| 161 static AnalysisContext _createAnalysisContext( |
| 162 AnalysisOptions _analysisOptions, |
| 163 DeclaredVariables declaredVariables, |
| 164 SourceFactory _sourceFactory, |
| 165 FileSystemState _fsState, |
| 166 SummaryDataStore store) { |
| 167 AnalysisContextImpl analysisContext = |
| 168 AnalysisEngine.instance.createAnalysisContext(); |
| 169 analysisContext.useSdkCachePartition = false; |
| 170 analysisContext.analysisOptions = _analysisOptions; |
| 171 analysisContext.declaredVariables.addAll(declaredVariables); |
| 172 analysisContext.sourceFactory = _sourceFactory.clone(); |
| 173 analysisContext.contentCache = new _ContentCacheWrapper(_fsState); |
| 174 analysisContext.resultProvider = |
| 175 new InputPackagesResultProvider(analysisContext, store); |
| 176 return analysisContext; |
| 177 } |
| 178 } |
| 179 |
| 180 /** |
| 181 * Container object holding the result of a call to |
| 182 * [LibraryContext.resolveUnit]. |
| 183 */ |
| 184 class ResolutionResult { |
| 185 final CompilationUnit resolvedUnit; |
| 186 final List<AnalysisError> errors; |
| 187 |
| 188 ResolutionResult(this.resolvedUnit, this.errors); |
| 189 } |
| 190 |
| 191 /** |
| 192 * [ContentCache] wrapper around [FileContentOverlay]. |
| 193 */ |
| 194 class _ContentCacheWrapper implements ContentCache { |
| 195 final FileSystemState fsState; |
| 196 |
| 197 _ContentCacheWrapper(this.fsState); |
| 198 |
| 199 @override |
| 200 void accept(ContentCacheVisitor visitor) { |
| 201 throw new UnimplementedError(); |
| 202 } |
| 203 |
| 204 @override |
| 205 String getContents(Source source) { |
| 206 return _getFileForSource(source).content; |
| 207 } |
| 208 |
| 209 @override |
| 210 bool getExists(Source source) { |
| 211 if (source.isInSystemLibrary) { |
| 212 return true; |
| 213 } |
| 214 return _getFileForSource(source).exists; |
| 215 } |
| 216 |
| 217 @override |
| 218 int getModificationStamp(Source source) { |
| 219 if (source.isInSystemLibrary) { |
| 220 return 0; |
| 221 } |
| 222 return _getFileForSource(source).exists ? 0 : -1; |
| 223 } |
| 224 |
| 225 @override |
| 226 String setContents(Source source, String contents) { |
| 227 throw new UnimplementedError(); |
| 228 } |
| 229 |
| 230 FileState _getFileForSource(Source source) { |
| 231 String path = source.fullName; |
| 232 return fsState.getFileForPath(path); |
| 233 } |
| 234 } |
| OLD | NEW |