Module Search Scopes use OrderEnumerator

This commit is contained in:
Anton Makeev
2010-12-23 14:53:40 +03:00
parent fe52b19f35
commit e88d4eae81
13 changed files with 647 additions and 473 deletions
@@ -78,7 +78,7 @@ public class DependencyScopeTest extends ModuleTestCase {
public void testTestOnlyLibraryDependency() throws IOException {
Module m = createModule("a.iml", StdModuleTypes.JAVA);
addLibrary(m, DependencyScope.TEST);
VirtualFile libraryClass = myFixture.createFile("lib/Test.java", "public class Test { }");
VirtualFile libraryClass = myFixture.createFile("lib/Test.class");
assertTrue(m.getModuleWithDependenciesAndLibrariesScope(true).contains(libraryClass));
assertFalse(m.getModuleWithDependenciesAndLibrariesScope(false).contains(libraryClass));
@@ -112,9 +112,12 @@ public class DependencyScopeTest extends ModuleTestCase {
VirtualFile[] production = getProductionCompileClasspath(m);
assertEmpty(production);
VirtualFile libraryClass = myFixture.createFile("lib/Test.java", "public class Test { }");
assertTrue(m.getModuleWithDependenciesAndLibrariesScope(true).contains(libraryClass));
VirtualFile libraryClass = myFixture.createFile("lib/Test.class");
assertFalse(m.getModuleWithDependenciesAndLibrariesScope(true).contains(libraryClass));
assertFalse(m.getModuleWithDependenciesAndLibrariesScope(false).contains(libraryClass));
assertTrue(m.getModuleRuntimeScope(true).contains(libraryClass));
assertTrue(m.getModuleRuntimeScope(false).contains(libraryClass));
}
public void testProvidedModuleDependency() throws IOException {
@@ -136,9 +139,12 @@ public class DependencyScopeTest extends ModuleTestCase {
final VirtualFile[] compilationClasspath = getCompilationClasspath(m);
assertOrderedEquals(compilationClasspath, libraryRoot);
VirtualFile libraryClass = myFixture.createFile("lib/Test.java", "public class Test { }");
VirtualFile libraryClass = myFixture.createFile("lib/Test.class");
assertTrue(m.getModuleWithDependenciesAndLibrariesScope(true).contains(libraryClass));
assertTrue(m.getModuleWithDependenciesAndLibrariesScope(false).contains(libraryClass));
assertTrue(m.getModuleRuntimeScope(true).contains(libraryClass));
assertFalse(m.getModuleRuntimeScope(false).contains(libraryClass));
}
private static VirtualFile[] getRuntimeClasspath(Module m) {
@@ -47,7 +47,9 @@ public abstract class OrderEnumerationHandler {
return true;
}
public boolean addCustomOutput(@NotNull ModuleOrderEntry orderEntry,
public boolean addCustomOutput(@NotNull Module forModule,
@NotNull ModuleRootModel orderEntryRootModel,
OrderRootType type,
boolean productionOnly,
boolean runtimeOnly,
boolean compileOnly,
@@ -21,6 +21,7 @@ import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.NotNullFunction;
import com.intellij.util.PathsList;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
@@ -129,6 +130,12 @@ public abstract class OrderEnumerator {
*/
public abstract OrderRootsEnumerator roots(@NotNull OrderRootType rootType);
/**
* @param rootTypeProvider custom root type provider
* @return {@link OrderRootsEnumerator} instance for processing roots of the provided type
*/
public abstract OrderRootsEnumerator roots(@NotNull NotNullFunction<OrderEntry, OrderRootType> rootTypeProvider);
/**
* @return classes roots for all entries processed by this enumerator
*/
@@ -34,7 +34,7 @@ public abstract class SearchScope {
}
public String getDisplayName() {
return PsiBundle.message("psi.search.scope.unknown");
return PsiBundle.message("search.scope.unknown");
}
@NotNull public abstract SearchScope intersectWith(@NotNull SearchScope scope2);
@@ -31,7 +31,6 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleComponent;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.impl.scopes.ModuleRuntimeClasspathScope;
import com.intellij.openapi.module.impl.scopes.ModuleWithDependenciesScope;
import com.intellij.openapi.module.impl.scopes.ModuleWithDependentsScope;
import com.intellij.openapi.project.Project;
@@ -66,14 +65,14 @@ public class ModuleImpl extends ComponentManagerImpl implements Module {
@NonNls private static final String OPTION_WORKSPACE = "workspace";
@NonNls public static final String ELEMENT_TYPE = "type";
private ModuleWithDependenciesScope myModuleWithLibrariesScope;
private ModuleWithDependenciesScope myModuleWithDependenciesScope;
private ModuleWithDependenciesScope myModuleWithDependenciesAndLibrariesScope;
private ModuleWithDependenciesScope myModuleWithDependenciesAndLibrariesNoTestsScope;
private ModuleWithDependentsScope myModuleWithDependentsScope;
private ModuleWithDependentsScope myModuleTestsWithDependentsScope;
private ModuleRuntimeClasspathScope myModuleTestsRuntimeClasspathScope;
private ModuleRuntimeClasspathScope myModuleRuntimeClasspathScope;
private GlobalSearchScope myModuleWithLibrariesScope;
private GlobalSearchScope myModuleWithDependenciesScope;
private GlobalSearchScope myModuleWithDependenciesAndLibrariesScope;
private GlobalSearchScope myModuleWithDependenciesAndLibrariesNoTestsScope;
private GlobalSearchScope myModuleWithDependentsScope;
private GlobalSearchScope myModuleTestsWithDependentsScope;
private GlobalSearchScope myModuleTestsRuntimeClasspathScope;
private GlobalSearchScope myModuleRuntimeClasspathScope;
public static final Object MODULE_RENAMING_REQUESTOR = new Object();
private String myName;
@@ -105,7 +104,7 @@ public class ModuleImpl extends ComponentManagerImpl implements Module {
myName = moduleNameByFileName(PathUtil.getFileName(filePath));
MyVirtualFileListener myVirtualFileListener = new MyVirtualFileListener();
VirtualFileManager.getInstance().addVirtualFileListener(myVirtualFileListener,this);
VirtualFileManager.getInstance().addVirtualFileListener(myVirtualFileListener, this);
}
public void loadModuleComponents() {
@@ -116,14 +115,14 @@ public class ModuleImpl extends ComponentManagerImpl implements Module {
}
}
protected boolean isComponentSuitable(Map<String,String> options) {
protected boolean isComponentSuitable(Map<String, String> options) {
if (!super.isComponentSuitable(options)) return false;
if (options == null) return true;
Set<String> optionNames = options.keySet();
for (String optionName : optionNames) {
if (Comparing.equal(OPTION_WORKSPACE, optionName)) continue;
if (!parseOptionValue(options.get(optionName)).contains( getOptionValue(optionName))) return false;
if (!parseOptionValue(options.get(optionName)).contains(getOptionValue(optionName))) return false;
}
return true;
@@ -246,7 +245,7 @@ public class ModuleImpl extends ComponentManagerImpl implements Module {
public GlobalSearchScope getModuleScope() {
if (myModuleScope == null) {
myModuleScope = new ModuleWithDependenciesScope(this, false, false, true);
myModuleScope = new ModuleWithDependenciesScope(this, true, false, false, true);
}
return myModuleScope;
@@ -254,14 +253,14 @@ public class ModuleImpl extends ComponentManagerImpl implements Module {
public GlobalSearchScope getModuleWithLibrariesScope() {
if (myModuleWithLibrariesScope == null) {
myModuleWithLibrariesScope = new ModuleWithDependenciesScope(this, true, false, true);
myModuleWithLibrariesScope = new ModuleWithDependenciesScope(this, true, true, false, true);
}
return myModuleWithLibrariesScope;
}
public GlobalSearchScope getModuleWithDependenciesScope() {
if (myModuleWithDependenciesScope == null) {
myModuleWithDependenciesScope = new ModuleWithDependenciesScope(this, false, true, true);
myModuleWithDependenciesScope = new ModuleWithDependenciesScope(this, true, false, true, true);
}
return myModuleWithDependenciesScope;
}
@@ -269,13 +268,13 @@ public class ModuleImpl extends ComponentManagerImpl implements Module {
public GlobalSearchScope getModuleWithDependenciesAndLibrariesScope(boolean includeTests) {
if (includeTests) {
if (myModuleWithDependenciesAndLibrariesScope == null) {
myModuleWithDependenciesAndLibrariesScope = new ModuleWithDependenciesScope(this, true, true, true);
myModuleWithDependenciesAndLibrariesScope = new ModuleWithDependenciesScope(this, true, true, true, true);
}
return myModuleWithDependenciesAndLibrariesScope;
}
else {
if (myModuleWithDependenciesAndLibrariesNoTestsScope == null) {
myModuleWithDependenciesAndLibrariesNoTestsScope = new ModuleWithDependenciesScope(this, true, true, false);
myModuleWithDependenciesAndLibrariesNoTestsScope = new ModuleWithDependenciesScope(this, true, true, true, false);
}
return myModuleWithDependenciesAndLibrariesNoTestsScope;
}
@@ -298,13 +297,13 @@ public class ModuleImpl extends ComponentManagerImpl implements Module {
public GlobalSearchScope getModuleRuntimeScope(boolean includeTests) {
if (includeTests) {
if (myModuleTestsRuntimeClasspathScope == null) {
myModuleTestsRuntimeClasspathScope = new ModuleRuntimeClasspathScope(this, true);
myModuleTestsRuntimeClasspathScope = new ModuleWithDependenciesScope(this, false, true, true, true);
}
return myModuleTestsRuntimeClasspathScope;
}
else {
if (myModuleRuntimeClasspathScope == null) {
myModuleRuntimeClasspathScope = new ModuleRuntimeClasspathScope(this, false);
myModuleRuntimeClasspathScope = new ModuleWithDependenciesScope(this, false, true, true, false);
}
return myModuleRuntimeClasspathScope;
}
@@ -324,7 +323,7 @@ public class ModuleImpl extends ComponentManagerImpl implements Module {
@SuppressWarnings({"HardCodedStringLiteral"})
public String toString() {
if (myName == null) return "Module"; // was called before initialized
return "Module: '" + getName() + "' path: '" + getModuleFilePath()+"'";
return "Module: '" + getName() + "' path: '" + getModuleFilePath() + "'";
}
private static String moduleNameByFileName(@NotNull String fileName) {
@@ -348,12 +347,9 @@ public class ModuleImpl extends ComponentManagerImpl implements Module {
ModuleManagerImpl.getInstanceImpl(getProject()).fireModuleRenamedByVfsEvent(ModuleImpl.this);
}
}
}
protected MutablePicoContainer createPicoContainer() {
return Extensions.getArea(this).getPicoContainer();
}
}
@@ -1,120 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* 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.
*/
package com.intellij.openapi.module.impl.scopes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiBundle;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashSet;
/**
* @author max
*/
public class ModuleRuntimeClasspathScope extends GlobalSearchScope {
private final ProjectFileIndex myIndex;
private final boolean myIncludeTests;
private final LinkedHashSet<VirtualFile> myEntries = new LinkedHashSet<VirtualFile>();
private final Module myModule;
public ModuleRuntimeClasspathScope(final Module module, boolean includeTests) {
super(module.getProject());
myModule = module;
myIndex = ProjectRootManager.getInstance(module.getProject()).getFileIndex();
myIncludeTests = includeTests;
buildEntries(module);
}
public int hashCode() {
return myModule.hashCode();
}
public boolean equals(Object object) {
if (object == this) return true;
if (object.getClass() != ModuleRuntimeClasspathScope.class) return false;
final ModuleRuntimeClasspathScope that = ((ModuleRuntimeClasspathScope)object);
return that.myModule == myModule && that.myIncludeTests == myIncludeTests;
}
private void buildEntries(final Module module) {
ModuleRootManager.getInstance(module).orderEntries().recursively().process(new RootPolicy<LinkedHashSet<VirtualFile>>() {
private boolean myJDKProcessed = false;
public LinkedHashSet<VirtualFile> visitModuleSourceOrderEntry(final ModuleSourceOrderEntry moduleSourceOrderEntry,
final LinkedHashSet<VirtualFile> value) {
ContainerUtil.addAll(value, moduleSourceOrderEntry.getFiles(OrderRootType.SOURCES));
return value;
}
public LinkedHashSet<VirtualFile> visitLibraryOrderEntry(final LibraryOrderEntry libraryOrderEntry,
final LinkedHashSet<VirtualFile> value) {
ContainerUtil.addAll(value, libraryOrderEntry.getRootFiles(OrderRootType.CLASSES));
return value;
}
public LinkedHashSet<VirtualFile> visitJdkOrderEntry(final JdkOrderEntry jdkOrderEntry, final LinkedHashSet<VirtualFile> value) {
if (myJDKProcessed) return value;
myJDKProcessed = true;
ContainerUtil.addAll(value, jdkOrderEntry.getRootFiles(OrderRootType.CLASSES));
return value;
}
}, myEntries);
}
public boolean contains(VirtualFile file) {
if (!myIncludeTests && myIndex.isInTestSourceContent(file)) return false;
return myEntries.contains(getFileRoot(file));
}
private VirtualFile getFileRoot(VirtualFile file) {
if (myIndex.isLibraryClassFile(file)) {
return myIndex.getClassRootForFile(file);
}
if (myIndex.isInContent(file)) {
return myIndex.getSourceRootForFile(file);
}
return null;
}
public int compare(VirtualFile file1, VirtualFile file2) {
final VirtualFile r1 = getFileRoot(file1);
final VirtualFile r2 = getFileRoot(file2);
for (VirtualFile root : myEntries) {
if (r1 == root) return 1;
if (r2 == root) return -1;
}
return 0;
}
public boolean isSearchInModuleContent(@NotNull Module aModule) {
return true;
}
public boolean isSearchInLibraries() {
return true;
}
public String getDisplayName() {
return PsiBundle.message("runtime.scope.display.name", myModule.getName());
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,189 +15,174 @@
*/
package com.intellij.openapi.module.impl.scopes;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiBundle;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import com.intellij.util.NotNullFunction;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* @author max
*/
public class ModuleWithDependenciesScope extends GlobalSearchScope {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.module.impl.scopes.ModuleWithDependenciesScope");
private final Module myModule;
private final boolean myCompileClasspath;
private final boolean myIncludeLibraries;
private final boolean myIncludeOtherModules;
private final boolean myIncludeTests;
private final ModuleFileIndex myFileIndex;
private final ProjectFileIndex myProjectFileIndex;
private final Set<Module> myModules;
public ModuleWithDependenciesScope(Module module, boolean includeLibraries, boolean includeOtherModules, boolean includeTests) {
private final Set<Module> myModules = new LinkedHashSet<Module>();
private final Set<VirtualFile> myRoots = new LinkedHashSet<VirtualFile>();
public ModuleWithDependenciesScope(Module module,
boolean compileClasspath,
boolean includeLibraries,
boolean includeOtherModules,
boolean includeTests) {
super(module.getProject());
myModule = module;
myCompileClasspath = compileClasspath;
myIncludeLibraries = includeLibraries;
myIncludeOtherModules = includeOtherModules;
myIncludeTests = includeTests;
myFileIndex = ModuleRootManager.getInstance(myModule).getFileIndex();
myProjectFileIndex = ProjectRootManager.getInstance(getProject()).getFileIndex();
if (myIncludeOtherModules) {
myModules = new LinkedHashSet<Module>();
myModules.add(myModule);
Module[] dependencies = ModuleRootManager.getInstance(myModule).getDependencies(myIncludeTests);
ContainerUtil.addAll(myModules, dependencies);
for (Module dependency : dependencies) {
addExportedModules(dependency);
}
OrderEnumerator en = ModuleRootManager.getInstance(module).orderEntries();
en.recursively();
if (myCompileClasspath) {
en.exportedOnly().compileOnly();
}
else {
myModules = null;
en.runtimeOnly();
}
}
if (!myIncludeLibraries) en.withoutLibraries();
if (!myIncludeOtherModules) en.withoutDepModules();
if (!myIncludeTests) en.productionOnly();
private void addExportedModules(Module module) {
OrderEntry[] orderEntries = ModuleRootManager.getInstance(module).getOrderEntries();
for (OrderEntry orderEntry : orderEntries) {
if (!orderEntry.isValid()) {
continue;
en.forEach(new Processor<OrderEntry>() {
@Override
public boolean process(OrderEntry each) {
if (each instanceof ModuleOrderEntry) {
myModules.add(((ModuleOrderEntry)each).getModule());
}
else if (each instanceof ModuleSourceOrderEntry) {
myModules.add(each.getOwnerModule());
}
return true;
}
if (orderEntry instanceof ModuleOrderEntry && ((ModuleOrderEntry)orderEntry).isExported()) {
if (!myIncludeTests) {
final DependencyScope scope = ((ModuleOrderEntry)orderEntry).getScope();
if (!scope.isForProductionCompile() && !scope.isForProductionRuntime()) {
continue;
}
}
Module exportedModule = ((ModuleOrderEntry)orderEntry).getModule();
if (!myModules.contains(exportedModule)) { //could be true in case of circular dependencies
myModules.add(exportedModule);
addExportedModules(exportedModule);
}
});
Collections.addAll(myRoots, en.roots(new NotNullFunction<OrderEntry, OrderRootType>() {
@NotNull
@Override
public OrderRootType fun(OrderEntry entry) {
if (entry instanceof ModuleOrderEntry || entry instanceof ModuleSourceOrderEntry) return OrderRootType.SOURCES;
return OrderRootType.CLASSES;
}
}
}
public boolean contains(VirtualFile file) {
if (!myIncludeTests && myFileIndex.isInTestSourceContent(file)) return false;
if (myModules != null) {
final Module module = myProjectFileIndex.getModuleForFile(file);
if (module != null) return myModules.contains(module) &&
myFileIndex.getOrderEntryForFile(file) != null &&
(myIncludeTests || !myProjectFileIndex.isInTestSourceContent(file));
}
final List<OrderEntry> entries = myFileIndex.getOrderEntriesForFile(file);
for (OrderEntry orderEntry : entries) {
if (myIncludeLibraries) {
if (orderEntry instanceof LibraryOrderEntry ||
orderEntry instanceof JdkOrderEntry) {
if (!myProjectFileIndex.isInLibraryClasses(file)) {
continue;
}
}
if (orderEntry instanceof ExportableOrderEntry) {
DependencyScope scope = ((ExportableOrderEntry)orderEntry).getScope();
if (!myIncludeTests && !scope.isForProductionCompile()) {
continue;
}
}
if (myIncludeOtherModules) {
return true;
}
else {
if (!(orderEntry instanceof ModuleOrderEntry)) return true;
}
}
else {
if (myIncludeOtherModules) {
if (orderEntry instanceof ModuleSourceOrderEntry || orderEntry instanceof ModuleOrderEntry) return true;
}
else {
if (orderEntry instanceof ModuleSourceOrderEntry) return true;
}
}
}
return false;
}
public int compare(VirtualFile file1, VirtualFile file2) {
OrderEntry orderEntry1 = myFileIndex.getOrderEntryForFile(file1);
LOG.assertTrue(orderEntry1 != null);
OrderEntry orderEntry2 = myFileIndex.getOrderEntryForFile(file2);
LOG.assertTrue(orderEntry2 != null);
int ret = orderEntry2.compareTo(orderEntry1);
if (ret != 0) return ret;
//prefer file which is closer to our module
if (myModules != null) {
for (Module module : myModules) {
ModuleFileIndex fileIndex = ModuleRootManager.getInstance(module).getFileIndex();
ret = fileIndex.isInContent(file1) ? fileIndex.isInContent(file2) ? 0 : 1 : fileIndex.isInContent(file2) ? -1 : 0;
if (ret != 0) return ret;
}
}
return 0;
}
public boolean isSearchInModuleContent(@NotNull Module aModule) {
if (myIncludeOtherModules) {
return myModules.contains(aModule);
}
else {
return aModule == myModule;
}
}
public boolean isSearchInModuleContent(@NotNull final Module aModule, final boolean testSources) {
return isSearchInModuleContent(aModule) && (myIncludeTests || !testSources);
}
public boolean isSearchInLibraries() {
return myIncludeLibraries;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ModuleWithDependenciesScope)) return false;
final ModuleWithDependenciesScope moduleWithDependenciesScope = (ModuleWithDependenciesScope)o;
if (!myModule.equals(moduleWithDependenciesScope.myModule)) return false;
if (myIncludeLibraries != moduleWithDependenciesScope.myIncludeLibraries) return false;
if (myIncludeOtherModules != moduleWithDependenciesScope.myIncludeOtherModules) return false;
if (myIncludeTests != moduleWithDependenciesScope.myIncludeTests) return false;
return true;
}
public int hashCode() {
return myModule.hashCode();
}
@NonNls
public String toString() {
return "Module with dependencies:" + myModule.getName() +
" include libraries:" + myIncludeLibraries +
" include other modules:" + myIncludeOtherModules +
" include tests:" + myIncludeTests;
}).getRoots());
}
@Override
public String getDisplayName() {
return PsiBundle.message("psi.search.scope.module", myModule.getName());
return myCompileClasspath ? PsiBundle.message("search.scope.module", myModule.getName())
: PsiBundle.message("search.scope.module.runtime", myModule.getName());
}
@Override
public boolean isSearchInModuleContent(@NotNull Module aModule) {
return myModules.contains(aModule);
}
@Override
public boolean isSearchInModuleContent(@NotNull Module aModule, boolean testSources) {
return isSearchInModuleContent(aModule) && (myIncludeTests || !testSources);
}
@Override
public boolean isSearchInLibraries() {
return myIncludeLibraries;
}
@Override
public boolean contains(VirtualFile file) {
return myRoots.contains(getFileRoot(file));
}
@Override
public int compare(VirtualFile file1, VirtualFile file2) {
VirtualFile r1 = getFileRoot(file1);
VirtualFile r2 = getFileRoot(file2);
if (r1 == r2) return 0;
if (r1 == null) return -1;
if (r2 == null) return 1;
for (VirtualFile root : myRoots) {
if (r1 == root) return 1;
if (r2 == root) return -1;
}
return 0;
}
@Nullable
private VirtualFile getFileRoot(VirtualFile file) {
if (myProjectFileIndex.isInContent(file)) {
return myProjectFileIndex.getSourceRootForFile(file);
}
return myProjectFileIndex.getClassRootForFile(file);
}
@TestOnly
public Collection<VirtualFile> getRoots() {
return Collections.unmodifiableSet(myRoots);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ModuleWithDependenciesScope that = (ModuleWithDependenciesScope)o;
if (myCompileClasspath != that.myCompileClasspath) return false;
if (myIncludeLibraries != that.myIncludeLibraries) return false;
if (myIncludeOtherModules != that.myIncludeOtherModules) return false;
if (myIncludeTests != that.myIncludeTests) return false;
if (myModule != null ? !myModule.equals(that.myModule) : that.myModule != null) return false;
return true;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (myModule != null ? myModule.hashCode() : 0);
result = 31 * result + (myIncludeLibraries ? 1 : 0);
result = 31 * result + (myIncludeOtherModules ? 1 : 0);
result = 31 * result + (myIncludeTests ? 1 : 0);
result = 31 * result + (myCompileClasspath ? 1 : 0);
return result;
}
@Override
public String toString() {
return "Module with dependencies:" + myModule.getName() +
" compile:" + myCompileClasspath +
" include libraries:" + myIncludeLibraries +
" include other modules:" + myIncludeOtherModules +
" include tests:" + myIncludeTests;
}
}
@@ -24,6 +24,7 @@ import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.NotNullFunction;
import com.intellij.util.Processor;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
@@ -152,6 +153,11 @@ abstract class OrderEnumeratorBase extends OrderEnumerator {
return new OrderRootsEnumeratorImpl(this, rootType);
}
@Override
public OrderRootsEnumerator roots(@NotNull NotNullFunction<OrderEntry, OrderRootType> rootTypeProvider) {
return new OrderRootsEnumeratorImpl(this, rootTypeProvider);
}
ModuleRootModel getRootModel(Module module) {
if (myModulesProvider != null) {
return myModulesProvider.getRootModel(module);
@@ -301,10 +307,11 @@ abstract class OrderEnumeratorBase extends OrderEnumerator {
return processor.myValue;
}
boolean addCustomOutput(ModuleOrderEntry moduleOrderEntry, Collection<VirtualFile> result) {
boolean addCustomOutput(Module forModule, ModuleRootModel orderEntryRootModel, OrderRootType type, Collection<VirtualFile> result) {
for (OrderEnumerationHandler handler : myCustomHandlers) {
final List<String> urls = new ArrayList<String>();
final boolean added = handler.addCustomOutput(moduleOrderEntry, myProductionOnly, myRuntimeOnly, myCompileOnly, urls);
final boolean added =
handler.addCustomOutput(forModule, orderEntryRootModel, type, myProductionOnly, myRuntimeOnly, myCompileOnly, urls);
for (String url : urls) {
ContainerUtil.addIfNotNull(VirtualFileManager.getInstance().findFileByUrl(url), result);
}
@@ -315,9 +322,9 @@ abstract class OrderEnumeratorBase extends OrderEnumerator {
return false;
}
boolean addCustomOutputUrls(ModuleOrderEntry moduleOrderEntry, Collection<String> result) {
boolean addCustomOutputUrls(Module forModule, ModuleRootModel orderEntryRootModel, OrderRootType type, Collection<String> result) {
for (OrderEnumerationHandler handler : myCustomHandlers) {
if (handler.addCustomOutput(moduleOrderEntry, myProductionOnly, myRuntimeOnly, myCompileOnly, result)) {
if (handler.addCustomOutput(forModule, orderEntryRootModel, type, myProductionOnly, myRuntimeOnly, myCompileOnly, result)) {
return true;
}
}
@@ -37,13 +37,22 @@ public class OrderRootsEnumeratorImpl implements OrderRootsEnumerator {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.OrderRootsEnumeratorImpl");
private final OrderEnumeratorBase myOrderEnumerator;
private final OrderRootType myRootType;
private final NotNullFunction<OrderEntry, OrderRootType> myRootTypeProvider;
private boolean myUsingCache;
private NotNullFunction<OrderEntry, VirtualFile[]> myCustomRootProvider;
private boolean myWithoutSelfModuleOutput;
public OrderRootsEnumeratorImpl(OrderEnumeratorBase orderEnumerator, OrderRootType rootType) {
public OrderRootsEnumeratorImpl(OrderEnumeratorBase orderEnumerator, @NotNull OrderRootType rootType) {
myOrderEnumerator = orderEnumerator;
myRootType = rootType;
myRootTypeProvider = null;
}
public OrderRootsEnumeratorImpl(OrderEnumeratorBase orderEnumerator,
@NotNull NotNullFunction<OrderEntry, OrderRootType> rootTypeProvider) {
myOrderEnumerator = orderEnumerator;
myRootTypeProvider = rootTypeProvider;
myRootType = null;
}
@NotNull
@@ -88,6 +97,7 @@ public class OrderRootsEnumeratorImpl implements OrderRootsEnumerator {
}
private void checkCanUseCache() {
LOG.assertTrue(myRootTypeProvider == null, "Caching not supported for OrderRootsEnumerator with root type provider");
LOG.assertTrue(myCustomRootProvider == null, "Caching not supported for OrderRootsEnumerator with 'usingCustomRootProvider' option");
LOG.assertTrue(!myWithoutSelfModuleOutput, "Caching not supported for OrderRootsEnumerator with 'withoutSelfModuleOutput' option");
}
@@ -97,21 +107,24 @@ public class OrderRootsEnumeratorImpl implements OrderRootsEnumerator {
myOrderEnumerator.forEach(new Processor<OrderEntry>() {
@Override
public boolean process(OrderEntry orderEntry) {
OrderRootType type = getRootType(orderEntry);
if (orderEntry instanceof ModuleSourceOrderEntry) {
collectModuleRoots(((ModuleSourceOrderEntry)orderEntry).getRootModel(), result);
collectModuleRoots(type, ((ModuleSourceOrderEntry)orderEntry).getRootModel(), result);
}
else if (orderEntry instanceof ModuleOrderEntry) {
ModuleOrderEntry moduleOrderEntry = (ModuleOrderEntry)orderEntry;
final Module module = moduleOrderEntry.getModule();
if (module != null) {
if (myRootType == OrderRootType.CLASSES && myOrderEnumerator.addCustomOutput(moduleOrderEntry, result)) {
ModuleRootModel rootModel = myOrderEnumerator.getRootModel(module);
if (myOrderEnumerator.addCustomOutput(orderEntry.getOwnerModule(), rootModel, type, result)) {
return true;
}
collectModuleRoots(myOrderEnumerator.getRootModel(module), result);
collectModuleRoots(type, rootModel, result);
}
}
else {
Collections.addAll(result, myCustomRootProvider != null ? myCustomRootProvider.fun(orderEntry) : orderEntry.getFiles(myRootType));
Collections.addAll(result, myCustomRootProvider != null ? myCustomRootProvider.fun(orderEntry) : orderEntry.getFiles(type));
}
return true;
}
@@ -131,21 +144,24 @@ public class OrderRootsEnumeratorImpl implements OrderRootsEnumerator {
myOrderEnumerator.forEach(new Processor<OrderEntry>() {
@Override
public boolean process(OrderEntry orderEntry) {
OrderRootType type = getRootType(orderEntry);
if (orderEntry instanceof ModuleSourceOrderEntry) {
collectModuleRootsUrls(((ModuleSourceOrderEntry)orderEntry).getRootModel(), result);
collectModuleRootsUrls(type, ((ModuleSourceOrderEntry)orderEntry).getRootModel(), result);
}
else if (orderEntry instanceof ModuleOrderEntry) {
ModuleOrderEntry moduleOrderEntry = (ModuleOrderEntry)orderEntry;
final Module module = moduleOrderEntry.getModule();
if (module != null) {
if (myRootType == OrderRootType.CLASSES && myOrderEnumerator.addCustomOutputUrls(moduleOrderEntry, result)) {
ModuleRootModel rootModel = myOrderEnumerator.getRootModel(module);
if (myOrderEnumerator.addCustomOutputUrls(orderEntry.getOwnerModule(), rootModel, type, result)) {
return true;
}
collectModuleRootsUrls(myOrderEnumerator.getRootModel(module), result);
collectModuleRootsUrls(type, rootModel, result);
}
}
else {
Collections.addAll(result, orderEntry.getUrls(myRootType));
Collections.addAll(result, orderEntry.getUrls(type));
}
return true;
}
@@ -191,12 +207,12 @@ public class OrderRootsEnumeratorImpl implements OrderRootsEnumerator {
return this;
}
private void collectModuleRoots(ModuleRootModel rootModel, Collection<VirtualFile> result) {
private void collectModuleRoots(OrderRootType type, ModuleRootModel rootModel, Collection<VirtualFile> result) {
final boolean productionOnly = myOrderEnumerator.isProductionOnly();
if (myRootType.equals(OrderRootType.SOURCES)) {
if (type.equals(OrderRootType.SOURCES)) {
Collections.addAll(result, rootModel.getSourceRoots(!productionOnly));
}
else if (myRootType.equals(OrderRootType.CLASSES)) {
else if (type.equals(OrderRootType.CLASSES)) {
final CompilerModuleExtension extension = rootModel.getModuleExtension(CompilerModuleExtension.class);
if (extension != null) {
if (myWithoutSelfModuleOutput && myOrderEnumerator.isMainModuleModel(rootModel)) {
@@ -211,12 +227,12 @@ public class OrderRootsEnumeratorImpl implements OrderRootsEnumerator {
}
}
private void collectModuleRootsUrls(ModuleRootModel rootModel, Collection<String> result) {
private void collectModuleRootsUrls(OrderRootType type, ModuleRootModel rootModel, Collection<String> result) {
final boolean productionOnly = myOrderEnumerator.isProductionOnly();
if (myRootType.equals(OrderRootType.SOURCES)) {
if (type.equals(OrderRootType.SOURCES)) {
Collections.addAll(result, rootModel.getSourceRootUrls(!productionOnly));
}
else if (myRootType.equals(OrderRootType.CLASSES)) {
else if (type.equals(OrderRootType.CLASSES)) {
final CompilerModuleExtension extension = rootModel.getModuleExtension(CompilerModuleExtension.class);
if (extension != null) {
if (myWithoutSelfModuleOutput && myOrderEnumerator.isMainModuleModel(rootModel)) {
@@ -231,4 +247,7 @@ public class OrderRootsEnumeratorImpl implements OrderRootsEnumerator {
}
}
private OrderRootType getRootType(OrderEntry e) {
return myRootType != null ? myRootType : myRootTypeProvider.fun(e);
}
}
@@ -43,8 +43,10 @@ el.cannot.resolve.variable=Cannot resolve variable ''{0}'' #loc
jsf.el.out.of.attribute=JSF EL out of attribute #loc
jsf.method.call.is.nonstd.extension=Method call is nonstandard extension #loc
psi.search.scope.unknown=<unknown scope>
psi.search.scope.module=Module ''{0}''
search.scope.unknown=<unknown scope>
search.scope.module=Module ''{0}''
search.scope.module.runtime=Module ''{0}'' runtime scope
anonymous.class.derived.display=Anonymous class derived from {0}
local.class.preposition=local
anonymous.class.context.display=Anonymous in {0}
@@ -85,7 +87,6 @@ invalid.regular.expression.message=Invalid regular expression {0}
#psi reference provider options
qualified.resolve.class.reference.provider.option=Tells reference provider to process only qualified class references (e.g. not resolve String as java.lang.String)
default.path.evaluator.option=Tells reference provider how evaluate default path for given file
runtime.scope.display.name={0} runtime scope
el.declare.variable.find.acceptable.class=Find acceptable class
0.is.not.an.identifier=''{0}'' is not an identifier.
cannot.modify.a.read.only.directory=Cannot modify a read-only directory ''{0}''.
@@ -95,20 +95,18 @@ public class MavenOrderEnumeratorHandler extends OrderEnumerationHandler {
}
@Override
public boolean addCustomOutput(@NotNull ModuleOrderEntry orderEntry,
public boolean addCustomOutput(@NotNull Module forModule,
@NotNull ModuleRootModel orderEntryRootModel,
OrderRootType type,
boolean productionOnly,
boolean runtimeOnly,
boolean compileOnly,
@NotNull Collection<String> urls) {
Module ownerModule = orderEntry.getOwnerModule();
MavenProjectsManager manager = MavenProjectsManager.getInstance(ownerModule.getProject());
MavenProject project = manager.findProject(ownerModule);
MavenProjectsManager manager = MavenProjectsManager.getInstance(forModule.getProject());
MavenProject project = manager.findProject(forModule);
if (project == null) return false;
Module depModule = orderEntry.getModule();
if (depModule == null) return false;
Module depModule = orderEntryRootModel.getModule();
MavenProject depProject = manager.findProject(depModule);
if (depProject == null) return false;
@@ -116,18 +114,29 @@ public class MavenOrderEnumeratorHandler extends OrderEnumerationHandler {
if (!shouldAddArtifact(each, productionOnly, runtimeOnly, compileOnly)) continue;
boolean isTestJar = MavenConstants.TYPE_TEST_JAR.equals(each.getType()) || "tests".equals(each.getClassifier());
addOutput(depModule, isTestJar, urls);
addRoots(orderEntryRootModel, type, isTestJar, urls);
}
return true;
}
private static void addOutput(Module module, boolean tests, Collection<String> urls) {
CompilerModuleExtension ex = CompilerModuleExtension.getInstance(module);
if (ex == null) return;
private static void addRoots(ModuleRootModel rootModel, OrderRootType type, boolean tests, Collection<String> result) {
if (type == OrderRootType.CLASSES) {
CompilerModuleExtension ex = rootModel.getModuleExtension(CompilerModuleExtension.class);
if (ex == null) return;
String output = tests ? ex.getCompilerOutputUrlForTests() : ex.getCompilerOutputUrl();
if (output != null) {
urls.add(output);
String output = tests ? ex.getCompilerOutputUrlForTests() : ex.getCompilerOutputUrl();
if (output != null) {
result.add(output);
}
}
else if (type == OrderRootType.SOURCES) {
for (ContentEntry eachEntry : rootModel.getContentEntries()) {
for (SourceFolder eachFolder : eachEntry.getSourceFolders()) {
if (eachFolder.isTestSource() == tests) {
result.add(eachFolder.getUrl());
}
}
}
}
}
@@ -1095,7 +1095,7 @@ public class MavenProjectsTree {
@NotNull MavenProgressIndicator process,
@NotNull EmbedderTask task) throws MavenProcessCanceledException {
MavenEmbedderWrapper embedder = embeddersManager.getEmbedder(embedderKind);
embedder.customizeForStrictResolve(getWorkspaceMap(), console, process);
embedder.customizeForResolve(getWorkspaceMap(), console, process);
embedder.clearCachesFor(mavenProject.getMavenId());
try {
task.run(embedder);
@@ -19,30 +19,44 @@ import com.intellij.execution.configurations.JavaParameters;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.roots.CompilerModuleExtension;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEnumerator;
import com.intellij.openapi.module.impl.scopes.ModuleWithDependenciesScope;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.PathsList;
import com.intellij.util.Processor;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.MavenImportingTestCase;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
public class MavenClasspathsAndSearchScopesTest extends MavenImportingTestCase {
private enum Type {PRODUCTION, TESTS}
private enum Scope {COMPILE, RUNTIME}
@Override
protected void setUpInWriteAction() throws Exception {
super.setUpInWriteAction();
createProjectSubDirs("m1/src/main/java",
"m1/src/test/java",
"m2/src/main/java",
"m2/src/test/java",
"m3/src/main/java",
"m3/src/test/java",
"m4/src/main/java",
"m4/src/test/java");
}
public void testConfiguringModuleDependencies() throws Exception {
VirtualFile m1 = createModulePom("m1", "<groupId>test</groupId>" +
"<artifactId>m1</artifactId>" +
@@ -90,12 +104,40 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
setupJdkForModules("m1", "m2", "m3", "m4");
assertAllProductionSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m2/src/main/java",
getProjectPath() + "/m3/src/main/java");
assertAllTestsSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m1/src/test/java",
getProjectPath() + "/m2/src/main/java",
getProjectPath() + "/m3/src/main/java");
assertAllProductionClasspath("m1",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes",
getProjectPath() + "/m3/target/classes");
assertAllTestsClasspath("m1",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes",
getProjectPath() + "/m3/target/classes");
assertAllProductionSearchScope("m2",
getProjectPath() + "/m2/src/main/java",
getProjectPath() + "/m3/src/main/java",
getProjectPath() + "/m4/src/main/java");
assertAllTestsSearchScope("m2",
getProjectPath() + "/m2/src/main/java",
getProjectPath() + "/m2/src/test/java",
getProjectPath() + "/m3/src/main/java",
getProjectPath() + "/m4/src/main/java");
assertAllProductionClasspath("m2",
getProjectPath() + "/m2/target/classes",
getProjectPath() + "/m3/target/classes",
getProjectPath() + "/m4/target/classes");
assertAllTestsClasspath("m2",
getProjectPath() + "/m2/target/test-classes",
getProjectPath() + "/m2/target/classes",
@@ -126,10 +168,15 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
setupJdkForModules("m1", "m2");
assertAllProductionSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m2/src/main/java");
assertAllProductionClasspath("m1",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes");
assertAllProductionSearchScope("m2",
getProjectPath() + "/m2/src/main/java");
assertAllProductionClasspath("m2",
getProjectPath() + "/m2/target/classes");
}
@@ -166,11 +213,20 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
setupJdkForModules("m1", "m2", "m3");
assertAllProductionSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m2/src/test/java",
getProjectPath() + "/m3/src/test/java");
assertAllTestsSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m1/src/test/java",
getProjectPath() + "/m2/src/test/java",
getProjectPath() + "/m3/src/test/java");
assertAllProductionClasspath("m1",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/test-classes",
getProjectPath() + "/m3/target/test-classes");
assertAllTestsClasspath("m1",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
@@ -212,9 +268,16 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
setupJdkForModules("m1", "m2", "m3");
assertAllProductionSearchScope("m1",
getProjectPath() + "/m1/src/main/java");
assertAllTestsSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m1/src/test/java",
getProjectPath() + "/m2/src/test/java",
getProjectPath() + "/m3/src/test/java");
assertAllProductionClasspath("m1",
getProjectPath() + "/m1/target/classes");
assertAllTestsClasspath("m1",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
@@ -222,46 +285,6 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
getProjectPath() + "/m3/target/test-classes");
}
public void testConfiguringModuleDependenciesOnTestJarWithTestScopeAndRegularDependency() throws Exception {
VirtualFile m1 = createModulePom("m1", "<groupId>test</groupId>" +
"<artifactId>m1</artifactId>" +
"<version>1</version>" +
"<dependencies>" +
" <dependency>" +
" <groupId>test</groupId>" +
" <artifactId>m2</artifactId>" +
" <version>1</version>" +
" </dependency>" +
" <dependency>" +
" <groupId>test</groupId>" +
" <artifactId>m2</artifactId>" +
" <version>1</version>" +
" <type>test-jar</type>" +
" <scope>test</scope>" +
" </dependency>" +
"</dependencies>");
VirtualFile m2 = createModulePom("m2", "<groupId>test</groupId>" +
"<artifactId>m2</artifactId>" +
"<version>1</version>");
importProjects(m1, m2);
assertModules("m1", "m2");
setupJdkForModules("m1", "m2");
assertAllProductionClasspath("m1",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes");
assertAllTestsClasspath("m1",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes",
getProjectPath() + "/m2/target/test-classes");
}
public void testConfiguringModuleDependenciesOnBothNormalAndTestJar() throws Exception {
VirtualFile m1 = createModulePom("m1", "<groupId>test</groupId>" +
"<artifactId>m1</artifactId>" +
@@ -290,6 +313,17 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
setupJdkForModules("m1", "m2", "m2");
assertAllProductionSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m2/src/main/java",
getProjectPath() + "/m2/src/test/java");
assertAllTestsSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m1/src/test/java",
getProjectPath() + "/m2/src/main/java",
getProjectPath() + "/m2/src/test/java");
assertAllProductionClasspath("m1",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes",
@@ -302,6 +336,55 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
getProjectPath() + "/m2/target/test-classes");
}
public void testConfiguringModuleDependenciesOnNormalAndTestJarWithTestScope() throws Exception {
VirtualFile m1 = createModulePom("m1", "<groupId>test</groupId>" +
"<artifactId>m1</artifactId>" +
"<version>1</version>" +
"<dependencies>" +
" <dependency>" +
" <groupId>test</groupId>" +
" <artifactId>m2</artifactId>" +
" <version>1</version>" +
" </dependency>" +
" <dependency>" +
" <groupId>test</groupId>" +
" <artifactId>m2</artifactId>" +
" <version>1</version>" +
" <type>test-jar</type>" +
" <scope>test</scope>" +
" </dependency>" +
"</dependencies>");
VirtualFile m2 = createModulePom("m2", "<groupId>test</groupId>" +
"<artifactId>m2</artifactId>" +
"<version>1</version>");
importProjects(m1, m2);
assertModules("m1", "m2");
setupJdkForModules("m1", "m2");
assertAllProductionSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m2/src/main/java");
assertAllTestsSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m1/src/test/java",
getProjectPath() + "/m2/src/main/java",
getProjectPath() + "/m2/src/test/java");
assertAllProductionClasspath("m1",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes");
assertAllTestsClasspath("m1",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes",
getProjectPath() + "/m2/target/test-classes");
}
public void testOptionalLibraryDependencies() throws Exception {
createRepositoryFile("jmock/jmock/1.0/jmock-1.0.jar");
VirtualFile m1 = createModulePom("m1", "<groupId>test</groupId>" +
@@ -343,12 +426,40 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
setupJdkForModules("m1", "m2");
assertAllProductionSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m2/src/main/java",
getRepositoryPath() + "/jmock/jmock/1.0/jmock-1.0.jar");
assertAllTestsSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m1/src/test/java",
getProjectPath() + "/m2/src/main/java",
getRepositoryPath() + "/jmock/jmock/1.0/jmock-1.0.jar");
assertAllProductionClasspath("m1",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes",
getRepositoryPath() + "/jmock/jmock/1.0/jmock-1.0.jar");
assertAllTestsClasspath("m1",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes",
getRepositoryPath() + "/jmock/jmock/1.0/jmock-1.0.jar");
assertAllProductionSearchScope("m2",
getProjectPath() + "/m2/src/main/java",
getRepositoryPath() + "/jmock/jmock/1.0/jmock-1.0.jar",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertAllTestsSearchScope("m2",
getProjectPath() + "/m2/src/main/java",
getProjectPath() + "/m2/src/test/java",
getRepositoryPath() + "/jmock/jmock/1.0/jmock-1.0.jar",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertAllProductionClasspath("m2",
getProjectPath() + "/m2/target/classes",
getRepositoryPath() + "/jmock/jmock/1.0/jmock-1.0.jar",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertAllTestsClasspath("m2",
getProjectPath() + "/m2/target/test-classes",
getProjectPath() + "/m2/target/classes",
@@ -356,74 +467,6 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
}
public void testDoNotChangeClasspathForRegularModules() throws Exception {
VirtualFile m1 = createModulePom("m1", "<groupId>test</groupId>" +
"<artifactId>m1</artifactId>" +
"<version>1</version>" +
"<dependencies>" +
" <dependency>" +
" <groupId>test</groupId>" +
" <artifactId>m2</artifactId>" +
" <version>1</version>" +
" <optional>true</optional>" +
" </dependency>" +
" <dependency>" +
" <groupId>junit</groupId>" +
" <artifactId>junit</artifactId>" +
" <version>4.0</version>" +
" <optional>true</optional>" +
" </dependency>" +
"</dependencies>");
VirtualFile m2 = createModulePom("m2", "<groupId>test</groupId>" +
"<artifactId>m2</artifactId>" +
"<version>1</version>");
importProjects(m1, m2);
assertModules("m1", "m2");
final Module user = createModule("user");
new WriteCommandAction.Simple(myProject) {
@Override
protected void run() throws Throwable {
ModifiableRootModel model = ModuleRootManager.getInstance(user).getModifiableModel();
model.addModuleOrderEntry(getModule("m1"));
VirtualFile out = user.getModuleFile().getParent().createChildDirectory(this, "output");
VirtualFile testOut = user.getModuleFile().getParent().createChildDirectory(this, "test-output");
model.getModuleExtension(CompilerModuleExtension.class).setCompilerOutputPath(out);
model.getModuleExtension(CompilerModuleExtension.class).setCompilerOutputPathForTests(testOut);
model.getModuleExtension(CompilerModuleExtension.class).inheritCompilerOutputPath(false);
model.commit();
}
}.execute().throwException();
assertModuleModuleDeps("m1", "m2");
assertModuleLibDeps("m1", "Maven: junit:junit:4.0");
assertModuleModuleDeps("user", "m1");
assertModuleLibDeps("user");
setupJdkForModules("m1", "m2", "user");
assertAllTestsClasspath("user",
getProjectPath() + "/user/test-output",
getProjectPath() + "/user/output",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/test-classes",
getProjectPath() + "/m2/target/classes",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertAllTestsClasspath("m1",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
}
public void testProvidedAndTestDependencies() throws Exception {
createRepositoryFile("jmock/jmock/4.0/jmock-4.0.jar");
VirtualFile m1 = createModulePom("m1", "<groupId>test</groupId>" +
@@ -471,13 +514,26 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
setupJdkForModules("m1", "m2", "m3");
assertCompileProductionSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m2/src/main/java",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertRuntimeProductionSearchScope("m1",
getProjectPath() + "/m1/src/main/java");
assertAllTestsSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m1/src/test/java",
getProjectPath() + "/m2/src/main/java",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar",
getProjectPath() + "/m3/src/main/java",
getRepositoryPath() + "/jmock/jmock/4.0/jmock-4.0.jar");
assertCompileProductionClasspath("m1",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertRuntimeProductionClasspath("m1",
getProjectPath() + "/m1/target/classes");
assertAllTestsClasspath("m1",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
@@ -517,6 +573,18 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
setupJdkForModules("m1", "m2");
assertCompileProductionSearchScope("m1",
getProjectPath() + "/m1/src/main/java");
assertRuntimeProductionSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m2/src/main/java",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertAllTestsSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m1/src/test/java",
getProjectPath() + "/m2/src/main/java",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertCompileProductionClasspath("m1",
getProjectPath() + "/m1/target/classes");
@@ -574,27 +642,44 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
setupJdkForModules("m1", "m2");
assertAllProductionSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m2/src/main/java");
assertAllTestsSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m1/src/test/java",
getProjectPath() + "/m2/src/main/java");
assertAllProductionClasspath("m1",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes");
assertAllTestsClasspath("m1",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes");
assertCompileProductionSearchScope("m2",
getProjectPath() + "/m2/src/main/java",
getRepositoryPath() + "/jmock/jmock/1.0/jmock-1.0.jar");
assertRuntimeProductionSearchScope("m2",
getProjectPath() + "/m2/src/main/java");
assertAllTestsSearchScope("m2",
getProjectPath() + "/m2/src/main/java",
getProjectPath() + "/m2/src/test/java",
getRepositoryPath() + "/jmock/jmock/1.0/jmock-1.0.jar",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertCompileProductionClasspath("m2",
getProjectPath() + "/m2/target/classes",
getRepositoryPath() + "/jmock/jmock/1.0/jmock-1.0.jar");
assertRuntimeProductionClasspath("m2",
getProjectPath() + "/m2/target/classes");
assertRuntimeTestsClasspath("m2",
getProjectPath() + "/m2/target/test-classes",
getProjectPath() + "/m2/target/classes",
getRepositoryPath() + "/jmock/jmock/1.0/jmock-1.0.jar",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertAllTestsClasspath("m2",
getProjectPath() + "/m2/target/test-classes",
getProjectPath() + "/m2/target/classes",
getRepositoryPath() + "/jmock/jmock/1.0/jmock-1.0.jar",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
}
public void testDoNotIncludeConflictingTransitiveDependenciesInTheClasspath() throws Exception {
@@ -647,6 +732,13 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
setupJdkForModules("m1", "m2", "m3");
assertAllTestsSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m1/src/test/java",
getProjectPath() + "/m2/src/main/java",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar",
getProjectPath() + "/m3/src/main/java");
assertAllTestsClasspath("m1",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
@@ -699,10 +791,19 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
setupJdkForModules("m1");
assertAllProductionSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertAllTestsSearchScope("m1",
getProjectPath() + "/m1/src/main/java",
getProjectPath() + "/m1/src/test/java",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar",
f1.getPath(),
f2.getPath());
assertAllProductionClasspath("m1",
getProjectPath() + "/m1/target/classes",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertAllTestsClasspath("m1",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
@@ -711,6 +812,101 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
f2.getPath());
}
public void testDoNotChangeClasspathForRegularModules() throws Exception {
VirtualFile m1 = createModulePom("m1", "<groupId>test</groupId>" +
"<artifactId>m1</artifactId>" +
"<version>1</version>" +
"<dependencies>" +
" <dependency>" +
" <groupId>test</groupId>" +
" <artifactId>m2</artifactId>" +
" <version>1</version>" +
" <scope>runtime</scope>" +
" <optional>true</optional>" +
" </dependency>" +
" <dependency>" +
" <groupId>junit</groupId>" +
" <artifactId>junit</artifactId>" +
" <version>4.0</version>" +
" <scope>provided</scope>" +
" <optional>true</optional>" +
" </dependency>" +
"</dependencies>");
VirtualFile m2 = createModulePom("m2", "<groupId>test</groupId>" +
"<artifactId>m2</artifactId>" +
"<version>1</version>");
importProjects(m1, m2);
assertModules("m1", "m2");
final Module user = createModule("user");
new WriteCommandAction.Simple(myProject) {
@Override
protected void run() throws Throwable {
ModifiableRootModel model = ModuleRootManager.getInstance(user).getModifiableModel();
model.addModuleOrderEntry(getModule("m1"));
VirtualFile out = user.getModuleFile().getParent().createChildDirectory(this, "output");
VirtualFile testOut = user.getModuleFile().getParent().createChildDirectory(this, "test-output");
model.getModuleExtension(CompilerModuleExtension.class).setCompilerOutputPath(out);
model.getModuleExtension(CompilerModuleExtension.class).setCompilerOutputPathForTests(testOut);
model.getModuleExtension(CompilerModuleExtension.class).inheritCompilerOutputPath(false);
model.commit();
}
}.execute().throwException();
assertModuleModuleDeps("m1", "m2");
assertModuleLibDeps("m1", "Maven: junit:junit:4.0");
assertModuleModuleDeps("user", "m1");
assertModuleLibDeps("user");
setupJdkForModules("m1", "m2", "user");
// todo check search scopes
assertCompileProductionClasspath("user",
getProjectPath() + "/user/output",
getProjectPath() + "/m1/target/classes",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertRuntimeProductionClasspath("user",
getProjectPath() + "/user/output",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes");
assertCompileTestsClasspath("user",
getProjectPath() + "/user/test-output",
getProjectPath() + "/user/output",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertRuntimeTestsClasspath("user",
getProjectPath() + "/user/test-output",
getProjectPath() + "/user/output",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/test-classes",
getProjectPath() + "/m2/target/classes",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertCompileProductionClasspath("m1",
getProjectPath() + "/m1/target/classes",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
assertRuntimeProductionClasspath("m1",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes");
assertAllTestsClasspath("m1",
getProjectPath() + "/m1/target/test-classes",
getProjectPath() + "/m1/target/classes",
getProjectPath() + "/m2/target/classes",
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
}
private void assertAllProductionClasspath(String moduleName, String... paths) throws Exception {
assertCompileProductionClasspath(moduleName, paths);
assertRuntimeProductionClasspath(moduleName, paths);
@@ -737,25 +933,91 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
assertClasspath(moduleName, Scope.RUNTIME, Type.TESTS, paths);
}
private void assertClasspath(String moduleName, Scope scope, Type type, String... paths) throws Exception {
private void assertClasspath(String moduleName, Scope scope, Type type, String... expectedPaths) throws Exception {
createOutputDirectories();
PathsList actualPaths;
PathsList actualPathsList;
Module module = getModule(moduleName);
if (scope == Scope.RUNTIME) {
JavaParameters params = new JavaParameters();
params.configureByModule(getModule(moduleName), type == Type.TESTS ? JavaParameters.CLASSES_AND_TESTS : JavaParameters.CLASSES_ONLY);
actualPaths = params.getClassPath();
params.configureByModule(module, type == Type.TESTS ? JavaParameters.CLASSES_AND_TESTS : JavaParameters.CLASSES_ONLY);
actualPathsList = params.getClassPath();
}
else {
OrderEnumerator en = OrderEnumerator.orderEntries(getModule(moduleName)).recursively().withoutSdk().compileOnly();
OrderEnumerator en = OrderEnumerator.orderEntries(module).recursively().withoutSdk().compileOnly();
if (type == Type.PRODUCTION) en.productionOnly();
actualPaths = en.classes().getPathsList();
actualPathsList = en.classes().getPathsList();
}
assertPaths(expectedPaths, actualPathsList.getPathList());
}
private void assertAllProductionSearchScope(String moduleName, String... paths) throws Exception {
assertCompileProductionSearchScope(moduleName, paths);
assertRuntimeProductionSearchScope(moduleName, paths);
}
private void assertAllTestsSearchScope(String moduleName, String... paths) throws Exception {
assertCompileTestsSearchScope(moduleName, paths);
assertRuntimeTestsSearchScope(moduleName, paths);
}
private void assertCompileProductionSearchScope(String moduleName, String... paths) throws Exception {
assertSearchScope(moduleName, Scope.COMPILE, Type.PRODUCTION, paths);
}
private void assertCompileTestsSearchScope(String moduleName, String... paths) throws Exception {
assertSearchScope(moduleName, Scope.COMPILE, Type.TESTS, paths);
}
private void assertRuntimeProductionSearchScope(String moduleName, String... paths) throws Exception {
assertSearchScope(moduleName, Scope.RUNTIME, Type.PRODUCTION, paths);
}
private void assertRuntimeTestsSearchScope(String moduleName, String... paths) throws Exception {
assertSearchScope(moduleName, Scope.RUNTIME, Type.TESTS, paths);
}
private void assertSearchScope(String moduleName, Scope scope, Type type, String... expectedPaths) throws Exception {
createOutputDirectories();
Module module = getModule(moduleName);
GlobalSearchScope searchScope = scope == Scope.COMPILE ? module.getModuleWithDependenciesAndLibrariesScope(type == Type.TESTS)
: module.getModuleRuntimeScope(type == Type.TESTS);
final List<VirtualFile> entries = new ArrayList<VirtualFile>(((ModuleWithDependenciesScope)searchScope).getRoots());
OrderEnumerator.orderEntries(module).recursively().compileOnly().forEach(new Processor<OrderEntry>() {
@Override
public boolean process(OrderEntry orderEntry) {
if (orderEntry instanceof JdkOrderEntry) {
entries.removeAll(Arrays.asList(orderEntry.getFiles(OrderRootType.CLASSES)));
}
return true;
}
});
List<String> actualPaths = new ArrayList<String>();
for (VirtualFile each : entries) {
if (each.getFileSystem() == JarFileSystem.getInstance()) {
actualPaths.add(JarFileSystem.getInstance().getVirtualFileForJar(each).getPath());
}
else {
actualPaths.add(each.getPath());
}
}
assertPaths(expectedPaths, actualPaths);
}
private void assertPaths(String[] expectedPaths, List<String> actualPaths) {
List<String> systemPaths = new ArrayList<String>();
for (String each : paths) {
for (String each : expectedPaths) {
systemPaths.add(FileUtil.toSystemDependentName(each));
}
assertOrderedElementsAreEqual(actualPaths.getPathList(), systemPaths);
assertOrderedElementsAreEqual(actualPaths, systemPaths);
}
private void createRepositoryFile(String filePath) throws IOException {
@@ -765,7 +1027,7 @@ public class MavenClasspathConfigurationTest extends MavenImportingTestCase {
private void createOutputDirectories() {
for (Module module : ModuleManager.getInstance(myProject).getModules()) {
final CompilerModuleExtension extension = CompilerModuleExtension.getInstance(module);
CompilerModuleExtension extension = CompilerModuleExtension.getInstance(module);
if (extension != null) {
createDirectoryIfDoesntExist(extension.getCompilerOutputUrl());
createDirectoryIfDoesntExist(extension.getCompilerOutputUrlForTests());