diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/DetectedRootData.java b/java/idea-ui/src/com/intellij/ide/util/importProject/DetectedRootData.java index b4bf4b17395e..ad7b5f868036 100644 --- a/java/idea-ui/src/com/intellij/ide/util/importProject/DetectedRootData.java +++ b/java/idea-ui/src/com/intellij/ide/util/importProject/DetectedRootData.java @@ -67,6 +67,10 @@ public class DetectedRootData { return roots.toArray(new DetectedProjectRoot[roots.size()]); } + public boolean isEmpty() { + return myRoots.isEmpty(); + } + public boolean isIncluded() { return myIncluded; } @@ -89,7 +93,7 @@ public class DetectedRootData { mySelectedRoot = root; } - public void removeRoot(DetectedProjectRoot root) { - myRoots.remove(root); + public Collection removeRoot(DetectedProjectRoot root) { + return myRoots.remove(root); } } diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/RootDetectionProcessor.java b/java/idea-ui/src/com/intellij/ide/util/importProject/RootDetectionProcessor.java index f7e2b88bd585..735e5b6769e4 100644 --- a/java/idea-ui/src/com/intellij/ide/util/importProject/RootDetectionProcessor.java +++ b/java/idea-ui/src/com/intellij/ide/util/importProject/RootDetectionProcessor.java @@ -15,16 +15,20 @@ */ package com.intellij.ide.util.importProject; +import com.intellij.ide.util.projectWizard.importSources.DetectedContentRoot; import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot; +import com.intellij.ide.util.projectWizard.importSources.DetectedSourceRoot; import com.intellij.ide.util.projectWizard.importSources.ProjectStructureDetector; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; @@ -173,7 +177,7 @@ public class RootDetectionProcessor { child.removeRoot(projectRoot); } } - if (child.getAllRoots().length == 0) { + if (child.isEmpty()) { rootData.remove(childDirectory); } } @@ -220,9 +224,65 @@ public class RootDetectionProcessor { } } + List dataCollection = mergeContentRoots(rootData); if (myProgressIndicator != null) { myProgressIndicator.setText2(""); } + return dataCollection; + } + + private List mergeContentRoots(Map rootData) { + LOG.debug(rootData.size() + " roots found, merging content roots"); + boolean hasSourceRoots = false; + Set typesToReplace = new HashSet(); + Set moduleTypes = new HashSet(); + for (DetectedRootData data : rootData.values()) { + for (DetectedProjectRoot root : data.getAllRoots()) { + if (root instanceof DetectedContentRoot) { + Collections.addAll(typesToReplace, ((DetectedContentRoot)root).getTypesToReplace()); + moduleTypes.add(((DetectedContentRoot)root).getModuleType()); + } + else if (root instanceof DetectedSourceRoot) { + LOG.debug("Source root found: " + root.getDirectory() + ", content roots will be ignored"); + hasSourceRoots = true; + break; + } + } + } + moduleTypes.removeAll(typesToReplace); + + if (hasSourceRoots || moduleTypes.size() <= 1) { + Iterator iterator = rootData.values().iterator(); + DetectedContentRoot firstRoot = null; + ProjectStructureDetector firstDetector = null; + while (iterator.hasNext()) { + DetectedRootData data = iterator.next(); + for (DetectedProjectRoot root : data.getAllRoots()) { + if (root instanceof DetectedContentRoot) { + LOG.debug("Removed detected " + root.getRootTypeName() + " content root: " + root.getDirectory()); + Collection detectors = data.removeRoot(root); + if ((firstRoot == null || firstDetector == null) && moduleTypes.contains(((DetectedContentRoot)root).getModuleType())) { + firstRoot = (DetectedContentRoot)root; + firstDetector = ContainerUtil.getFirstItem(detectors); + } + } + } + if (data.isEmpty()) { + iterator.remove(); + } + } + if (!hasSourceRoots && firstRoot != null && firstDetector != null) { + DetectedContentRoot baseRoot = new DetectedContentRoot(myBaseDir, firstRoot.getRootTypeName(), firstRoot.getModuleType()); + DetectedRootData data = rootData.get(myBaseDir); + if (data == null) { + rootData.put(myBaseDir, new DetectedRootData(firstDetector, baseRoot)); + } + else { + data.addRoot(firstDetector, baseRoot); + } + LOG.debug("Added " + firstRoot.getRootTypeName() + " content root for " + myBaseDir); + } + } return new ArrayList(rootData.values()); } } diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/AbstractStepWithProgress.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/AbstractStepWithProgress.java index 1068a14f7331..50ecf4a512b8 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/AbstractStepWithProgress.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/AbstractStepWithProgress.java @@ -29,6 +29,7 @@ import com.intellij.util.concurrency.SwingWorker; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.update.UiNotifyConnector; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.TestOnly; import javax.swing.*; import java.awt.*; @@ -97,6 +98,14 @@ public abstract class AbstractStepWithProgress extends ModuleWizardStep return progressPanel; } + @TestOnly + public void performStep() { + Result result = calculate(); + createResultsPanel(); + onFinished(result, false); + updateDataModel(); + } + private void cancelSearch() { if (myProgressIndicator != null) { myProgressIndicator.cancel(); diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/DetectedContentRoot.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/DetectedContentRoot.java new file mode 100644 index 000000000000..c56af7d60c65 --- /dev/null +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/DetectedContentRoot.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2014 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.ide.util.projectWizard.importSources; + +import com.intellij.openapi.module.ModuleType; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +/** + * @author nik + */ +public final class DetectedContentRoot extends DetectedProjectRoot { + @NotNull private final String myRootTypeName; + @NotNull private final ModuleType myModuleType; + @NotNull private final ModuleType[] myTypesToReplace; + + public DetectedContentRoot(@NotNull File directory, @NotNull String rootTypeName, @NotNull ModuleType moduleType, @NotNull ModuleType... typesToReplace) { + super(directory); + myRootTypeName = rootTypeName; + myModuleType = moduleType; + myTypesToReplace = typesToReplace; + } + + @NotNull + @Override + public String getRootTypeName() { + return myRootTypeName; + } + + @NotNull + public ModuleType getModuleType() { + return myModuleType; + } + + @NotNull + public ModuleType[] getTypesToReplace() { + return myTypesToReplace; + } +} diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectFromSourcesBuilder.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectFromSourcesBuilder.java index fc28f8f6bf6d..2863fe67b2c7 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectFromSourcesBuilder.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectFromSourcesBuilder.java @@ -44,4 +44,6 @@ public interface ProjectFromSourcesBuilder { WizardContext getContext(); boolean hasRootsFromOtherDetectors(ProjectStructureDetector thisDetector); + + void setupModulesByContentRoots(ProjectDescriptor projectDescriptor, Collection roots); } diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java index 6b4fe75e7fa6..e907b12a9f4c 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java @@ -25,10 +25,7 @@ import com.intellij.ide.util.newProjectWizard.modes.ImportImlMode; import com.intellij.ide.util.projectWizard.ExistingModuleLoader; import com.intellij.ide.util.projectWizard.ModuleBuilder; import com.intellij.ide.util.projectWizard.WizardContext; -import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot; -import com.intellij.ide.util.projectWizard.importSources.JavaModuleSourceRoot; -import com.intellij.ide.util.projectWizard.importSources.ProjectFromSourcesBuilder; -import com.intellij.ide.util.projectWizard.importSources.ProjectStructureDetector; +import com.intellij.ide.util.projectWizard.importSources.*; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.diagnostic.Logger; @@ -319,6 +316,19 @@ public class ProjectFromSourcesBuilderImpl extends ProjectImportBuilder implemen return false; } + @Override + public void setupModulesByContentRoots(ProjectDescriptor projectDescriptor, Collection roots) { + if (projectDescriptor.getModules().isEmpty()) { + List modules = new ArrayList(); + for (DetectedProjectRoot root : roots) { + if (root instanceof DetectedContentRoot) { + modules.add(new ModuleDescriptor(root.getDirectory(), ((DetectedContentRoot)root).getModuleType(), Collections.emptyList())); + } + } + projectDescriptor.setModules(modules); + } + } + @NotNull private static Module createModule(ProjectDescriptor projectDescriptor, final ModuleDescriptor descriptor, final Map projectLibs, final ModifiableModuleModel moduleModel) diff --git a/java/testFramework/src/com/intellij/ide/projectWizard/ImportFromSourcesTestCase.java b/java/testFramework/src/com/intellij/ide/projectWizard/ImportFromSourcesTestCase.java index f52a623514f4..175a9fd3a6d5 100644 --- a/java/testFramework/src/com/intellij/ide/projectWizard/ImportFromSourcesTestCase.java +++ b/java/testFramework/src/com/intellij/ide/projectWizard/ImportFromSourcesTestCase.java @@ -17,7 +17,11 @@ package com.intellij.ide.projectWizard; import com.intellij.ide.util.importProject.DetectedRootData; import com.intellij.ide.util.importProject.RootDetectionProcessor; +import com.intellij.ide.util.projectWizard.AbstractStepWithProgress; +import com.intellij.ide.util.projectWizard.ModuleWizardStep; import com.intellij.ide.util.projectWizard.WizardContext; +import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot; +import com.intellij.ide.util.projectWizard.importSources.ProjectStructureDetector; import com.intellij.ide.util.projectWizard.importSources.impl.ProjectFromSourcesBuilderImpl; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; @@ -26,6 +30,8 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.testFramework.PlatformTestCase; +import com.intellij.util.containers.MultiMap; +import com.intellij.util.ui.EmptyIcon; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -65,12 +71,26 @@ public abstract class ImportFromSourcesTestCase extends PlatformTestCase { myRootDir = dir; try { myProject = doCreateProject(getIprFile()); + myBuilder.setBaseProjectPath(dir.getAbsolutePath()); List list = RootDetectionProcessor.detectRoots(dir); - myBuilder.setupProjectStructure(RootDetectionProcessor.createRootsMap(list)); + MultiMap map = RootDetectionProcessor.createRootsMap(list); + myBuilder.setupProjectStructure(map); + for (ProjectStructureDetector detector : map.keySet()) { + List steps = detector.createWizardSteps(myBuilder, myBuilder.getProjectDescriptor(detector), EmptyIcon.ICON_16); + for (ModuleWizardStep step : steps) { + if (step instanceof AbstractStepWithProgress) { + performStep((AbstractStepWithProgress)step); + } + } + } myBuilder.commit(myProject, null, ModulesProvider.EMPTY_MODULES_PROVIDER); } catch (Exception e) { throw new RuntimeException(e); } } + + private static void performStep(AbstractStepWithProgress step) { + step.performStep(); + } } diff --git a/python/pluginSrc/com/jetbrains/python/module/PyProjectStructureDetector.java b/python/pluginSrc/com/jetbrains/python/module/PyProjectStructureDetector.java index 45dd7cda6d0f..2cad5f6855c3 100644 --- a/python/pluginSrc/com/jetbrains/python/module/PyProjectStructureDetector.java +++ b/python/pluginSrc/com/jetbrains/python/module/PyProjectStructureDetector.java @@ -19,11 +19,14 @@ import com.intellij.ide.util.importProject.ModuleDescriptor; import com.intellij.ide.util.importProject.ProjectDescriptor; import com.intellij.ide.util.projectWizard.ModuleWizardStep; import com.intellij.ide.util.projectWizard.ProjectWizardStepFactory; +import com.intellij.ide.util.projectWizard.importSources.DetectedContentRoot; import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot; import com.intellij.ide.util.projectWizard.importSources.ProjectFromSourcesBuilder; import com.intellij.ide.util.projectWizard.importSources.ProjectStructureDetector; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.module.WebModuleType; import com.intellij.openapi.util.io.FileUtilRt; +import com.jetbrains.python.PythonModuleTypeBase; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -50,13 +53,7 @@ public class PyProjectStructureDetector extends ProjectStructureDetector { for (File child : children) { if (FileUtilRt.extensionEquals(child.getName(), "py")) { LOG.info("Found Python file " + child.getPath()); - result.add(new DetectedProjectRoot(dir) { - @NotNull - @Override - public String getRootTypeName() { - return "Python"; - } - }); + result.add(new DetectedContentRoot(dir, "Python", PythonModuleTypeBase.getInstance(), WebModuleType.getInstance())); return DirectoryProcessingResult.SKIP_CHILDREN; } } @@ -67,6 +64,7 @@ public class PyProjectStructureDetector extends ProjectStructureDetector { public void setupProjectStructure(@NotNull Collection roots, @NotNull ProjectDescriptor projectDescriptor, @NotNull ProjectFromSourcesBuilder builder) { + builder.setupModulesByContentRoots(projectDescriptor, roots); if (!roots.isEmpty() && !builder.hasRootsFromOtherDetectors(this)) { List modules = projectDescriptor.getModules(); if (modules.isEmpty()) {