create project from existing sources: refactored and tests added

This commit is contained in:
nik
2014-02-05 12:14:37 +04:00
parent cd2d98447d
commit 64dd67f943
6 changed files with 166 additions and 83 deletions
@@ -26,7 +26,7 @@ import java.util.*;
/**
* @author nik
*/
class DetectedRootData {
public class DetectedRootData {
private final File myDirectory;
private MultiMap<DetectedProjectRoot, ProjectStructureDetector> myRoots = MultiMap.createLinked();
@@ -25,6 +25,8 @@ 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.MultiMap;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
@@ -41,6 +43,11 @@ public class RootDetectionProcessor {
private final FileTypeManager myTypeManager;
private final ProgressIndicator myProgressIndicator;
@NotNull
public static List<DetectedRootData> detectRoots(@NotNull File baseProjectFile) {
return new RootDetectionProcessor(baseProjectFile, ProjectStructureDetector.EP_NAME.getExtensions()).detectRoots();
}
public RootDetectionProcessor(File baseDir, final ProjectStructureDetector[] detectors) {
myBaseDir = getCanonicalDir(baseDir);
myDetectors = detectors;
@@ -60,8 +67,18 @@ public class RootDetectionProcessor {
}
}
public static MultiMap<ProjectStructureDetector, DetectedProjectRoot> createRootsMap(List<DetectedRootData> list) {
MultiMap<ProjectStructureDetector, DetectedProjectRoot> roots = new MultiMap<ProjectStructureDetector, DetectedProjectRoot>();
for (final DetectedRootData rootData : list) {
for (ProjectStructureDetector detector : rootData.getSelectedDetectors()) {
roots.putValue(detector, rootData.getSelectedRoot());
}
}
return roots;
}
public Map<ProjectStructureDetector, List<DetectedProjectRoot>> findRoots() {
public Map<ProjectStructureDetector, List<DetectedProjectRoot>> runDetectors() {
if (!myBaseDir.isDirectory()) {
return Collections.emptyMap();
}
@@ -145,4 +162,67 @@ public class RootDetectionProcessor {
}
return parentsToSkip;
}
private static void removeIncompatibleRoots(DetectedProjectRoot root, Map<File, DetectedRootData> rootData) {
DetectedRootData[] allRoots = rootData.values().toArray(new DetectedRootData[rootData.values().size()]);
for (DetectedRootData child : allRoots) {
final File childDirectory = child.getDirectory();
if (FileUtil.isAncestor(root.getDirectory(), childDirectory, true)) {
for (DetectedProjectRoot projectRoot : child.getAllRoots()) {
if (!root.canContainRoot(projectRoot)) {
child.removeRoot(projectRoot);
}
}
if (child.getAllRoots().length == 0) {
rootData.remove(childDirectory);
}
}
}
}
private static boolean isUnderIncompatibleRoot(DetectedProjectRoot root, Map<File, DetectedRootData> rootData) {
File directory = root.getDirectory().getParentFile();
while (directory != null) {
final DetectedRootData data = rootData.get(directory);
if (data != null) {
for (DetectedProjectRoot parentRoot : data.getAllRoots()) {
if (!parentRoot.canContainRoot(root)) {
return true;
}
}
}
directory = directory.getParentFile();
}
return false;
}
private List<DetectedRootData> detectRoots() {
Map<ProjectStructureDetector, List<DetectedProjectRoot>> roots = runDetectors();
if (myProgressIndicator != null) {
myProgressIndicator.setText2("Processing " + roots.values().size() + " project roots...");
}
Map<File, DetectedRootData> rootData = new LinkedHashMap<File, DetectedRootData>();
for (ProjectStructureDetector detector : roots.keySet()) {
for (DetectedProjectRoot detectedRoot : roots.get(detector)) {
if (isUnderIncompatibleRoot(detectedRoot, rootData)) {
continue;
}
final DetectedRootData data = rootData.get(detectedRoot.getDirectory());
if (data == null) {
rootData.put(detectedRoot.getDirectory(), new DetectedRootData(detector, detectedRoot));
}
else {
detectedRoot = data.addRoot(detector, detectedRoot);
}
removeIncompatibleRoots(detectedRoot, rootData);
}
}
if (myProgressIndicator != null) {
myProgressIndicator.setText2("");
}
return new ArrayList<DetectedRootData>(rootData.values());
}
}
@@ -16,20 +16,15 @@
package com.intellij.ide.util.importProject;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.util.newProjectWizard.*;
import com.intellij.ide.util.newProjectWizard.StepSequence;
import com.intellij.ide.util.projectWizard.AbstractStepWithProgress;
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.application.ApplicationNamesInfo;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.ui.MultiLineLabelUI;
import com.intellij.openapi.ui.ex.MultiLineLabel;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -122,17 +117,8 @@ public class RootsDetectionStep extends AbstractStepWithProgress<List<DetectedRo
}
public void updateDataModel() {
MultiMap<ProjectStructureDetector, DetectedProjectRoot> roots = new MultiMap<ProjectStructureDetector, DetectedProjectRoot>();
final List<DetectedRootData> selectedElements = myDetectedRootsChooser.getMarkedElements();
for (final DetectedRootData rootData : selectedElements) {
for (ProjectStructureDetector detector : rootData.getSelectedDetectors()) {
roots.putValue(detector, rootData.getSelectedRoot());
}
}
myBuilder.setProjectRoots(roots);
for (ProjectStructureDetector detector : roots.keySet()) {
detector.setupProjectStructure(roots.get(detector), myBuilder.getProjectDescriptor(detector), myBuilder);
}
myBuilder.setupProjectStructure(RootDetectionProcessor.createRootsMap(selectedElements));
updateSelectedTypes();
}
@@ -177,71 +163,9 @@ public class RootsDetectionStep extends AbstractStepWithProgress<List<DetectedRo
return Collections.emptyList();
}
final File baseProjectFile = new File(baseProjectPath);
Map<ProjectStructureDetector, List<DetectedProjectRoot>> roots = new RootDetectionProcessor(baseProjectFile,
ProjectStructureDetector.EP_NAME.getExtensions()).findRoots();
final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
if (progressIndicator != null) {
progressIndicator.setText2("Processing " + roots.values().size() + " project roots...");
}
Map<File, DetectedRootData> rootData = new LinkedHashMap<File, DetectedRootData>();
for (ProjectStructureDetector detector : roots.keySet()) {
for (DetectedProjectRoot detectedRoot : roots.get(detector)) {
if (isUnderIncompatibleRoot(detectedRoot, rootData)) {
continue;
}
final DetectedRootData data = rootData.get(detectedRoot.getDirectory());
if (data == null) {
rootData.put(detectedRoot.getDirectory(), new DetectedRootData(detector, detectedRoot));
}
else {
detectedRoot = data.addRoot(detector, detectedRoot);
}
removeIncompatibleRoots(detectedRoot, rootData);
}
}
if (progressIndicator != null) {
progressIndicator.setText2("");
}
return new ArrayList<DetectedRootData>(rootData.values());
return RootDetectionProcessor.detectRoots(new File(baseProjectPath));
}
private static void removeIncompatibleRoots(DetectedProjectRoot root, Map<File, DetectedRootData> rootData) {
DetectedRootData[] allRoots = rootData.values().toArray(new DetectedRootData[rootData.values().size()]);
for (DetectedRootData child : allRoots) {
final File childDirectory = child.getDirectory();
if (FileUtil.isAncestor(root.getDirectory(), childDirectory, true)) {
for (DetectedProjectRoot projectRoot : child.getAllRoots()) {
if (!root.canContainRoot(projectRoot)) {
child.removeRoot(projectRoot);
}
}
if (child.getAllRoots().length == 0) {
rootData.remove(childDirectory);
}
}
}
}
private static boolean isUnderIncompatibleRoot(DetectedProjectRoot root, Map<File, DetectedRootData> rootData) {
File directory = root.getDirectory().getParentFile();
while (directory != null) {
final DetectedRootData data = rootData.get(directory);
if (data != null) {
for (DetectedProjectRoot parentRoot : data.getAllRoots()) {
if (!parentRoot.canContainRoot(root)) {
return true;
}
}
}
directory = directory.getParentFile();
}
return false;
}
@Nullable
private String getBaseProjectPath() {
@@ -48,7 +48,7 @@ public class JavaSourceRootDetectionUtil {
public static Collection<JavaModuleSourceRoot> suggestRoots(@NotNull File dir) {
final List<JavaSourceRootDetector> detectors = ContainerUtil.findAll(ProjectStructureDetector.EP_NAME.getExtensions(), JavaSourceRootDetector.class);
final RootDetectionProcessor processor = new RootDetectionProcessor(dir, detectors.toArray(new JavaSourceRootDetector[detectors.size()]));
final Map<ProjectStructureDetector,List<DetectedProjectRoot>> rootsMap = processor.findRoots();
final Map<ProjectStructureDetector,List<DetectedProjectRoot>> rootsMap = processor.runDetectors();
Map<File, JavaModuleSourceRoot> result = new HashMap<File, JavaModuleSourceRoot>();
for (List<DetectedProjectRoot> roots : rootsMap.values()) {
@@ -128,8 +128,11 @@ public class ProjectFromSourcesBuilderImpl extends ProjectImportBuilder implemen
return myBaseProjectPath;
}
public void setProjectRoots(MultiMap<ProjectStructureDetector, DetectedProjectRoot> roots) {
public void setupProjectStructure(MultiMap<ProjectStructureDetector, DetectedProjectRoot> roots) {
myRoots = roots;
for (ProjectStructureDetector detector : roots.keySet()) {
detector.setupProjectStructure(roots.get(detector), getProjectDescriptor(detector), this);
}
}
@NotNull
@@ -0,0 +1,76 @@
/*
* 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.projectWizard;
import com.intellij.ide.util.importProject.DetectedRootData;
import com.intellij.ide.util.importProject.RootDetectionProcessor;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.ide.util.projectWizard.importSources.impl.ProjectFromSourcesBuilderImpl;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleType;
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 org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.List;
/**
* @author nik
*/
public abstract class ImportFromSourcesTestCase extends PlatformTestCase {
private ProjectFromSourcesBuilderImpl myBuilder;
private File myRootDir;
@Override
public void setUp() throws Exception {
super.setUp();
myBuilder = new ProjectFromSourcesBuilderImpl(new WizardContext(null), ModulesProvider.EMPTY_MODULES_PROVIDER);
}
@Override
protected void setUpProject() throws Exception {
}
protected Module assertOneModule(@NotNull ModuleType moduleType) {
Module module = assertOneElement(ModuleManager.getInstance(myProject).getModules());
assertEquals(moduleType, ModuleType.get(module));
return module;
}
protected void assertOneContentRoot(@NotNull Module module, String relativePath) {
File expected = new File(myRootDir, relativePath);
String url = assertOneElement(ModuleRootManager.getInstance(module).getContentRootUrls());
File actual = new File(VfsUtilCore.urlToPath(url));
assertEquals(expected.getAbsolutePath(), actual.getAbsolutePath());
}
protected void importFromSources(File dir) {
myRootDir = dir;
try {
myProject = doCreateProject(getIprFile());
List<DetectedRootData> list = RootDetectionProcessor.detectRoots(dir);
myBuilder.setupProjectStructure(RootDetectionProcessor.createRootsMap(list));
myBuilder.commit(myProject, null, ModulesProvider.EMPTY_MODULES_PROVIDER);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}