OLD | NEW |
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; |
(...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
723 /** | 723 /** |
724 * Compute the appropriate [FolderDisposition] for [folder]. Use | 724 * Compute the appropriate [FolderDisposition] for [folder]. Use |
725 * [addDependency] to indicate which files needed to be consulted in order to | 725 * [addDependency] to indicate which files needed to be consulted in order to |
726 * figure out the [FolderDisposition]; these dependencies will be watched in | 726 * figure out the [FolderDisposition]; these dependencies will be watched in |
727 * order to determine when it is necessary to call this function again. | 727 * order to determine when it is necessary to call this function again. |
728 * | 728 * |
729 * TODO(paulberry): use [addDependency] for tracking all folder disposition | 729 * TODO(paulberry): use [addDependency] for tracking all folder disposition |
730 * dependencies (currently we only use it to track "pub list" dependencies). | 730 * dependencies (currently we only use it to track "pub list" dependencies). |
731 */ | 731 */ |
732 FolderDisposition _computeFolderDisposition( | 732 FolderDisposition _computeFolderDisposition( |
733 Folder folder, void addDependency(String path)) { | 733 Folder folder, void addDependency(String path), File packagespecFile) { |
734 String packageRoot = normalizedPackageRoots[folder.path]; | 734 String packageRoot = normalizedPackageRoots[folder.path]; |
735 if (packageRoot != null) { | 735 if (packageRoot != null) { |
736 // TODO(paulberry): We shouldn't be using JavaFile here because it | 736 // TODO(paulberry): We shouldn't be using JavaFile here because it |
737 // makes the code untestable (see dartbug.com/23909). | 737 // makes the code untestable (see dartbug.com/23909). |
738 JavaFile packagesDir = new JavaFile(packageRoot); | 738 JavaFile packagesDir = new JavaFile(packageRoot); |
739 Map<String, List<Folder>> packageMap = new Map<String, List<Folder>>(); | 739 Map<String, List<Folder>> packageMap = new Map<String, List<Folder>>(); |
740 if (packagesDir.isDirectory()) { | 740 if (packagesDir.isDirectory()) { |
741 for (JavaFile file in packagesDir.listFiles()) { | 741 for (JavaFile file in packagesDir.listFiles()) { |
742 // Ensure symlinks in packages directory are canonicalized | 742 // Ensure symlinks in packages directory are canonicalized |
743 // to prevent 'type X cannot be assigned to type X' warnings | 743 // to prevent 'type X cannot be assigned to type X' warnings |
(...skipping 12 matching lines...) Expand all Loading... |
756 } | 756 } |
757 return new PackageMapDisposition(packageMap, packageRoot: packageRoot); | 757 return new PackageMapDisposition(packageMap, packageRoot: packageRoot); |
758 } | 758 } |
759 // The package root does not exist (or is not a folder). Since | 759 // The package root does not exist (or is not a folder). Since |
760 // [setRoots] ignores any package roots that don't exist (or aren't | 760 // [setRoots] ignores any package roots that don't exist (or aren't |
761 // folders), the only way we should be able to get here is due to a race | 761 // folders), the only way we should be able to get here is due to a race |
762 // condition. In any case, the package root folder is gone, so we can't | 762 // condition. In any case, the package root folder is gone, so we can't |
763 // resolve packages. | 763 // resolve packages. |
764 return new NoPackageFolderDisposition(packageRoot: packageRoot); | 764 return new NoPackageFolderDisposition(packageRoot: packageRoot); |
765 } else { | 765 } else { |
| 766 PackageMapInfo packageMapInfo; |
766 callbacks.beginComputePackageMap(); | 767 callbacks.beginComputePackageMap(); |
767 if (packageResolverProvider != null) { | 768 try { |
768 UriResolver resolver = packageResolverProvider(folder); | 769 if (ENABLE_PACKAGESPEC_SUPPORT) { |
769 if (resolver != null) { | 770 // Try .packages first. |
770 return new CustomPackageResolverDisposition(resolver); | 771 if (pathos.basename(packagespecFile.path) == PACKAGE_SPEC_NAME) { |
| 772 Packages packages = _readPackagespec(packagespecFile); |
| 773 return new PackagesFileDisposition(packages); |
| 774 } |
771 } | 775 } |
| 776 if (packageResolverProvider != null) { |
| 777 UriResolver resolver = packageResolverProvider(folder); |
| 778 if (resolver != null) { |
| 779 return new CustomPackageResolverDisposition(resolver); |
| 780 } |
| 781 } |
| 782 ServerPerformanceStatistics.pub.makeCurrentWhile(() { |
| 783 packageMapInfo = _packageMapProvider.computePackageMap(folder); |
| 784 }); |
| 785 } finally { |
| 786 callbacks.endComputePackageMap(); |
772 } | 787 } |
773 PackageMapInfo packageMapInfo; | |
774 ServerPerformanceStatistics.pub.makeCurrentWhile(() { | |
775 packageMapInfo = _packageMapProvider.computePackageMap(folder); | |
776 }); | |
777 callbacks.endComputePackageMap(); | |
778 for (String dependencyPath in packageMapInfo.dependencies) { | 788 for (String dependencyPath in packageMapInfo.dependencies) { |
779 addDependency(dependencyPath); | 789 addDependency(dependencyPath); |
780 } | 790 } |
781 if (packageMapInfo.packageMap == null) { | 791 if (packageMapInfo.packageMap == null) { |
782 return new NoPackageFolderDisposition(); | 792 return new NoPackageFolderDisposition(); |
783 } | 793 } |
784 return new PackageMapDisposition(packageMapInfo.packageMap); | 794 return new PackageMapDisposition(packageMapInfo.packageMap); |
785 } | 795 } |
786 } | 796 } |
787 | 797 |
788 /** | 798 /** |
789 * Create a new empty context associated with [folder], having parent | 799 * Create a new empty context associated with [folder], having parent |
790 * [parent] and using [packagespecFile] to resolve package URI's. | 800 * [parent] and using [packagespecFile] to resolve package URI's. |
791 */ | 801 */ |
792 ContextInfo _createContext( | 802 ContextInfo _createContext( |
793 ContextInfo parent, Folder folder, File packagespecFile) { | 803 ContextInfo parent, Folder folder, File packagespecFile) { |
794 ContextInfo info = new ContextInfo(this, parent, folder, packagespecFile, | 804 ContextInfo info = new ContextInfo(this, parent, folder, packagespecFile, |
795 normalizedPackageRoots[folder.path]); | 805 normalizedPackageRoots[folder.path]); |
796 Map<String, YamlNode> options = analysisOptionsProvider.getOptions(folder); | 806 Map<String, YamlNode> options = analysisOptionsProvider.getOptions(folder); |
797 processOptionsForContext(info, options); | 807 processOptionsForContext(info, options); |
798 FolderDisposition disposition; | 808 FolderDisposition disposition; |
799 List<String> dependencies = <String>[]; | 809 List<String> dependencies = <String>[]; |
800 | 810 |
801 if (ENABLE_PACKAGESPEC_SUPPORT) { | |
802 // Try .packages first. | |
803 if (pathos.basename(packagespecFile.path) == PACKAGE_SPEC_NAME) { | |
804 Packages packages = _readPackagespec(packagespecFile); | |
805 disposition = new PackagesFileDisposition(packages); | |
806 } | |
807 } | |
808 | |
809 // Next resort to a package uri resolver. | 811 // Next resort to a package uri resolver. |
810 if (disposition == null) { | 812 if (disposition == null) { |
811 disposition = _computeFolderDisposition(folder, dependencies.add); | 813 disposition = |
| 814 _computeFolderDisposition(folder, dependencies.add, packagespecFile); |
812 } | 815 } |
813 | 816 |
814 info.setDependencies(dependencies); | 817 info.setDependencies(dependencies); |
815 info.context = callbacks.addContext(folder, disposition); | 818 info.context = callbacks.addContext(folder, disposition); |
816 info.context.name = folder.path; | 819 info.context.name = folder.path; |
817 return info; | 820 return info; |
818 } | 821 } |
819 | 822 |
820 /** | 823 /** |
821 * Potentially create a new context associated with the given [folder]. | 824 * Potentially create a new context associated with the given [folder]. |
822 * | 825 * |
823 * If there are subfolders with 'pubspec.yaml' files, separate contexts are | 826 * If there are subfolders with 'pubspec.yaml' files, separate contexts are |
824 * created for them and excluded from the context associated with the | 827 * created for them and excluded from the context associated with the |
825 * [folder]. | 828 * [folder]. |
826 * | 829 * |
827 * If [withPackageSpecOnly] is `true`, a context will be created only if there | 830 * If [withPackageSpecOnly] is `true`, a context will be created only if there |
828 * is a 'pubspec.yaml' or '.packages' file in the [folder]. | 831 * is a 'pubspec.yaml' or '.packages' file in the [folder]. |
829 * | 832 * |
830 * [parent] should be the parent of any contexts that are created. | 833 * [parent] should be the parent of any contexts that are created. |
831 */ | 834 */ |
832 void _createContexts( | 835 void _createContexts( |
833 ContextInfo parent, Folder folder, bool withPackageSpecOnly) { | 836 ContextInfo parent, Folder folder, bool withPackageSpecOnly) { |
834 // Decide whether a context needs to be created for [folder] here, and if | 837 // Decide whether a context needs to be created for [folder] here, and if |
835 // so, create it. | 838 // so, create it. |
836 File packageSpec; | 839 File packageSpec = _findPackageSpecFile(folder); |
837 | |
838 if (ENABLE_PACKAGESPEC_SUPPORT) { | |
839 // Start by looking for .packages. | |
840 packageSpec = folder.getChild(PACKAGE_SPEC_NAME); | |
841 } | |
842 | |
843 // Fall back to looking for a pubspec. | |
844 if (packageSpec == null || !packageSpec.exists) { | |
845 packageSpec = folder.getChild(PUBSPEC_NAME); | |
846 } | |
847 | |
848 bool createContext = packageSpec.exists || !withPackageSpecOnly; | 840 bool createContext = packageSpec.exists || !withPackageSpecOnly; |
849 if (withPackageSpecOnly && | 841 if (withPackageSpecOnly && |
850 packageSpec.exists && | 842 packageSpec.exists && |
851 (parent != null) && | 843 (parent != null) && |
852 parent.ignored(packageSpec.path)) { | 844 parent.ignored(packageSpec.path)) { |
853 // Don't create a context if the package spec is required and ignored. | 845 // Don't create a context if the package spec is required and ignored. |
854 createContext = false; | 846 createContext = false; |
855 } | 847 } |
856 if (createContext) { | 848 if (createContext) { |
857 parent = _createContext(parent, folder, packageSpec); | 849 parent = _createContext(parent, folder, packageSpec); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
922 changeSet.removedSource(source); | 914 changeSet.removedSource(source); |
923 }); | 915 }); |
924 callbacks.applyChangesToContext(oldInfo.folder, changeSet); | 916 callbacks.applyChangesToContext(oldInfo.folder, changeSet); |
925 } | 917 } |
926 // TODO(paulberry): every context that was previously a child of oldInfo is | 918 // TODO(paulberry): every context that was previously a child of oldInfo is |
927 // is still a child of oldInfo. This is wrong--some of them ought to be | 919 // is still a child of oldInfo. This is wrong--some of them ought to be |
928 // adopted by newInfo now. | 920 // adopted by newInfo now. |
929 } | 921 } |
930 | 922 |
931 /** | 923 /** |
| 924 * Find the file that should be used to determine whether a context needs to |
| 925 * be created here--this is either the ".packages" file or the "pubspec.yaml" |
| 926 * file. |
| 927 */ |
| 928 File _findPackageSpecFile(Folder folder) { |
| 929 // Decide whether a context needs to be created for [folder] here, and if |
| 930 // so, create it. |
| 931 File packageSpec; |
| 932 |
| 933 if (ENABLE_PACKAGESPEC_SUPPORT) { |
| 934 // Start by looking for .packages. |
| 935 packageSpec = folder.getChild(PACKAGE_SPEC_NAME); |
| 936 } |
| 937 |
| 938 // Fall back to looking for a pubspec. |
| 939 if (packageSpec == null || !packageSpec.exists) { |
| 940 packageSpec = folder.getChild(PUBSPEC_NAME); |
| 941 } |
| 942 return packageSpec; |
| 943 } |
| 944 |
| 945 /** |
932 * Return the [ContextInfo] for the "innermost" context whose associated | 946 * Return the [ContextInfo] for the "innermost" context whose associated |
933 * folder is or contains the given path. ("innermost" refers to the nesting | 947 * folder is or contains the given path. ("innermost" refers to the nesting |
934 * of contexts, so if there is a context for path /foo and a context for | 948 * of contexts, so if there is a context for path /foo and a context for |
935 * path /foo/bar, then the innermost context containing /foo/bar/baz.dart is | 949 * path /foo/bar, then the innermost context containing /foo/bar/baz.dart is |
936 * the context for /foo/bar.) | 950 * the context for /foo/bar.) |
937 * | 951 * |
938 * If no context contains the given path, `null` is returned. | 952 * If no context contains the given path, `null` is returned. |
939 */ | 953 */ |
940 ContextInfo _getInnermostContextInfoFor(String path) { | 954 ContextInfo _getInnermostContextInfoFor(String path) { |
941 ContextInfo info = _rootInfo.findChildInfoFor(path); | 955 ContextInfo info = _rootInfo.findChildInfoFor(path); |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1175 /** | 1189 /** |
1176 * Recompute the [FolderDisposition] for the context described by [info], | 1190 * Recompute the [FolderDisposition] for the context described by [info], |
1177 * and update the client appropriately. | 1191 * and update the client appropriately. |
1178 */ | 1192 */ |
1179 void _recomputeFolderDisposition(ContextInfo info) { | 1193 void _recomputeFolderDisposition(ContextInfo info) { |
1180 // TODO(paulberry): when computePackageMap is changed into an | 1194 // TODO(paulberry): when computePackageMap is changed into an |
1181 // asynchronous API call, we'll want to suspend analysis for this context | 1195 // asynchronous API call, we'll want to suspend analysis for this context |
1182 // while we're rerunning "pub list", since any analysis we complete while | 1196 // while we're rerunning "pub list", since any analysis we complete while |
1183 // "pub list" is in progress is just going to get thrown away anyhow. | 1197 // "pub list" is in progress is just going to get thrown away anyhow. |
1184 List<String> dependencies = <String>[]; | 1198 List<String> dependencies = <String>[]; |
1185 FolderDisposition disposition = | 1199 FolderDisposition disposition = _computeFolderDisposition( |
1186 _computeFolderDisposition(info.folder, dependencies.add); | 1200 info.folder, dependencies.add, _findPackageSpecFile(info.folder)); |
1187 info.setDependencies(dependencies); | 1201 info.setDependencies(dependencies); |
1188 callbacks.updateContextPackageUriResolver(info.folder, disposition); | 1202 callbacks.updateContextPackageUriResolver(info.folder, disposition); |
1189 } | 1203 } |
1190 | 1204 |
1191 /** | 1205 /** |
1192 * Create and return a source representing the given [file] within the given | 1206 * Create and return a source representing the given [file] within the given |
1193 * [context]. | 1207 * [context]. |
1194 */ | 1208 */ |
1195 static Source createSourceInContext(AnalysisContext context, File file) { | 1209 static Source createSourceInContext(AnalysisContext context, File file) { |
1196 // TODO(brianwilkerson) Optimize this, by allowing support for source | 1210 // TODO(brianwilkerson) Optimize this, by allowing support for source |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1352 PackagesFileDisposition(this.packages) {} | 1366 PackagesFileDisposition(this.packages) {} |
1353 | 1367 |
1354 @override | 1368 @override |
1355 String get packageRoot => null; | 1369 String get packageRoot => null; |
1356 | 1370 |
1357 @override | 1371 @override |
1358 Iterable<UriResolver> createPackageUriResolvers( | 1372 Iterable<UriResolver> createPackageUriResolvers( |
1359 ResourceProvider resourceProvider) => | 1373 ResourceProvider resourceProvider) => |
1360 const <UriResolver>[]; | 1374 const <UriResolver>[]; |
1361 } | 1375 } |
OLD | NEW |