Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: pkg/analyzer/lib/src/summary/bazel_summary.dart

Issue 2379563004: Clean up Bazel provider, still only unlinked. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analyzer/test/src/summary/bazel_summary_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, 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 import 'dart:convert'; 5 import 'dart:convert';
6 6
7 import 'package:analyzer/file_system/file_system.dart'; 7 import 'package:analyzer/file_system/file_system.dart';
8 import 'package:analyzer/src/generated/engine.dart'; 8 import 'package:analyzer/src/generated/engine.dart';
9 import 'package:analyzer/src/generated/source.dart'; 9 import 'package:analyzer/src/generated/source.dart';
10 import 'package:analyzer/src/generated/utilities_collection.dart'; 10 import 'package:analyzer/src/generated/utilities_collection.dart';
11 import 'package:analyzer/src/summary/idl.dart'; 11 import 'package:analyzer/src/summary/idl.dart';
12 import 'package:convert/convert.dart'; 12 import 'package:convert/convert.dart';
13 import 'package:crypto/crypto.dart'; 13 import 'package:crypto/crypto.dart';
14 import 'package:meta/meta.dart'; 14 import 'package:meta/meta.dart';
15 15
16 /** 16 /**
17 * Return the path of the directory where bundles for the given [uri] should be 17 * Return the [Folder] where bundles for the given [absoluteUri] should be
18 * looked for. This directory should contain corresponding pairs of `*.api.ds` 18 * looked for. This folder should contain corresponding `*.full.ds` files,
19 * and `*.full.ds` files, possibly more than one pair. Return `null` if the 19 * possibly more than one one. Return `null` if the given [absoluteUri]
20 * given [uri] does not have the expected structure, so the output path cannot 20 * does not have the expected structure, so the output path cannot be computed.
21 * be computed.
22 */ 21 */
23 typedef String GetOutputPath(ResourceProvider provider, Uri uri); 22 typedef Folder GetOutputFolder(Uri absoluteUri);
24 23
25 /** 24 /**
26 * Information about a Dart package in Bazel. 25 * Information about a Dart package in Bazel.
27 */ 26 */
28 class Package { 27 class Package {
29 final String bundlePath; 28 final File unlinkedFile;
30 final PackageBundle bundle; 29 final PackageBundle unlinked;
31 final Set<String> _unitUris = new Set<String>(); 30 final Set<String> _unitUris = new Set<String>();
32 31
33 Package(this.bundlePath, this.bundle) { 32 Package(this.unlinkedFile, this.unlinked) {
34 _unitUris.addAll(bundle.unlinkedUnitUris); 33 _unitUris.addAll(unlinked.unlinkedUnitUris);
35 } 34 }
36 } 35 }
37 36
38 /** 37 /**
39 * Class that reads summaries of Bazel packages. 38 * Class that reads summaries of Bazel packages.
40 * 39 *
41 * When the client needs to produce a resolution result for a new [Source], it 40 * When the client needs to produce a resolution result for a new [Source], it
42 * should call [getPackages] to checked whether there is the set of packages 41 * should call [getLinkedPackages] to check whether there is the set of
43 * to resynthesize resolution results. 42 * packages to resynthesize resolution results.
44 */ 43 */
45 class SummaryProvider { 44 class SummaryProvider {
46 final ResourceProvider provider; 45 final ResourceProvider provider;
47 final GetOutputPath getOutputPath; 46 final GetOutputFolder getOutputFolder;
48 final AnalysisContext context; 47 final AnalysisContext context;
49 48
50 /** 49 /**
51 * Mapping from bundle paths to corresponding [Package]s. The packages in 50 * Mapping from bundle paths to corresponding [Package]s. The packages in
52 * the map were consistent with their constituent sources at the moment when 51 * the map were consistent with their constituent sources at the moment when
53 * they were put into the map. 52 * they were put into the map.
54 */ 53 */
55 final Map<String, Package> bundlePathToPackageMap = <String, Package>{}; 54 final Map<Folder, List<Package>> folderToPackagesMap = {};
56 55
57 /** 56 SummaryProvider(this.provider, this.getOutputFolder, this.context);
58 * When we detected than some bundle is not consistent with its constituent
59 * sources (i.e. even its unlinked state is not consistent), we remember
60 * this fact to avoid loading and checking consistency next time.
61 */
62 final Set<String> knownInconsistentBundlePaths = new Set<String>();
63
64 SummaryProvider(this.provider, this.getOutputPath, this.context);
65
66 /**
67 * Return the [Package] that contains information about the source with
68 * the given [uri], or `null` if such package does not exist.
69 */
70 @visibleForTesting
71 Package getPackageForUri(Uri uri) {
72 String outputPath = getOutputPath(provider, uri);
73 if (outputPath != null) {
74 List<Package> packages = _getPackages(outputPath);
75 for (Package package in packages) {
76 String uriStr = uri.toString();
77 if (package._unitUris.contains(uriStr)) {
78 return package;
79 }
80 }
81 }
82 return null;
83 }
84 57
85 /** 58 /**
86 * Return the complete list of [Package]s that are required to provide all 59 * Return the complete list of [Package]s that are required to provide all
87 * resolution results for the given [source]. 60 * resolution results for the given [source].
88 * 61 *
89 * The same list of packages is returned for the same [Source], i.e. always 62 * The same list of packages is returned for the same [Source], i.e. always
90 * the full list, not a difference with a previous request. It is up to the 63 * the full list, not a difference with a previous request. It is up to the
91 * client to decide whether some of the returned packages should be excluded 64 * client to decide whether some of the returned packages should be excluded
92 * as already mixed into a resynthesizer. 65 * as already mixed into a resynthesizer.
93 * 66 *
94 * If the full set of packages cannot be produced, for example because some 67 * If the full set of packages cannot be produced, for example because some
95 * bundles are not built, or out of date, etc, then `null` is returned. 68 * bundles are not built, or out of date, etc, then `null` is returned.
96 */ 69 */
97 List<PackageBundle> getPackages(Source source) { 70 List<Package> getLinkedPackages(Source source) {
98 // TODO(scheglov) implement 71 // TODO(scheglov) implement
99 return null; 72 return null;
100 } 73 }
101 74
102 /** 75 /**
103 * Return the hexadecimal string for the given [source] contents. 76 * Return the [Package] that contains information about the source with
77 * the given [uri], or `null` if such package does not exist.
78 */
79 @visibleForTesting
80 Package getUnlinkedForUri(Uri uri) {
81 Folder outputFolder = getOutputFolder(uri);
82 if (outputFolder != null) {
83 String uriStr = uri.toString();
84 List<Package> packages = _getUnlinkedPackages(outputFolder);
85 for (Package package in packages) {
86 if (package._unitUris.contains(uriStr)) {
87 return package;
88 }
89 }
90 }
91 return null;
92 }
93
94 /**
95 * Return the hexadecimal string of the MD5 hash of the contents of the
96 * given [source] in [context].
104 */ 97 */
105 String _computeSourceHashHex(Source source) { 98 String _computeSourceHashHex(Source source) {
106 String text = context.getContents(source).data; 99 String text = context.getContents(source).data;
107 List<int> bytes = UTF8.encode(text); 100 List<int> bytes = UTF8.encode(text);
108 List<int> hashBytes = md5.convert(bytes).bytes; 101 List<int> hashBytes = md5.convert(bytes).bytes;
109 return hex.encode(hashBytes); 102 return hex.encode(hashBytes);
110 } 103 }
111 104
112 /** 105 /**
113 * Return the [Package] from the file with the given [path], or `null` if the 106 * Return all consistent unlinked [Package]s in the given [folder]. Some of
114 * file does not exist, or it cannot be read, or is not consistent with the 107 * the returned packages might be already linked.
115 * sources it contains, etc.
116 */ 108 */
117 Package _getPackage(String path) { 109 List<Package> _getUnlinkedPackages(Folder folder) {
118 // Check if the bundle know to be inconsistent, missing, etc. 110 List<Package> packages = folderToPackagesMap[folder];
119 if (knownInconsistentBundlePaths.contains(path)) { 111 if (packages == null) {
120 return null; 112 packages = <Package>[];
121 } 113 try {
122 // Attempt to get from the cache or read from the file system. 114 List<Resource> children = folder.getChildren();
123 try { 115 for (Resource child in children) {
124 Package package = bundlePathToPackageMap[path]; 116 if (child is File) {
125 if (package == null) { 117 String packagePath = child.path;
126 File file = provider.getFile(path); 118 if (packagePath.toLowerCase().endsWith('.full.ds')) {
127 List<int> bytes = file.readAsBytesSync(); 119 Package package = _readUnlinkedPackage(child);
128 PackageBundle bundle = new PackageBundle.fromBuffer(bytes); 120 if (package != null) {
129 // Check for consistency, and fail if it's not. 121 packages.add(package);
130 if (!_isUnlinkedBundleConsistent(bundle)) { 122 }
131 knownInconsistentBundlePaths.add(path);
132 return null;
133 }
134 // OK, put the package into the cache.
135 package = new Package(path, bundle);
136 bundlePathToPackageMap[path] = package;
137 }
138 return package;
139 } catch (_) {
140 return null;
141 }
142 }
143
144 /**
145 * Return all consistent [Package]s in the given [folderPath].
146 */
147 List<Package> _getPackages(String folderPath) {
148 List<Package> packages = <Package>[];
149 try {
150 Folder folder = provider.getFolder(folderPath);
151 List<Resource> children = folder.getChildren();
152 for (Resource child in children) {
153 if (child is File) {
154 String packagePath = child.path;
155 if (packagePath.toLowerCase().endsWith('.full.ds')) {
156 Package package = _getPackage(packagePath);
157 if (package != null) {
158 packages.add(package);
159 } 123 }
160 } 124 }
161 } 125 }
162 } 126 } on FileSystemException {}
163 } on FileSystemException {} 127 folderToPackagesMap[folder] = packages;
128 }
164 return packages; 129 return packages;
165 } 130 }
166 131
167 /** 132 /**
168 * Return `true` if the unlinked information of the [bundle] is consistent 133 * Return `true` if the unlinked information of the [bundle] is consistent
169 * with its constituent sources. 134 * with its constituent sources in [context].
170 */ 135 */
171 bool _isUnlinkedBundleConsistent(PackageBundle bundle) { 136 bool _isUnlinkedBundleConsistent(PackageBundle bundle) {
172 try { 137 try {
173 // Compute hashes of the constituent sources. 138 // Compute hashes of the constituent sources.
174 List<String> actualHashes = <String>[]; 139 List<String> actualHashes = <String>[];
175 for (String uri in bundle.unlinkedUnitUris) { 140 for (String uri in bundle.unlinkedUnitUris) {
176 Source source = context.sourceFactory.resolveUri(null, uri); 141 Source source = context.sourceFactory.resolveUri(null, uri);
177 if (source == null) { 142 if (source == null) {
178 return false; 143 return false;
179 } 144 }
180 String hash = _computeSourceHashHex(source); 145 String hash = _computeSourceHashHex(source);
181 actualHashes.add(hash); 146 actualHashes.add(hash);
182 } 147 }
183 // Compare sorted actual and bundle unit hashes. 148 // Compare sorted actual and bundle unit hashes.
184 List<String> bundleHashes = bundle.unlinkedUnitHashes.toList()..sort(); 149 List<String> bundleHashes = bundle.unlinkedUnitHashes.toList()..sort();
185 actualHashes.sort(); 150 actualHashes.sort();
186 return listsEqual(actualHashes, bundleHashes); 151 return listsEqual(actualHashes, bundleHashes);
187 } catch (_) { 152 } on FileSystemException {}
188 return false; 153 return false;
189 } 154 }
155
156 /**
157 * Read the unlinked [Package] from the given [file], or return `null` if the
158 * file does not exist, or it cannot be read, or is not consistent with the
159 * constituent sources on the file system.
160 */
161 Package _readUnlinkedPackage(File file) {
162 try {
163 List<int> bytes = file.readAsBytesSync();
164 PackageBundle bundle = new PackageBundle.fromBuffer(bytes);
165 // Check for consistency, and fail if it's not.
166 if (!_isUnlinkedBundleConsistent(bundle)) {
167 return null;
168 }
169 // OK, use the bundle.
170 return new Package(file, bundle);
171 } on FileSystemException {}
172 return null;
190 } 173 }
191 } 174 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/src/summary/bazel_summary_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698