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

Side by Side Diff: pkg/analysis_server/lib/src/context_manager.dart

Issue 1443173004: Optimize work with absolute paths. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month 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
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 context.directory.manager; 5 library context.directory.manager;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection'; 8 import 'dart:collection';
9 import 'dart:convert'; 9 import 'dart:convert';
10 import 'dart:core' hide Resource; 10 import 'dart:core' hide Resource;
11 11
12 import 'package:analysis_server/plugin/analysis/resolver_provider.dart'; 12 import 'package:analysis_server/plugin/analysis/resolver_provider.dart';
13 import 'package:analysis_server/src/analysis_server.dart'; 13 import 'package:analysis_server/src/analysis_server.dart';
14 import 'package:analyzer/file_system/file_system.dart'; 14 import 'package:analyzer/file_system/file_system.dart';
15 import 'package:analyzer/instrumentation/instrumentation.dart'; 15 import 'package:analyzer/instrumentation/instrumentation.dart';
16 import 'package:analyzer/plugin/options.dart'; 16 import 'package:analyzer/plugin/options.dart';
17 import 'package:analyzer/source/analysis_options_provider.dart'; 17 import 'package:analyzer/source/analysis_options_provider.dart';
18 import 'package:analyzer/source/package_map_provider.dart'; 18 import 'package:analyzer/source/package_map_provider.dart';
19 import 'package:analyzer/source/package_map_resolver.dart'; 19 import 'package:analyzer/source/package_map_resolver.dart';
20 import 'package:analyzer/source/path_filter.dart'; 20 import 'package:analyzer/source/path_filter.dart';
21 import 'package:analyzer/source/pub_package_map_provider.dart'; 21 import 'package:analyzer/source/pub_package_map_provider.dart';
22 import 'package:analyzer/source/sdk_ext.dart'; 22 import 'package:analyzer/source/sdk_ext.dart';
23 import 'package:analyzer/src/context/context.dart' as context; 23 import 'package:analyzer/src/context/context.dart' as context;
24 import 'package:analyzer/src/generated/engine.dart'; 24 import 'package:analyzer/src/generated/engine.dart';
25 import 'package:analyzer/src/generated/java_engine.dart'; 25 import 'package:analyzer/src/generated/java_engine.dart';
26 import 'package:analyzer/src/generated/java_io.dart'; 26 import 'package:analyzer/src/generated/java_io.dart';
27 import 'package:analyzer/src/generated/source.dart'; 27 import 'package:analyzer/src/generated/source.dart';
28 import 'package:analyzer/src/generated/source_io.dart'; 28 import 'package:analyzer/src/generated/source_io.dart';
29 import 'package:analyzer/src/task/options.dart'; 29 import 'package:analyzer/src/task/options.dart';
30 import 'package:analyzer/src/util/absolute_path.dart';
30 import 'package:package_config/packages.dart'; 31 import 'package:package_config/packages.dart';
31 import 'package:package_config/packages_file.dart' as pkgfile show parse; 32 import 'package:package_config/packages_file.dart' as pkgfile show parse;
32 import 'package:package_config/src/packages_impl.dart' show MapPackages; 33 import 'package:package_config/src/packages_impl.dart' show MapPackages;
33 import 'package:path/path.dart' as pathos; 34 import 'package:path/path.dart' as pathos;
34 import 'package:watcher/watcher.dart'; 35 import 'package:watcher/watcher.dart';
35 import 'package:yaml/yaml.dart'; 36 import 'package:yaml/yaml.dart';
36 37
37 /** 38 /**
38 * Information tracked by the [ContextManager] for each context. 39 * Information tracked by the [ContextManager] for each context.
39 */ 40 */
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 * The [ResourceProvider] using which paths are converted into [Resource]s. 341 * The [ResourceProvider] using which paths are converted into [Resource]s.
341 */ 342 */
342 final ResourceProvider resourceProvider; 343 final ResourceProvider resourceProvider;
343 344
344 /** 345 /**
345 * The context used to work with file system paths. 346 * The context used to work with file system paths.
346 */ 347 */
347 pathos.Context pathContext; 348 pathos.Context pathContext;
348 349
349 /** 350 /**
351 * The context used to work with absolute file system paths.
352 *
353 * TODO(scheglov) remove [pathContext].
354 */
355 AbsolutePathContext absolutePathContext;
356
357 /**
350 * The list of excluded paths (folders and files) most recently passed to 358 * The list of excluded paths (folders and files) most recently passed to
351 * [setRoots]. 359 * [setRoots].
352 */ 360 */
353 List<String> excludedPaths = <String>[]; 361 List<String> excludedPaths = <String>[];
354 362
355 /** 363 /**
356 * The list of included paths (folders and files) most recently passed to 364 * The list of included paths (folders and files) most recently passed to
357 * [setRoots]. 365 * [setRoots].
358 */ 366 */
359 List<String> includedPaths = <String>[]; 367 List<String> includedPaths = <String>[];
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 /** 411 /**
404 * Stream subscription we are using to watch each analysis root directory for 412 * Stream subscription we are using to watch each analysis root directory for
405 * changes. 413 * changes.
406 */ 414 */
407 final Map<Folder, StreamSubscription<WatchEvent>> changeSubscriptions = 415 final Map<Folder, StreamSubscription<WatchEvent>> changeSubscriptions =
408 <Folder, StreamSubscription<WatchEvent>>{}; 416 <Folder, StreamSubscription<WatchEvent>>{};
409 417
410 ContextManagerImpl(this.resourceProvider, this.packageResolverProvider, 418 ContextManagerImpl(this.resourceProvider, this.packageResolverProvider,
411 this._packageMapProvider, this._instrumentationService) { 419 this._packageMapProvider, this._instrumentationService) {
412 pathContext = resourceProvider.pathContext; 420 pathContext = resourceProvider.pathContext;
421 absolutePathContext = new AbsolutePathContext(pathContext.separator);
413 } 422 }
414 423
415 @override 424 @override
416 List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot) { 425 List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot) {
417 List<AnalysisContext> contexts = <AnalysisContext>[]; 426 List<AnalysisContext> contexts = <AnalysisContext>[];
418 ContextInfo innermostContainingInfo = 427 ContextInfo innermostContainingInfo =
419 _getInnermostContextInfoFor(analysisRoot.path); 428 _getInnermostContextInfoFor(analysisRoot.path);
420 void addContextAndDescendants(ContextInfo info) { 429 void addContextAndDescendants(ContextInfo info) {
421 contexts.add(info.context); 430 contexts.add(info.context);
422 info.children.forEach(addContextAndDescendants); 431 info.children.forEach(addContextAndDescendants);
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
730 analysisContext.invalidateCachedResults(); 739 analysisContext.invalidateCachedResults();
731 callbacks.applyChangesToContext(info.folder, new ChangeSet()); 740 callbacks.applyChangesToContext(info.folder, new ChangeSet());
732 } 741 }
733 } 742 }
734 } 743 }
735 744
736 void _checkForPackagespecUpdate( 745 void _checkForPackagespecUpdate(
737 String path, ContextInfo info, Folder folder) { 746 String path, ContextInfo info, Folder folder) {
738 // Check to see if this is the .packages file for this context and if so, 747 // Check to see if this is the .packages file for this context and if so,
739 // update the context's source factory. 748 // update the context's source factory.
740 if (pathContext.basename(path) == PACKAGE_SPEC_NAME && 749 if (absolutePathContext.basename(path) == PACKAGE_SPEC_NAME &&
741 info.isPathToPackageDescription(path)) { 750 info.isPathToPackageDescription(path)) {
742 File packagespec = resourceProvider.getFile(path); 751 File packagespec = resourceProvider.getFile(path);
743 if (packagespec.exists) { 752 if (packagespec.exists) {
744 Packages packages = _readPackagespec(packagespec); 753 Packages packages = _readPackagespec(packagespec);
745 if (packages != null) { 754 if (packages != null) {
746 callbacks.updateContextPackageUriResolver( 755 callbacks.updateContextPackageUriResolver(
747 folder, new PackagesFileDisposition(packages)); 756 folder, new PackagesFileDisposition(packages));
748 } 757 }
749 } 758 }
750 } 759 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
813 // [setRoots] ignores any package roots that don't exist (or aren't 822 // [setRoots] ignores any package roots that don't exist (or aren't
814 // folders), the only way we should be able to get here is due to a race 823 // folders), the only way we should be able to get here is due to a race
815 // condition. In any case, the package root folder is gone, so we can't 824 // condition. In any case, the package root folder is gone, so we can't
816 // resolve packages. 825 // resolve packages.
817 return new NoPackageFolderDisposition(packageRoot: packageRoot); 826 return new NoPackageFolderDisposition(packageRoot: packageRoot);
818 } else { 827 } else {
819 PackageMapInfo packageMapInfo; 828 PackageMapInfo packageMapInfo;
820 callbacks.beginComputePackageMap(); 829 callbacks.beginComputePackageMap();
821 try { 830 try {
822 // Try .packages first. 831 // Try .packages first.
823 if (pathContext.basename(packagespecFile.path) == PACKAGE_SPEC_NAME) { 832 if (absolutePathContext.basename(packagespecFile.path) ==
833 PACKAGE_SPEC_NAME) {
824 Packages packages = _readPackagespec(packagespecFile); 834 Packages packages = _readPackagespec(packagespecFile);
825 return new PackagesFileDisposition(packages); 835 return new PackagesFileDisposition(packages);
826 } 836 }
827 if (packageResolverProvider != null) { 837 if (packageResolverProvider != null) {
828 UriResolver resolver = packageResolverProvider(folder); 838 UriResolver resolver = packageResolverProvider(folder);
829 if (resolver != null) { 839 if (resolver != null) {
830 return new CustomPackageResolverDisposition(resolver); 840 return new CustomPackageResolverDisposition(resolver);
831 } 841 }
832 } 842 }
833 843
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1054 return; 1064 return;
1055 } 1065 }
1056 if (info.ignored(path)) { 1066 if (info.ignored(path)) {
1057 return; 1067 return;
1058 } 1068 }
1059 // handle the change 1069 // handle the change
1060 switch (event.type) { 1070 switch (event.type) {
1061 case ChangeType.ADD: 1071 case ChangeType.ADD:
1062 Resource resource = resourceProvider.getResource(path); 1072 Resource resource = resourceProvider.getResource(path);
1063 1073
1064 String directoryPath = pathContext.dirname(path); 1074 String directoryPath = absolutePathContext.dirname(path);
1065 1075
1066 // Check to see if we need to create a new context. 1076 // Check to see if we need to create a new context.
1067 if (info.isTopLevel) { 1077 if (info.isTopLevel) {
1068 // Only create a new context if this is not the same directory 1078 // Only create a new context if this is not the same directory
1069 // described by our info object. 1079 // described by our info object.
1070 if (info.folder.path != directoryPath) { 1080 if (info.folder.path != directoryPath) {
1071 if (_isPubspec(path)) { 1081 if (_isPubspec(path)) {
1072 // Check for a sibling .packages file. 1082 // Check for a sibling .packages file.
1073 if (!resourceProvider 1083 if (!resourceProvider
1074 .getFile(pathContext.join(directoryPath, PACKAGE_SPEC_NAME)) 1084 .getFile(absolutePathContext.append(
1085 directoryPath, PACKAGE_SPEC_NAME))
1075 .exists) { 1086 .exists) {
1076 _extractContext(info, resource); 1087 _extractContext(info, resource);
1077 return; 1088 return;
1078 } 1089 }
1079 } 1090 }
1080 if (_isPackagespec(path)) { 1091 if (_isPackagespec(path)) {
1081 // Check for a sibling pubspec.yaml file. 1092 // Check for a sibling pubspec.yaml file.
1082 if (!resourceProvider 1093 if (!resourceProvider
1083 .getFile(pathContext.join(directoryPath, PUBSPEC_NAME)) 1094 .getFile(
1095 absolutePathContext.append(directoryPath, PUBSPEC_NAME))
1084 .exists) { 1096 .exists) {
1085 _extractContext(info, resource); 1097 _extractContext(info, resource);
1086 return; 1098 return;
1087 } 1099 }
1088 } 1100 }
1089 } 1101 }
1090 } 1102 }
1091 1103
1092 // If the file went away and was replaced by a folder before we 1104 // If the file went away and was replaced by a folder before we
1093 // had a chance to process the event, resource might be a Folder. In 1105 // had a chance to process the event, resource might be a Folder. In
1094 // that case don't add it. 1106 // that case don't add it.
1095 if (resource is File) { 1107 if (resource is File) {
1096 File file = resource; 1108 File file = resource;
1097 if (callbacks.shouldFileBeAnalyzed(file)) { 1109 if (callbacks.shouldFileBeAnalyzed(file)) {
1098 ChangeSet changeSet = new ChangeSet(); 1110 ChangeSet changeSet = new ChangeSet();
1099 Source source = createSourceInContext(info.context, file); 1111 Source source = createSourceInContext(info.context, file);
1100 changeSet.addedSource(source); 1112 changeSet.addedSource(source);
1101 callbacks.applyChangesToContext(info.folder, changeSet); 1113 callbacks.applyChangesToContext(info.folder, changeSet);
1102 info.sources[path] = source; 1114 info.sources[path] = source;
1103 } 1115 }
1104 } 1116 }
1105 break; 1117 break;
1106 case ChangeType.REMOVE: 1118 case ChangeType.REMOVE:
1107 1119
1108 // If package spec info is removed, check to see if we can merge context s. 1120 // If package spec info is removed, check to see if we can merge context s.
1109 // Note that it's important to verify that there is NEITHER a .packages nor a 1121 // Note that it's important to verify that there is NEITHER a .packages nor a
1110 // lingering pubspec.yaml before merging. 1122 // lingering pubspec.yaml before merging.
1111 if (!info.isTopLevel) { 1123 if (!info.isTopLevel) {
1112 String directoryPath = pathContext.dirname(path); 1124 String directoryPath = absolutePathContext.dirname(path);
1113 1125
1114 // Only merge if this is the same directory described by our info obje ct. 1126 // Only merge if this is the same directory described by our info obje ct.
1115 if (info.folder.path == directoryPath) { 1127 if (info.folder.path == directoryPath) {
1116 if (_isPubspec(path)) { 1128 if (_isPubspec(path)) {
1117 // Check for a sibling .packages file. 1129 // Check for a sibling .packages file.
1118 if (!resourceProvider 1130 if (!resourceProvider
1119 .getFile(pathContext.join(directoryPath, PACKAGE_SPEC_NAME)) 1131 .getFile(absolutePathContext.append(
1132 directoryPath, PACKAGE_SPEC_NAME))
1120 .exists) { 1133 .exists) {
1121 _mergeContext(info); 1134 _mergeContext(info);
1122 return; 1135 return;
1123 } 1136 }
1124 } 1137 }
1125 if (_isPackagespec(path)) { 1138 if (_isPackagespec(path)) {
1126 // Check for a sibling pubspec.yaml file. 1139 // Check for a sibling pubspec.yaml file.
1127 if (!resourceProvider 1140 if (!resourceProvider
1128 .getFile(pathContext.join(directoryPath, PUBSPEC_NAME)) 1141 .getFile(
1142 absolutePathContext.append(directoryPath, PUBSPEC_NAME))
1129 .exists) { 1143 .exists) {
1130 _mergeContext(info); 1144 _mergeContext(info);
1131 return; 1145 return;
1132 } 1146 }
1133 } 1147 }
1134 } 1148 }
1135 } 1149 }
1136 1150
1137 List<Source> sources = info.context.getSourcesWithFullName(path); 1151 List<Source> sources = info.context.getSourcesWithFullName(path);
1138 if (!sources.isEmpty) { 1152 if (!sources.isEmpty) {
(...skipping 18 matching lines...) Expand all
1157 } 1171 }
1158 _checkForPackagespecUpdate(path, info, info.folder); 1172 _checkForPackagespecUpdate(path, info, info.folder);
1159 _checkForAnalysisOptionsUpdate(path, info, event.type); 1173 _checkForAnalysisOptionsUpdate(path, info, event.type);
1160 } 1174 }
1161 1175
1162 /** 1176 /**
1163 * Determine whether the given [path], when interpreted relative to the 1177 * Determine whether the given [path], when interpreted relative to the
1164 * context root [root], contains a folder whose name starts with '.'. 1178 * context root [root], contains a folder whose name starts with '.'.
1165 */ 1179 */
1166 bool _isContainedInDotFolder(String root, String path) { 1180 bool _isContainedInDotFolder(String root, String path) {
1167 String relativePath = 1181 String pathDir = absolutePathContext.dirname(path);
1168 pathContext.relative(pathContext.dirname(path), from: root); 1182 String relativePath = absolutePathContext.relative(pathDir, root);
1169 for (String pathComponent in pathContext.split(relativePath)) { 1183 if (relativePath == null) {
1184 return false;
1185 }
1186 for (String pathComponent in absolutePathContext.split(relativePath)) {
1170 if (pathComponent.startsWith('.') && 1187 if (pathComponent.startsWith('.') &&
1171 pathComponent != '.' && 1188 pathComponent != '.' &&
1172 pathComponent != '..') { 1189 pathComponent != '..') {
1173 return true; 1190 return true;
1174 } 1191 }
1175 } 1192 }
1176 return false; 1193 return false;
1177 } 1194 }
1178 1195
1179 /** 1196 /**
1180 * Returns `true` if the given [path] is excluded by [excludedPaths]. 1197 * Returns `true` if the given [path] is excluded by [excludedPaths].
1181 */ 1198 */
1182 bool _isExcluded(String path) => _isExcludedBy(excludedPaths, path); 1199 bool _isExcluded(String path) => _isExcludedBy(excludedPaths, path);
1183 1200
1184 /** 1201 /**
1185 * Returns `true` if the given [path] is excluded by [excludedPaths]. 1202 * Returns `true` if the given [path] is excluded by [excludedPaths].
1186 */ 1203 */
1187 bool _isExcludedBy(List<String> excludedPaths, String path) { 1204 bool _isExcludedBy(List<String> excludedPaths, String path) {
1188 return excludedPaths.any((excludedPath) { 1205 return excludedPaths.any((excludedPath) {
1189 if (pathContext.isWithin(excludedPath, path)) { 1206 if (absolutePathContext.isWithin(excludedPath, path)) {
1190 return true; 1207 return true;
1191 } 1208 }
1192 return path == excludedPath; 1209 return path == excludedPath;
1193 }); 1210 });
1194 } 1211 }
1195 1212
1196 /** 1213 /**
1197 * Determine whether the given [path], when interpreted relative to the 1214 * Determine whether the given [path], when interpreted relative to the
1198 * context root [root], contains a 'packages' folder. 1215 * context root [root], contains a 'packages' folder.
1199 */ 1216 */
1200 bool _isInPackagesDir(String root, String path) { 1217 bool _isInPackagesDir(String root, String path) {
1201 String relativePath = pathContext.relative(path, from: root); 1218 String relativePath = absolutePathContext.relative(path, root);
1202 List<String> pathParts = pathContext.split(relativePath); 1219 if (relativePath == null) {
1220 return false;
1221 }
1222 List<String> pathParts = absolutePathContext.split(relativePath);
1203 return pathParts.contains(PACKAGES_NAME); 1223 return pathParts.contains(PACKAGES_NAME);
1204 } 1224 }
1205 1225
1206 /** 1226 /**
1207 * Determine whether the given [path] is in the direct 'doc' folder of the 1227 * Determine whether the given [path] is in the direct 'doc' folder of the
1208 * context root [root]. 1228 * context root [root].
1209 */ 1229 */
1210 bool _isInTopLevelDocDir(String root, String path) { 1230 bool _isInTopLevelDocDir(String root, String path) {
1211 String relativePath = pathContext.relative(path, from: root); 1231 String relativePath = absolutePathContext.relative(path, root);
1232 if (relativePath == null) {
1233 return false;
1234 }
1212 return relativePath == DOC_DIR_NAME || 1235 return relativePath == DOC_DIR_NAME ||
1213 relativePath.startsWith(DOC_DIR_NAME + pathContext.separator); 1236 relativePath.startsWith(DOC_DIR_NAME + absolutePathContext.separator);
1214 } 1237 }
1215 1238
1216 bool _isPackagespec(String path) => 1239 bool _isPackagespec(String path) =>
1217 pathContext.basename(path) == PACKAGE_SPEC_NAME; 1240 absolutePathContext.basename(path) == PACKAGE_SPEC_NAME;
1218 1241
1219 bool _isPubspec(String path) => pathContext.basename(path) == PUBSPEC_NAME; 1242 bool _isPubspec(String path) =>
1243 absolutePathContext.basename(path) == PUBSPEC_NAME;
1220 1244
1221 /** 1245 /**
1222 * Merges [info] context into its parent. 1246 * Merges [info] context into its parent.
1223 */ 1247 */
1224 void _mergeContext(ContextInfo info) { 1248 void _mergeContext(ContextInfo info) {
1225 // destroy the context 1249 // destroy the context
1226 _destroyContext(info); 1250 _destroyContext(info);
1227 // add files to the parent context 1251 // add files to the parent context
1228 ContextInfo parentInfo = info.parent; 1252 ContextInfo parentInfo = info.parent;
1229 if (parentInfo != null) { 1253 if (parentInfo != null) {
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
1445 var path = resourceProvider.pathContext.fromUri(uri); 1469 var path = resourceProvider.pathContext.fromUri(uri);
1446 packageMap[name] = <Folder>[resourceProvider.getFolder(path)]; 1470 packageMap[name] = <Folder>[resourceProvider.getFolder(path)];
1447 } 1471 }
1448 }); 1472 });
1449 return <UriResolver>[new SdkExtUriResolver(packageMap)]; 1473 return <UriResolver>[new SdkExtUriResolver(packageMap)];
1450 } else { 1474 } else {
1451 return const <UriResolver>[]; 1475 return const <UriResolver>[];
1452 } 1476 }
1453 } 1477 }
1454 } 1478 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/util/absolute_path.dart » ('j') | pkg/analyzer/lib/src/util/absolute_path.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698