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

Side by Side Diff: pkg/analyzer/lib/src/generated/gn.dart

Issue 2651613003: Added support for GN workspaces. (Closed)
Patch Set: Tests Created 3 years, 10 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 | « pkg/analyzer/lib/src/context/builder.dart ('k') | pkg/analyzer/test/generated/gn_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
(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 library analyzer.src.generated.gn;
6
7 import 'dart:collection';
8 import 'dart:core';
9
10 import 'package:analyzer/file_system/file_system.dart';
11 import 'package:analyzer/src/generated/source.dart';
12 import 'package:analyzer/src/generated/source_io.dart';
13 import 'package:analyzer/src/util/fast_uri.dart';
14 import 'package:path/path.dart';
15
16 /**
17 * The [UriResolver] used to resolve `file` URIs in a [GnWorkspace].
18 */
19 class GnFileUriResolver extends ResourceUriResolver {
20 /**
21 * The workspace associated with this resolver.
22 */
23 final GnWorkspace workspace;
24
25 /**
26 * Initialize a newly created resolver to be associated with the given
27 * [workspace].
28 */
29 GnFileUriResolver(GnWorkspace workspace)
30 : workspace = workspace,
31 super(workspace.provider);
32
33 @override
34 Source resolveAbsolute(Uri uri, [Uri actualUri]) {
35 if (!ResourceUriResolver.isFileUri(uri)) {
36 return null;
37 }
38 String path = provider.pathContext.fromUri(uri);
39 File file = workspace.findFile(path);
40 if (file != null) {
41 return file.createSource(actualUri ?? uri);
42 }
43 return null;
44 }
45 }
46
47 /**
48 * The [UriResolver] used to resolve `package` URIs in a [GnWorkspace].
49 */
50 class GnPackageUriResolver extends UriResolver {
51 /**
52 * The workspace associated with this resolver.
53 */
54 final GnWorkspace workspace;
55
56 /**
57 * The path context that should be used to manipulate file system paths.
58 */
59 final Context pathContext;
60
61 /**
62 * The map of package sources indexed by package name.
63 */
64 final Map<String, String> _packages;
65
66 /**
67 * The cache of absolute [Uri]s to [Source]s mappings.
68 */
69 final Map<Uri, Source> _sourceCache = new HashMap<Uri, Source>();
70
71 /**
72 * Initialize a newly created resolver to be associated with the given
73 * [workspace].
74 */
75 GnPackageUriResolver(GnWorkspace workspace)
76 : workspace = workspace,
77 pathContext = workspace.provider.pathContext,
78 _packages = workspace.packages;
79
80 @override
81 Source resolveAbsolute(Uri uri, [Uri actualUri]) {
82 return _sourceCache.putIfAbsent(uri, () {
83 if (uri.scheme != 'package') {
84 return null;
85 }
86
87 String uriPath = uri.path;
88 int slash = uriPath.indexOf('/');
89
90 // If the path either starts with a slash or has no slash, it is invalid.
91 if (slash < 1) {
92 return null;
93 }
94
95 String packageName = uriPath.substring(0, slash);
96 String fileUriPart = uriPath.substring(slash + 1);
97 String filePath = fileUriPart.replaceAll('/', pathContext.separator);
98
99 if (!_packages.containsKey(packageName)) {
100 return null;
101 }
102 String packageBase = _packages[packageName];
103 String path = pathContext.join(packageBase, filePath);
104 File file = workspace.findFile(path);
105 return file?.createSource(uri);
106 });
107 }
108
109 @override
110 Uri restoreAbsolute(Source source) {
111 Context context = workspace.provider.pathContext;
112 String path = source.fullName;
113
114 if (!context.isWithin(workspace.root, path)) {
115 return null;
116 }
117
118 String package = _packages.keys.firstWhere(
119 (key) => context.isWithin(_packages[key], path),
120 orElse: () => null);
121
122 if (package == null) {
123 return null;
124 }
125
126 String sourcePath = context.relative(path, from: _packages[package]);
127
128 return FastUri.parse('package:$package/$sourcePath');
129 }
130 }
131
132 /**
133 * Information about a Gn workspace.
134 */
135 class GnWorkspace {
136 /**
137 * The name of the directory that identifies the root of the workspace.
138 */
139 static const String _jiriRootName = '.jiri_root';
140
141 /**
142 * The resource provider used to access the file system.
143 */
144 final ResourceProvider provider;
145
146 /**
147 * The absolute workspace root path (the directory containing the `.jiri_root`
148 * directory).
149 */
150 final String root;
151
152 /**
153 * The map of package sources indexed by package name.
154 */
155 final Map<String, String> packages;
156
157 GnWorkspace._(this.provider, this.root, this.packages);
158
159 /**
160 * Return a map of package sources.
161 */
162 Map<String, List<Folder>> get packageMap {
163 Map<String, List<Folder>> result = new HashMap<String, List<Folder>>();
164 packages.forEach((package, sourceDir) {
165 result[package] = [provider.getFolder(sourceDir)];
166 });
167 return result;
168 }
169
170 /**
171 * Return the file with the given [absolutePath].
172 *
173 * Return `null` if the given [absolutePath] is not in the workspace [root].
174 */
175 File findFile(String absolutePath) {
176 try {
177 File writableFile = provider.getFile(absolutePath);
178 return writableFile;
179 } catch (_) {
180 return null;
181 }
182 }
183
184 /**
185 * Locate the output directory.
186 *
187 * Return `null` if it could not be found.
188 */
189 static String _getOutDirectory(ResourceProvider provider, String root) =>
190 provider
191 .getFolder('$root/out')
192 .getChildren()
193 .where((resource) => resource is Folder)
194 .map((resource) => resource as Folder)
195 .firstWhere((Folder folder) {
196 String baseName = basename(folder.path);
197 // TODO(pylaligand): find a better way to locate the proper directory.
198 return baseName.startsWith('debug') || baseName.startsWith('release');
199 }, orElse: () => null)?.path;
200
201 /**
202 * Return a map of package source locations indexed by package name.
203 */
204 static Map<String, String> _getPackages(
205 ResourceProvider provider, String outDirectory) {
206 String packagesDir = '$outDirectory/gen/dart.sources';
207 Map<String, String> result = new HashMap<String, String>();
208 provider
209 .getFolder(packagesDir)
210 .getChildren()
211 .where((resource) => resource is File)
212 .map((resource) => resource as File)
213 .forEach((file) {
214 String packageName = basename(file.path);
215 String source = file.readAsStringSync();
216 result[packageName] = source;
217 });
218 return result;
219 }
220
221 /**
222 * Find the Gn workspace that contains the given [path].
223 *
224 * Return `null` if a workspace markers, such as the `.jiri_root` directory
225 * cannot be found.
226 */
227 static GnWorkspace find(ResourceProvider provider, String path) {
228 Context context = provider.pathContext;
229
230 // Ensure that the path is absolute and normalized.
231 if (!context.isAbsolute(path)) {
232 throw new ArgumentError('not absolute: $path');
233 }
234 path = context.normalize(path);
235
236 Folder folder = provider.getFolder(path);
237 while (true) {
238 Folder parent = folder.parent;
239 if (parent == null) {
240 return null;
241 }
242
243 // Found the .jiri_root file, must be a non-git workspace.
244 if (folder.getChildAssumingFolder(_jiriRootName).exists) {
245 String root = folder.path;
246 String outDirectory = _getOutDirectory(provider, root);
247 Map<String, String> packages = _getPackages(provider, outDirectory);
248 return new GnWorkspace._(provider, root, packages);
249 }
250
251 // Go up the folder.
252 folder = parent;
253 }
254 }
255 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/context/builder.dart ('k') | pkg/analyzer/test/generated/gn_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698