summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
authorSiva Velusamy <vsiva@google.com>2014-08-05 17:46:09 -0700
committerSiva Velusamy <vsiva@google.com>2014-08-05 17:56:24 -0700
commit261b2fe692c401e9b79619a7b89a4d688f6b92ed (patch)
treeb8ba797f49f81560825e75a858dd3d1f0d874d24 /android
parent87d28ed8e3100d8e2287069c6544a67a0379dc3c (diff)
downloadidea-261b2fe692c401e9b79619a7b89a4d688f6b92ed.tar.gz
navigator: Handle overlapping source sets
Gradle projects, especially those migrated from Eclipse contain overlapping source sets for different source types. e.g.: java.srcDirs = ['src'] aidl.srcDirs = ['src'] resources.srcDirs = ['src', 'resources'] Currently, this will show up as separate nodes (java, aidl and resources), with all of them showing the sources within their source folders. This is not only odd, but causes issues where the navigator would expand multiple nodes seemingly randomly when expanding a particular node. This happens because we have a single folder present in multiple locations inside the tree. This CL improves this scenario by: - If the source roots for a particular source type is a subset of a previously shown source type's roots, then we just don't show this source type. e.g. in the above case, we don't show aidl at all since it is completely present inside java. - If the set of source roots is an improper subset, we only show those folders that have not already been shown. In the above example, for resources, we only show the contents of the 'resources' folder and not the 'src' folder. Fixes https://code.google.com/p/android/issues/detail?id=74243 and https://code.google.com/p/android/issues/detail?id=73928 Change-Id: I4a9c056e96096d6bf29239e5da41fca1746eb70e
Diffstat (limited to 'android')
-rw-r--r--android/src/com/android/tools/idea/navigator/AndroidProjectViewPane.java8
-rw-r--r--android/src/com/android/tools/idea/navigator/nodes/AndroidManifestFileNode.java24
-rw-r--r--android/src/com/android/tools/idea/navigator/nodes/AndroidManifestsGroupNode.java25
-rw-r--r--android/src/com/android/tools/idea/navigator/nodes/AndroidModuleNode.java58
-rw-r--r--android/src/com/android/tools/idea/navigator/nodes/AndroidResFileNode.java10
-rw-r--r--android/src/com/android/tools/idea/navigator/nodes/AndroidResFolderNode.java8
-rw-r--r--android/src/com/android/tools/idea/navigator/nodes/AndroidResFolderTypeNode.java16
-rw-r--r--android/src/com/android/tools/idea/navigator/nodes/AndroidResGroupNode.java8
-rw-r--r--android/src/com/android/tools/idea/navigator/nodes/AndroidSourceTypeNode.java55
-rw-r--r--android/testData/projects/navigator/packageview/commonroots/AndroidManifest.xml21
-rw-r--r--android/testData/projects/navigator/packageview/commonroots/build.gradle51
-rw-r--r--android/testData/projects/navigator/packageview/commonroots/res/values-w820dp/dimens.xml6
-rw-r--r--android/testData/projects/navigator/packageview/commonroots/resources/sample_resource.txt0
-rw-r--r--android/testData/projects/navigator/packageview/commonroots/src/com/foo/Foo.java0
-rw-r--r--android/testSrc/com/android/tools/idea/navigator/AndroidProjectViewTest.java36
15 files changed, 227 insertions, 99 deletions
diff --git a/android/src/com/android/tools/idea/navigator/AndroidProjectViewPane.java b/android/src/com/android/tools/idea/navigator/AndroidProjectViewPane.java
index 230d1e2dc16..30561d8d7ce 100644
--- a/android/src/com/android/tools/idea/navigator/AndroidProjectViewPane.java
+++ b/android/src/com/android/tools/idea/navigator/AndroidProjectViewPane.java
@@ -47,6 +47,7 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.search.GlobalSearchScope;
import icons.AndroidIcons;
import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.android.facet.IdeaSourceProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -88,6 +89,13 @@ public class AndroidProjectViewPane extends AbstractProjectViewPSIPane {
return 142;
}
+ @NotNull
+ public static List<IdeaSourceProvider> getSourceProviders(@NotNull AndroidFacet facet) {
+ List<IdeaSourceProvider> sourceProviders = IdeaSourceProvider.getCurrentSourceProviders(facet);
+ sourceProviders.addAll(IdeaSourceProvider.getCurrentTestSourceProviders(facet));
+ return sourceProviders;
+ }
+
@Override
public SelectInTarget createSelectInTarget() {
return new ProjectPaneSelectInTarget(myProject);
diff --git a/android/src/com/android/tools/idea/navigator/nodes/AndroidManifestFileNode.java b/android/src/com/android/tools/idea/navigator/nodes/AndroidManifestFileNode.java
index 97444e0c145..13b460d7311 100644
--- a/android/src/com/android/tools/idea/navigator/nodes/AndroidManifestFileNode.java
+++ b/android/src/com/android/tools/idea/navigator/nodes/AndroidManifestFileNode.java
@@ -16,7 +16,9 @@
package com.android.tools.idea.navigator.nodes;
import com.android.SdkConstants;
+import com.android.tools.idea.navigator.AndroidProjectViewPane;
import com.intellij.ide.projectView.PresentationData;
+import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.projectView.impl.nodes.PsiFileNode;
import com.intellij.ide.util.treeView.AbstractTreeNode;
@@ -31,16 +33,13 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class AndroidManifestFileNode extends PsiFileNode implements AndroidProjectViewNode {
- @NotNull private final IdeaSourceProvider mySourceProvider;
@NotNull private final AndroidFacet myFacet;
public AndroidManifestFileNode(@NotNull Project project,
@NotNull PsiFile psiFile,
@NotNull ViewSettings settings,
- @NotNull IdeaSourceProvider provider,
- AndroidFacet facet) {
+ @NotNull AndroidFacet facet) {
super(project, psiFile, settings);
- mySourceProvider = provider;
myFacet = facet;
}
@@ -49,14 +48,25 @@ public class AndroidManifestFileNode extends PsiFileNode implements AndroidProje
super.update(data);
// if it is not part of the main source set, then append the provider name
- if (!SdkConstants.FD_MAIN.equals(mySourceProvider.getName())) {
+ IdeaSourceProvider sourceProvider = getSourceProvider(getValue());
+ if (sourceProvider != null && !SdkConstants.FD_MAIN.equals(sourceProvider.getName())) {
PsiFile file = getValue();
data.addText(file.getName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
- data.addText(" (" + mySourceProvider.getName() + ")", SimpleTextAttributes.GRAY_ATTRIBUTES);
+ data.addText(" (" + sourceProvider.getName() + ")", SimpleTextAttributes.GRAY_ATTRIBUTES);
data.setPresentableText(file.getName());
}
}
+ @Nullable
+ private IdeaSourceProvider getSourceProvider(@NotNull PsiFile file) {
+ for (IdeaSourceProvider provider : AndroidProjectViewPane.getSourceProviders(myFacet)) {
+ if (file.getVirtualFile().equals(provider.getManifestFile())) {
+ return provider;
+ }
+ }
+ return null;
+ }
+
@NotNull
@Override
public AndroidFacet getAndroidFacet() {
@@ -76,7 +86,7 @@ public class AndroidManifestFileNode extends PsiFileNode implements AndroidProje
PsiFile file = getValue();
sb.append(file.getName());
sb.append(" (");
- sb.append(mySourceProvider.getName());
+ sb.append(getSourceProvider(getValue()).getName());
sb.append(")");
return sb.toString();
}
diff --git a/android/src/com/android/tools/idea/navigator/nodes/AndroidManifestsGroupNode.java b/android/src/com/android/tools/idea/navigator/nodes/AndroidManifestsGroupNode.java
index 15d39e18ed7..81bce3709f9 100644
--- a/android/src/com/android/tools/idea/navigator/nodes/AndroidManifestsGroupNode.java
+++ b/android/src/com/android/tools/idea/navigator/nodes/AndroidManifestsGroupNode.java
@@ -29,35 +29,29 @@ import com.intellij.psi.PsiManager;
import com.intellij.ui.SimpleTextAttributes;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidSourceType;
-import org.jetbrains.android.facet.IdeaSourceProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
public class AndroidManifestsGroupNode extends ProjectViewNode<AndroidFacet> implements AndroidProjectViewNode {
private static final String MANIFESTS_NODE = "manifests";
- @NotNull private final List<IdeaSourceProvider> mySourceProviders;
+ @NotNull private final Set<VirtualFile> mySources;
protected AndroidManifestsGroupNode(@NotNull Project project,
@NotNull AndroidFacet facet,
@NotNull ViewSettings viewSettings,
- @NotNull List<IdeaSourceProvider> sourceProviders) {
+ @NotNull Set<VirtualFile> sources) {
super(project, facet, viewSettings);
- mySourceProviders = sourceProviders;
+ mySources = sources;
}
@Override
public boolean contains(@NotNull VirtualFile file) {
- for (IdeaSourceProvider provider : mySourceProviders) {
- VirtualFile manifestFile = provider.getManifestFile();
- if (file.equals(manifestFile)) {
- return true;
- }
- }
- return false;
+ return mySources.contains(file);
}
@NotNull
@@ -66,15 +60,10 @@ public class AndroidManifestsGroupNode extends ProjectViewNode<AndroidFacet> imp
PsiManager psiManager = PsiManager.getInstance(myProject);
List<AbstractTreeNode> children = Lists.newArrayList();
- for (IdeaSourceProvider provider : mySourceProviders) {
- VirtualFile manifest = provider.getManifestFile();
- if (manifest == null) {
- continue;
- }
-
+ for (VirtualFile manifest : mySources) {
PsiFile psiFile = psiManager.findFile(manifest);
if (psiFile != null) {
- children.add(new AndroidManifestFileNode(myProject, psiFile, getSettings(), provider, getValue()));
+ children.add(new AndroidManifestFileNode(myProject, psiFile, getSettings(), getValue()));
}
}
return children;
diff --git a/android/src/com/android/tools/idea/navigator/nodes/AndroidModuleNode.java b/android/src/com/android/tools/idea/navigator/nodes/AndroidModuleNode.java
index d90ad66b52c..a4f41087ece 100644
--- a/android/src/com/android/tools/idea/navigator/nodes/AndroidModuleNode.java
+++ b/android/src/com/android/tools/idea/navigator/nodes/AndroidModuleNode.java
@@ -16,7 +16,11 @@
package com.android.tools.idea.navigator.nodes;
import com.android.tools.idea.navigator.AndroidProjectViewPane;
+import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.intellij.codeInsight.dataflow.SetUtil;
+import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode;
import com.intellij.ide.util.treeView.AbstractTreeNode;
@@ -32,6 +36,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
/**
* {@link com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode} does not classify source types, and just assumes that all source
@@ -58,9 +63,7 @@ public class AndroidModuleNode extends PackageViewModuleNode {
return super.getChildren();
}
- List<IdeaSourceProvider> sourceProviders = IdeaSourceProvider.getCurrentSourceProviders(facet);
- sourceProviders.addAll(IdeaSourceProvider.getCurrentTestSourceProviders(facet));
- return getChildren(facet, getSettings(), myProjectViewPane, sourceProviders);
+ return getChildren(facet, getSettings(), myProjectViewPane, AndroidProjectViewPane.getSourceProviders(facet));
}
public static Collection<AbstractTreeNode> getChildren(AndroidFacet facet,
@@ -70,29 +73,58 @@ public class AndroidModuleNode extends PackageViewModuleNode {
Project project = facet.getModule().getProject();
List<AbstractTreeNode> result = Lists.newArrayList();
- for (AndroidSourceType sourceType : AndroidSourceType.values()) {
- List<VirtualFile> sources = getSources(sourceType, providers);
- if (sources.isEmpty()) {
- continue;
- }
+ HashMultimap<AndroidSourceType,VirtualFile> sourcesByType = getSourcesBySourceType(providers);
+ for (AndroidSourceType sourceType : sourcesByType.keySet()) {
if (sourceType == AndroidSourceType.MANIFEST) {
- result.add(new AndroidManifestsGroupNode(project, facet, settings, providers));
+ result.add(new AndroidManifestsGroupNode(project, facet, settings, sourcesByType.get(sourceType)));
}
else if (sourceType == AndroidSourceType.RES) {
- result.add(new AndroidResFolderNode(project, facet, settings, providers, pane));
+ result.add(new AndroidResFolderNode(project, facet, settings, sourcesByType.get(sourceType), pane));
}
else {
- result.add(new AndroidSourceTypeNode(project, facet, settings, sourceType, providers, pane));
+ result.add(new AndroidSourceTypeNode(project, facet, settings, sourceType, sourcesByType.get(sourceType), pane));
}
}
return result;
}
+ private static HashMultimap<AndroidSourceType,VirtualFile> getSourcesBySourceType(List<IdeaSourceProvider> providers) {
+ HashMultimap<AndroidSourceType,VirtualFile> sourcesByType = HashMultimap.create();
+
+ // Multiple source types can sometimes be present in the same source folder, e.g.:
+ // sourcesSets.main.java.srcDirs = sourceSets.main.aidl.srcDirs = ['src']
+ // in such a case, we only want to show one of them. Source sets can be either proper or improper subsets. It is not entirely
+ // obvious there is a perfect solution here, but since this is not a common occurence, we resort to the easiest solution here:
+ // If a set of sources has partially been included as part of another source type's source set, then we simply don't include it
+ // as part of this source type.
+ Set<VirtualFile> allSources = Sets.newHashSet();
+
+ for (AndroidSourceType sourceType : AndroidSourceType.values()) {
+ Set<VirtualFile> sources = getSources(sourceType, providers);
+ if (sources.isEmpty()) {
+ continue;
+ }
+
+ if (SetUtil.intersect(allSources, sources).isEmpty()) {
+ // if we haven't seen any of these source folders, then create a new source type folder
+ sourcesByType.putAll(sourceType, sources);
+ } else if (!allSources.containsAll(sources)) {
+ // if we have a partial overlap, we put just the non overlapping sources into this source type
+ sources.removeAll(allSources);
+ sourcesByType.putAll(sourceType, sources);
+ }
+
+ allSources.addAll(sources);
+ }
+
+ return sourcesByType;
+ }
+
@NotNull
- private static List<VirtualFile> getSources(AndroidSourceType sourceType, Iterable<IdeaSourceProvider> providers) {
- List<VirtualFile> sources = Lists.newArrayList();
+ private static Set<VirtualFile> getSources(AndroidSourceType sourceType, Iterable<IdeaSourceProvider> providers) {
+ Set<VirtualFile> sources = Sets.newHashSet();
for (IdeaSourceProvider provider : providers) {
sources.addAll(sourceType.getSources(provider));
diff --git a/android/src/com/android/tools/idea/navigator/nodes/AndroidResFileNode.java b/android/src/com/android/tools/idea/navigator/nodes/AndroidResFileNode.java
index b9ecbe02802..bd47d7327c9 100644
--- a/android/src/com/android/tools/idea/navigator/nodes/AndroidResFileNode.java
+++ b/android/src/com/android/tools/idea/navigator/nodes/AndroidResFileNode.java
@@ -17,6 +17,7 @@ package com.android.tools.idea.navigator.nodes;
import com.android.SdkConstants;
import com.android.resources.ResourceConstants;
+import com.android.tools.idea.navigator.AndroidProjectViewPane;
import com.google.common.base.Joiner;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.ide.projectView.ViewSettings;
@@ -26,6 +27,7 @@ import com.intellij.openapi.ui.Queryable;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.ui.SimpleTextAttributes;
+import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.IdeaSourceProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,14 +35,14 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
public class AndroidResFileNode extends PsiFileNode {
- private final List<IdeaSourceProvider> mySourceProviders;
+ private final AndroidFacet myFacet;
public AndroidResFileNode(@NotNull Project project,
@NotNull PsiFile psiFile,
@NotNull ViewSettings settings,
- @NotNull List<IdeaSourceProvider> sourceProviders) {
+ @NotNull AndroidFacet facet) {
super(project, psiFile, settings);
- mySourceProviders = sourceProviders;
+ myFacet = facet;
}
@Override
@@ -105,7 +107,7 @@ public class AndroidResFileNode extends PsiFileNode {
@Nullable
private IdeaSourceProvider findSourceProviderForResFolder(@NotNull PsiDirectory resDirectory) {
- for (IdeaSourceProvider provider : mySourceProviders) {
+ for (IdeaSourceProvider provider : AndroidProjectViewPane.getSourceProviders(myFacet)) {
if (provider.getResDirectories().contains(resDirectory.getVirtualFile())) {
return provider;
}
diff --git a/android/src/com/android/tools/idea/navigator/nodes/AndroidResFolderNode.java b/android/src/com/android/tools/idea/navigator/nodes/AndroidResFolderNode.java
index 6d494930293..cfee1df830b 100644
--- a/android/src/com/android/tools/idea/navigator/nodes/AndroidResFolderNode.java
+++ b/android/src/com/android/tools/idea/navigator/nodes/AndroidResFolderNode.java
@@ -23,6 +23,7 @@ import com.google.common.collect.Lists;
import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidSourceType;
@@ -37,9 +38,9 @@ public class AndroidResFolderNode extends AndroidSourceTypeNode {
public AndroidResFolderNode(@NotNull Project project,
@NotNull AndroidFacet facet,
@NotNull ViewSettings viewSettings,
- @NotNull List<IdeaSourceProvider> sourceProviders,
+ @NotNull Set<VirtualFile> sourceRoots,
@NotNull AndroidProjectViewPane projectViewPane) {
- super(project, facet, viewSettings, AndroidSourceType.RES, sourceProviders, projectViewPane);
+ super(project, facet, viewSettings, AndroidSourceType.RES, sourceRoots, projectViewPane);
}
/**
@@ -68,8 +69,7 @@ public class AndroidResFolderNode extends AndroidSourceTypeNode {
for (ResourceFolderType type : foldersByResourceType.keySet()) {
Set<PsiDirectory> folders = foldersByResourceType.get(type);
final AndroidResFolderTypeNode androidResFolderTypeNode =
- new AndroidResFolderTypeNode(myProject, getValue(), Lists.newArrayList(folders), getSettings(), type, mySourceProviders,
- myProjectViewPane);
+ new AndroidResFolderTypeNode(myProject, getValue(), Lists.newArrayList(folders), getSettings(), type, myProjectViewPane);
children.add(androidResFolderTypeNode);
// Inform the tree builder of the node that this particular virtual file maps to
diff --git a/android/src/com/android/tools/idea/navigator/nodes/AndroidResFolderTypeNode.java b/android/src/com/android/tools/idea/navigator/nodes/AndroidResFolderTypeNode.java
index 0314b40a8a1..cf068ab167e 100644
--- a/android/src/com/android/tools/idea/navigator/nodes/AndroidResFolderTypeNode.java
+++ b/android/src/com/android/tools/idea/navigator/nodes/AndroidResFolderTypeNode.java
@@ -17,7 +17,9 @@ package com.android.tools.idea.navigator.nodes;
import com.android.resources.ResourceFolderType;
import com.android.tools.idea.navigator.AndroidProjectViewPane;
-import com.google.common.collect.*;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.ide.projectView.ProjectViewNode;
import com.intellij.ide.projectView.ViewSettings;
@@ -30,22 +32,16 @@ import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.PlatformIcons;
-import com.intellij.util.containers.ContainerUtil;
-import com.siyeh.ig.psiutils.IteratorUtils;
import org.jetbrains.android.facet.AndroidFacet;
-import org.jetbrains.android.facet.IdeaSourceProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
public class AndroidResFolderTypeNode extends ProjectViewNode<List<PsiDirectory>> implements AndroidProjectViewNode {
@NotNull private final AndroidFacet myFacet;
@NotNull private final ResourceFolderType myFolderType;
- @NotNull private final List<IdeaSourceProvider> mySourceProviders;
@NotNull private final AndroidProjectViewPane myProjectViewPane;
public AndroidResFolderTypeNode(@NotNull Project project,
@@ -53,12 +49,10 @@ public class AndroidResFolderTypeNode extends ProjectViewNode<List<PsiDirectory>
@NotNull List<PsiDirectory> folders,
@NotNull ViewSettings settings,
@NotNull ResourceFolderType folderType,
- @NotNull List<IdeaSourceProvider> sourceProviders,
@NotNull AndroidProjectViewPane projectViewPane) {
super(project, folders, settings);
myFacet = facet;
myFolderType = folderType;
- mySourceProviders = sourceProviders;
myProjectViewPane = projectViewPane;
}
@@ -105,9 +99,9 @@ public class AndroidResFolderTypeNode extends ProjectViewNode<List<PsiDirectory>
for (String resName : multimap.keySet()) {
List<PsiFile> files = Lists.newArrayList(multimap.get(resName));
if (files.size() > 1) {
- children.add(new AndroidResGroupNode(myProject, myFacet, files, resName, getSettings(), mySourceProviders));
+ children.add(new AndroidResGroupNode(myProject, myFacet, files, resName, getSettings()));
} else {
- children.add(new AndroidResFileNode(myProject, files.get(0), getSettings(), mySourceProviders));
+ children.add(new AndroidResFileNode(myProject, files.get(0), getSettings(), myFacet));
}
}
return children;
diff --git a/android/src/com/android/tools/idea/navigator/nodes/AndroidResGroupNode.java b/android/src/com/android/tools/idea/navigator/nodes/AndroidResGroupNode.java
index e93fa1be3f4..32b57a140ac 100644
--- a/android/src/com/android/tools/idea/navigator/nodes/AndroidResGroupNode.java
+++ b/android/src/com/android/tools/idea/navigator/nodes/AndroidResGroupNode.java
@@ -29,7 +29,6 @@ import com.intellij.psi.PsiFile;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.PlatformIcons;
import org.jetbrains.android.facet.AndroidFacet;
-import org.jetbrains.android.facet.IdeaSourceProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,19 +40,16 @@ public class AndroidResGroupNode extends ProjectViewNode<List<PsiFile>> implemen
@NotNull private final String myResName;
@NotNull private final AndroidFacet myFacet;
@NotNull private final List<PsiFile> myFiles;
- @NotNull private final List<IdeaSourceProvider> mySourceProviders;
public AndroidResGroupNode(@NotNull Project project,
@NotNull AndroidFacet facet,
@NotNull List<PsiFile> files,
@NotNull String resName,
- @NotNull ViewSettings settings,
- List<IdeaSourceProvider> sourceProviders) {
+ @NotNull ViewSettings settings) {
super(project, files, settings);
myResName = resName;
myFacet = facet;
myFiles = files;
- mySourceProviders = sourceProviders;
}
@NotNull
@@ -89,7 +85,7 @@ public class AndroidResGroupNode extends ProjectViewNode<List<PsiFile>> implemen
public Collection<? extends AbstractTreeNode> getChildren() {
List<PsiFileNode> children = Lists.newArrayListWithExpectedSize(myFiles.size());
for (PsiFile file : myFiles) {
- children.add(new AndroidResFileNode(myProject, file, getSettings(), mySourceProviders));
+ children.add(new AndroidResFileNode(myProject, file, getSettings(), myFacet));
}
return children;
}
diff --git a/android/src/com/android/tools/idea/navigator/nodes/AndroidSourceTypeNode.java b/android/src/com/android/tools/idea/navigator/nodes/AndroidSourceTypeNode.java
index 0f0959d7565..45cac1e5c4f 100644
--- a/android/src/com/android/tools/idea/navigator/nodes/AndroidSourceTypeNode.java
+++ b/android/src/com/android/tools/idea/navigator/nodes/AndroidSourceTypeNode.java
@@ -18,7 +18,6 @@ package com.android.tools.idea.navigator.nodes;
import com.android.tools.idea.navigator.AndroidProjectTreeBuilder;
import com.android.tools.idea.navigator.AndroidProjectViewPane;
import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.ide.projectView.ProjectViewNode;
import com.intellij.ide.projectView.ViewSettings;
@@ -27,7 +26,6 @@ import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Queryable;
-import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
@@ -50,18 +48,18 @@ import java.util.Set;
*/
public class AndroidSourceTypeNode extends ProjectViewNode<AndroidFacet> implements AndroidProjectViewNode {
@NotNull private final AndroidSourceType mySourceType;
- @NotNull protected final List<IdeaSourceProvider> mySourceProviders;
+ @NotNull private final Set<VirtualFile> mySourceRoots;
@NotNull protected final AndroidProjectViewPane myProjectViewPane;
public AndroidSourceTypeNode(@NotNull Project project,
@NotNull AndroidFacet facet,
@NotNull ViewSettings viewSettings,
@NotNull AndroidSourceType sourceType,
- @NotNull List<IdeaSourceProvider> sourceProviders,
+ @NotNull Set<VirtualFile> sources,
@NotNull AndroidProjectViewPane projectViewPane) {
super(project, facet, viewSettings);
mySourceType = sourceType;
- mySourceProviders = sourceProviders;
+ mySourceRoots = sources;
myProjectViewPane = projectViewPane;
}
@@ -94,7 +92,7 @@ public class AndroidSourceTypeNode extends ProjectViewNode<AndroidFacet> impleme
for (AbstractTreeNode child : directoryChildren) {
if (child instanceof PsiDirectoryNode) {
PsiDirectory directory = ((PsiDirectoryNode)child).getValue();
- children.add(new AndroidPsiDirectoryNode(myProject, directory, getSettings(), findSourceProvider(directory.getVirtualFile())));
+ children.add(new AndroidPsiDirectoryNode(myProject, directory, getSettings(), findJavaSourceProvider(directory.getVirtualFile())));
} else {
children.add(child);
}
@@ -104,8 +102,8 @@ public class AndroidSourceTypeNode extends ProjectViewNode<AndroidFacet> impleme
}
@Nullable
- private IdeaSourceProvider findSourceProvider(VirtualFile virtualFile) {
- for (IdeaSourceProvider provider : mySourceProviders) {
+ private IdeaSourceProvider findJavaSourceProvider(VirtualFile virtualFile) {
+ for (IdeaSourceProvider provider : AndroidProjectViewPane.getSourceProviders(getValue())) {
if (provider.containsFile(virtualFile)) {
return provider;
}
@@ -116,14 +114,12 @@ public class AndroidSourceTypeNode extends ProjectViewNode<AndroidFacet> impleme
protected List<PsiDirectory> getSourceDirectories() {
PsiManager psiManager = PsiManager.getInstance(myProject);
- List<PsiDirectory> psiDirectories = Lists.newArrayList();
-
- for (IdeaSourceProvider sourceProvider : mySourceProviders) {
- for (VirtualFile file : mySourceType.getSources(sourceProvider)) {
- final PsiDirectory directory = psiManager.findDirectory(file);
- if (directory != null) {
- psiDirectories.add(directory);
- }
+ List<PsiDirectory> psiDirectories = Lists.newArrayListWithExpectedSize(mySourceRoots.size());
+
+ for (VirtualFile root : mySourceRoots) {
+ final PsiDirectory directory = psiManager.findDirectory(root);
+ if (directory != null) {
+ psiDirectories.add(directory);
}
}
@@ -151,11 +147,9 @@ public class AndroidSourceTypeNode extends ProjectViewNode<AndroidFacet> impleme
public boolean contains(@NotNull VirtualFile file) {
//TODO: first check if the file is of my source type
- for (IdeaSourceProvider sourceProvider : mySourceProviders) {
- for (VirtualFile folder : mySourceType.getSources(sourceProvider)) {
- if (VfsUtilCore.isAncestor(folder, file, false)) {
- return true;
- }
+ for (VirtualFile root : mySourceRoots) {
+ if (VfsUtilCore.isAncestor(root, file, false)) {
+ return true;
}
}
@@ -177,15 +171,15 @@ public class AndroidSourceTypeNode extends ProjectViewNode<AndroidFacet> impleme
AndroidSourceTypeNode that = (AndroidSourceTypeNode)o;
if (mySourceType != that.mySourceType) return false;
- return mySourceProviders.equals(that.mySourceProviders);
+ return mySourceRoots.equals(that.mySourceRoots);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + mySourceType.hashCode();
- for (IdeaSourceProvider provider : mySourceProviders) {
- result = 31 * result + provider.hashCode();
+ for (VirtualFile root : mySourceRoots) {
+ result = 31 * result + root.hashCode();
}
return result;
}
@@ -199,18 +193,7 @@ public class AndroidSourceTypeNode extends ProjectViewNode<AndroidFacet> impleme
@NotNull
@Override
public PsiDirectory[] getDirectories() {
- PsiManager psiManager = PsiManager.getInstance(myProject);
- Set<PsiDirectory> folders = Sets.newHashSet();
-
- for (IdeaSourceProvider provider : mySourceProviders) {
- for (VirtualFile vf : mySourceType.getSources(provider)) {
- PsiDirectory folder = psiManager.findDirectory(vf);
- if (folder != null) {
- folders.add(folder);
- }
- }
- }
-
+ List<PsiDirectory> folders = getSourceDirectories();
return folders.toArray(new PsiDirectory[folders.size()]);
}
}
diff --git a/android/testData/projects/navigator/packageview/commonroots/AndroidManifest.xml b/android/testData/projects/navigator/packageview/commonroots/AndroidManifest.xml
new file mode 100644
index 00000000000..0af21be139a
--- /dev/null
+++ b/android/testData/projects/navigator/packageview/commonroots/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.canon.app" >
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="com.example.canon.app.MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/android/testData/projects/navigator/packageview/commonroots/build.gradle b/android/testData/projects/navigator/packageview/commonroots/build.gradle
new file mode 100644
index 00000000000..e3930be2dd5
--- /dev/null
+++ b/android/testData/projects/navigator/packageview/commonroots/build.gradle
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+buildscript {
+ repositories {
+ mavenCentral()
+ if (System.getenv("MAVEN_URL") != null) {
+ maven {url System.getenv("MAVEN_URL")}
+ }
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:0.12.+'
+ }
+}
+
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 19
+ buildToolsVersion '19.1.0'
+
+ defaultConfig {
+ minSdkVersion 14
+ targetSdkVersion 19
+ versionCode 10
+ versionName "1.0"
+ }
+
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src']
+ aidl.srcDirs = ['src']
+ resources.srcDirs = ['src', 'resources']
+ res.srcDirs = ['res']
+ }
+ }
+} \ No newline at end of file
diff --git a/android/testData/projects/navigator/packageview/commonroots/res/values-w820dp/dimens.xml b/android/testData/projects/navigator/packageview/commonroots/res/values-w820dp/dimens.xml
new file mode 100644
index 00000000000..63fc8164446
--- /dev/null
+++ b/android/testData/projects/navigator/packageview/commonroots/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+<resources>
+ <!-- Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+</resources>
diff --git a/android/testData/projects/navigator/packageview/commonroots/resources/sample_resource.txt b/android/testData/projects/navigator/packageview/commonroots/resources/sample_resource.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/android/testData/projects/navigator/packageview/commonroots/resources/sample_resource.txt
diff --git a/android/testData/projects/navigator/packageview/commonroots/src/com/foo/Foo.java b/android/testData/projects/navigator/packageview/commonroots/src/com/foo/Foo.java
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/android/testData/projects/navigator/packageview/commonroots/src/com/foo/Foo.java
diff --git a/android/testSrc/com/android/tools/idea/navigator/AndroidProjectViewTest.java b/android/testSrc/com/android/tools/idea/navigator/AndroidProjectViewTest.java
index 054d6587e59..67855adbe2b 100644
--- a/android/testSrc/com/android/tools/idea/navigator/AndroidProjectViewTest.java
+++ b/android/testSrc/com/android/tools/idea/navigator/AndroidProjectViewTest.java
@@ -114,6 +114,42 @@ public class AndroidProjectViewTest extends AndroidGradleTestCase {
printInfo);
}
+ public void testCommonRoots() throws Exception {
+ loadProject("projects/navigator/packageview/commonroots");
+
+ myPane = createPane();
+ TestAndroidTreeStructure structure = new TestAndroidTreeStructure(getProject(), myTestRootDisposable);
+
+ Queryable.PrintInfo printInfo = new Queryable.PrintInfo();
+ PsiDirectory dir = getBaseFolder();
+ assertNotNull(dir);
+
+ Module[] modules = ModuleManager.getInstance(getProject()).getModules();
+ assertEquals(1, modules.length);
+
+ String projectName = getProject().getName();
+ String expected =
+ projectName + "\n" +
+ " Gradle Scripts\n" +
+ " build.gradle (" + modules[0].getName() + ")\n" +
+ " gradle-wrapper.properties\n" +
+ " " + modules[0].getName() + " (Android)\n" +
+ " java\n" +
+ " foo (main)\n" +
+ " Foo.java\n" +
+ " manifests\n" +
+ " AndroidManifest.xml (main)\n" +
+ " res\n" +
+ " values\n" +
+ " dimens.xml (w820dp)\n" +
+ " resources\n" +
+ " sample_resource.txt\n";
+ int numLines = expected.split("\n").length;
+ ProjectViewTestUtil
+ .assertStructureEqual(structure, expected, numLines, PlatformTestUtil.createComparator(printInfo), structure.getRootElement(),
+ printInfo);
+ }
+
@Nullable
private PsiDirectory getBaseFolder() throws Exception {
VirtualFile folder = getProject().getBaseDir();