mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
added Maven's implementation for ProjectModelModificationService so various 'add missing dependency' actions will modify pom.xml files in case of Maven projects
This commit is contained in:
+15
-3
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.daemon.impl.quickfix;
|
||||
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.roots.ExternalLibraryDescriptor;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -23,6 +25,7 @@ import com.intellij.openapi.roots.DependencyScope;
|
||||
import com.intellij.openapi.roots.ProjectModelModificationService;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -66,9 +69,18 @@ class AddExternalLibraryToDependenciesQuickFix extends OrderEntryFix {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
public void invoke(@NotNull Project project, final Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
DependencyScope scope = suggestScopeByLocation(myCurrentModule, myReference.getElement());
|
||||
ProjectModelModificationService.getInstance(project).addDependency(myCurrentModule, myLibraryDescriptor, scope);
|
||||
importClass(myCurrentModule, editor, myReference, myQualifiedClassName);
|
||||
ProjectModelModificationService.getInstance(project).addDependency(myCurrentModule, myLibraryDescriptor, scope).done(
|
||||
new Consumer<Void>() {
|
||||
@Override
|
||||
public void consume(Void aVoid) {
|
||||
new WriteAction() {
|
||||
protected void run(@NotNull final Result result) {
|
||||
importClass(myCurrentModule, editor, myReference, myQualifiedClassName);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+16
-10
@@ -20,11 +20,17 @@ import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Provides methods to perform high-level modifications of project configuration accordingly with dependency management system used in the
|
||||
* project. E.g. if the project is imported from Maven the methods will modify pom.xml files and invoke reimporting to update IDEA's
|
||||
* project model. Since importing the changes to IDEA's project model may take a while the method work asynchronously and returns
|
||||
* {@link Promise} objects which may be used to be notified when the project configuration is finally updated.
|
||||
*
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class ProjectModelModificationService {
|
||||
@@ -32,22 +38,22 @@ public abstract class ProjectModelModificationService {
|
||||
return ServiceManager.getService(project, ProjectModelModificationService.class);
|
||||
}
|
||||
|
||||
public void addDependency(@NotNull Module from, @NotNull Module to) {
|
||||
addDependency(from, to, DependencyScope.COMPILE);
|
||||
public Promise<Void> addDependency(@NotNull Module from, @NotNull Module to) {
|
||||
return addDependency(from, to, DependencyScope.COMPILE);
|
||||
}
|
||||
|
||||
public abstract void addDependency(@NotNull Module from, @NotNull Module to, @NotNull DependencyScope scope);
|
||||
public abstract Promise<Void> addDependency(@NotNull Module from, @NotNull Module to, @NotNull DependencyScope scope);
|
||||
|
||||
public void addDependency(@NotNull Module from, @NotNull ExternalLibraryDescriptor libraryDescriptor) {
|
||||
addDependency(from, libraryDescriptor, DependencyScope.COMPILE);
|
||||
public Promise<Void> addDependency(@NotNull Module from, @NotNull ExternalLibraryDescriptor libraryDescriptor) {
|
||||
return addDependency(from, libraryDescriptor, DependencyScope.COMPILE);
|
||||
}
|
||||
|
||||
public void addDependency(Module from, ExternalLibraryDescriptor descriptor, DependencyScope scope) {
|
||||
addDependency(Collections.singletonList(from), descriptor, scope);
|
||||
public Promise<Void> addDependency(@NotNull Module from, @NotNull ExternalLibraryDescriptor descriptor, @NotNull DependencyScope scope) {
|
||||
return addDependency(Collections.singletonList(from), descriptor, scope);
|
||||
}
|
||||
|
||||
public abstract void addDependency(@NotNull Collection<Module> from, @NotNull ExternalLibraryDescriptor libraryDescriptor,
|
||||
@NotNull DependencyScope scope);
|
||||
public abstract Promise<Void> addDependency(@NotNull Collection<Module> from, @NotNull ExternalLibraryDescriptor libraryDescriptor,
|
||||
@NotNull DependencyScope scope);
|
||||
|
||||
public abstract void addDependency(@NotNull Module from, @NotNull Library library, @NotNull DependencyScope scope);
|
||||
public abstract Promise<Void> addDependency(@NotNull Module from, @NotNull Library library, @NotNull DependencyScope scope);
|
||||
}
|
||||
|
||||
@@ -19,20 +19,53 @@ import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Register implementation of this extension to support custom dependency management system for {@link ProjectModelModificationService}.
|
||||
*
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class ProjectModelModifier {
|
||||
public static final ExtensionPointName<ProjectModelModifier> EP_NAME = ExtensionPointName.create("com.intellij.projectModelModifier");
|
||||
|
||||
public abstract boolean addModuleDependency(@NotNull Module from, @NotNull Module to, @NotNull DependencyScope scope);
|
||||
/**
|
||||
* Implementation of this method should add dependency from module {@code from} to module {@code to} with scope {@code scope} accordingly
|
||||
* to this dependencies management system. If it takes some time to propagate changes in the external project configuration to IDEA's
|
||||
* project model the method may schedule this work for asynchronous execution and return {@link Promise} instance which will be fulfilled
|
||||
* when the work is done.
|
||||
* @return {@link Promise} instance if dependencies between these modules can be handled by this dependencies management system or
|
||||
* {@code null} otherwise
|
||||
*/
|
||||
@Nullable
|
||||
public abstract Promise<Void> addModuleDependency(@NotNull Module from, @NotNull Module to, @NotNull DependencyScope scope);
|
||||
|
||||
public abstract boolean addExternalLibraryDependency(@NotNull Collection<Module> modules,
|
||||
@NotNull ExternalLibraryDescriptor descriptor,
|
||||
@NotNull DependencyScope scope);
|
||||
/**
|
||||
* Implementation of this method should add dependency from modules {@code modules} to an external library with scope {@code scope} accordingly
|
||||
* to this dependencies management system. If it takes some time to propagate changes in the external project configuration to IDEA's
|
||||
* project model the method may schedule this work for asynchronous execution and return {@link Promise} instance which will be fulfilled
|
||||
* when the work is done.
|
||||
*
|
||||
* @return {@link Promise} instance if dependencies of these modules can be handled by this dependencies management system or
|
||||
* {@code null} otherwise
|
||||
*/
|
||||
@Nullable
|
||||
public abstract Promise<Void> addExternalLibraryDependency(@NotNull Collection<Module> modules,
|
||||
@NotNull ExternalLibraryDescriptor descriptor,
|
||||
@NotNull DependencyScope scope);
|
||||
|
||||
public abstract boolean addLibraryDependency(@NotNull Module from, @NotNull Library library, @NotNull DependencyScope scope);
|
||||
/**
|
||||
* Implementation of this method should add dependency from module {@code from} to {@code library} with scope {@code scope} accordingly
|
||||
* to this dependencies management system. If it takes some time to propagate changes in the external project configuration to IDEA's
|
||||
* project model the method may schedule this work for asynchronous execution and return {@link Promise} instance which will be fulfilled
|
||||
* when the work is done.
|
||||
*
|
||||
* @return {@link Promise} instance if dependencies between these modules can be handled by this dependencies management system or
|
||||
* {@code null} otherwise
|
||||
*/
|
||||
@Nullable
|
||||
public abstract Promise<Void> addLibraryDependency(@NotNull Module from, @NotNull Library library, @NotNull DependencyScope scope);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
|
||||
import com.intellij.openapi.roots.libraries.LibraryUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -45,15 +46,15 @@ public class IdeaProjectModelModifier extends ProjectModelModifier {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addModuleDependency(@NotNull Module from, @NotNull Module to, @NotNull DependencyScope scope) {
|
||||
public Promise<Void> addModuleDependency(@NotNull Module from, @NotNull Module to, @NotNull DependencyScope scope) {
|
||||
ModuleRootModificationUtil.addDependency(from, to, scope, false);
|
||||
return true;
|
||||
return Promise.DONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addExternalLibraryDependency(@NotNull final Collection<Module> modules,
|
||||
@NotNull final ExternalLibraryDescriptor descriptor,
|
||||
@NotNull final DependencyScope scope) {
|
||||
public Promise<Void> addExternalLibraryDependency(@NotNull final Collection<Module> modules,
|
||||
@NotNull final ExternalLibraryDescriptor descriptor,
|
||||
@NotNull final DependencyScope scope) {
|
||||
List<String> defaultRoots = descriptor.getLibraryClassesRoots();
|
||||
Module firstModule = ContainerUtil.getFirstItem(modules);
|
||||
LOG.assertTrue(firstModule != null);
|
||||
@@ -82,12 +83,12 @@ public class IdeaProjectModelModifier extends ProjectModelModifier {
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return Promise.DONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addLibraryDependency(@NotNull Module from, @NotNull Library library, @NotNull DependencyScope scope) {
|
||||
public Promise<Void> addLibraryDependency(@NotNull Module from, @NotNull Library library, @NotNull DependencyScope scope) {
|
||||
OrderEntryUtil.addLibraryToRoots(from, library);
|
||||
return true;
|
||||
return Promise.DONE;
|
||||
}
|
||||
}
|
||||
|
||||
+16
-9
@@ -23,6 +23,7 @@ import com.intellij.openapi.roots.ProjectModelModificationService;
|
||||
import com.intellij.openapi.roots.ProjectModelModifier;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -37,30 +38,36 @@ public class ProjectModelModificationServiceImpl extends ProjectModelModificatio
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDependency(@NotNull Module from, @NotNull Module to, @NotNull DependencyScope scope) {
|
||||
public Promise<Void> addDependency(@NotNull Module from, @NotNull Module to, @NotNull DependencyScope scope) {
|
||||
for (ProjectModelModifier modifier : getModelModifiers()) {
|
||||
if (modifier.addModuleDependency(from, to, scope)) {
|
||||
return;
|
||||
Promise<Void> promise = modifier.addModuleDependency(from, to, scope);
|
||||
if (promise != null) {
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
return Promise.REJECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDependency(@NotNull Collection<Module> from, @NotNull ExternalLibraryDescriptor libraryDescriptor, @NotNull DependencyScope scope) {
|
||||
public Promise<Void> addDependency(@NotNull Collection<Module> from, @NotNull ExternalLibraryDescriptor libraryDescriptor, @NotNull DependencyScope scope) {
|
||||
for (ProjectModelModifier modifier : getModelModifiers()) {
|
||||
if (modifier.addExternalLibraryDependency(from, libraryDescriptor, scope)) {
|
||||
return;
|
||||
Promise<Void> promise = modifier.addExternalLibraryDependency(from, libraryDescriptor, scope);
|
||||
if (promise != null) {
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
return Promise.REJECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDependency(@NotNull Module from, @NotNull Library library, @NotNull DependencyScope scope) {
|
||||
public Promise<Void> addDependency(@NotNull Module from, @NotNull Library library, @NotNull DependencyScope scope) {
|
||||
for (ProjectModelModifier modifier : getModelModifiers()) {
|
||||
if (modifier.addLibraryDependency(from, library, scope)) {
|
||||
return;
|
||||
Promise<Void> promise = modifier.addLibraryDependency(from, library, scope);
|
||||
if (promise != null) {
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
return Promise.REJECTED;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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 org.jetbrains.idea.maven.importing;
|
||||
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.DependencyScope;
|
||||
import com.intellij.openapi.roots.ExternalLibraryDescriptor;
|
||||
import com.intellij.openapi.roots.ProjectModelModifier;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
import com.intellij.util.text.VersionComparatorUtil;
|
||||
import com.intellij.util.xml.DomUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
import org.jetbrains.idea.maven.dom.MavenDomUtil;
|
||||
import org.jetbrains.idea.maven.dom.model.MavenDomDependency;
|
||||
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
|
||||
import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
|
||||
import org.jetbrains.idea.maven.model.MavenArtifact;
|
||||
import org.jetbrains.idea.maven.model.MavenConstants;
|
||||
import org.jetbrains.idea.maven.model.MavenId;
|
||||
import org.jetbrains.idea.maven.project.MavenProject;
|
||||
import org.jetbrains.idea.maven.project.MavenProjectsManager;
|
||||
import org.jetbrains.idea.maven.utils.library.RepositoryAttachHandler;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class MavenProjectModelModifier extends ProjectModelModifier {
|
||||
private final Project myProject;
|
||||
private final MavenProjectsManager myProjectsManager;
|
||||
private MavenProjectIndicesManager myIndicesManager;
|
||||
|
||||
public MavenProjectModelModifier(Project project, MavenProjectsManager projectsManager, MavenProjectIndicesManager manager) {
|
||||
myProject = project;
|
||||
myProjectsManager = projectsManager;
|
||||
myIndicesManager = manager;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Promise<Void> addModuleDependency(@NotNull Module from, @NotNull Module to, @NotNull final DependencyScope scope) {
|
||||
final MavenProject toProject = myProjectsManager.findProject(to);
|
||||
if (toProject == null) return null;
|
||||
MavenId mavenId = toProject.getMavenId();
|
||||
|
||||
return addDependency(Collections.singletonList(from), mavenId, scope);
|
||||
}
|
||||
|
||||
private Promise<Void> addDependency(@NotNull Collection<Module> fromModules, @NotNull final MavenId mavenId, @NotNull final DependencyScope scope) {
|
||||
final List<MavenDomProjectModel> models = new ArrayList<MavenDomProjectModel>(fromModules.size());
|
||||
List<XmlFile> files = new ArrayList<XmlFile>(fromModules.size());
|
||||
List<MavenProject> projectToUpdate = new ArrayList<MavenProject>(fromModules.size());
|
||||
for (Module from : fromModules) {
|
||||
if (!myProjectsManager.isMavenizedModule(from)) return null;
|
||||
MavenProject fromProject = myProjectsManager.findProject(from);
|
||||
if (fromProject == null) return null;
|
||||
|
||||
final MavenDomProjectModel model = MavenDomUtil.getMavenDomProjectModel(myProject, fromProject.getFile());
|
||||
if (model == null) return null;
|
||||
models.add(model);
|
||||
files.add(DomUtil.getFile(model));
|
||||
projectToUpdate.add(fromProject);
|
||||
}
|
||||
|
||||
new WriteCommandAction(myProject, "Add Maven Dependency", PsiUtilCore.toPsiFileArray(files)) {
|
||||
@Override
|
||||
protected void run(@NotNull Result result) throws Throwable {
|
||||
for (MavenDomProjectModel model : models) {
|
||||
MavenDomDependency dependency = MavenDomUtil.createDomDependency(model, null, mavenId);
|
||||
String mavenScope = getMavenScope(scope);
|
||||
if (mavenScope != null) {
|
||||
dependency.getScope().setStringValue(mavenScope);
|
||||
}
|
||||
Document document = PsiDocumentManager.getInstance(myProject).getDocument(DomUtil.getFile(model));
|
||||
if (document != null) {
|
||||
FileDocumentManager.getInstance().saveDocument(document);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
return myProjectsManager.forceUpdateProjects(projectToUpdate);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Promise<Void> addExternalLibraryDependency(@NotNull Collection<Module> modules,
|
||||
@NotNull ExternalLibraryDescriptor descriptor,
|
||||
@NotNull DependencyScope scope) {
|
||||
for (Module module : modules) {
|
||||
if (!myProjectsManager.isMavenizedModule(module)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String version = selectVersion(descriptor);
|
||||
MavenId mavenId = new MavenId(descriptor.getLibraryGroupId(), descriptor.getLibraryArtifactId(), version);
|
||||
return addDependency(modules, mavenId, scope);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String selectVersion(@NotNull ExternalLibraryDescriptor descriptor) {
|
||||
Set<String> versions = myIndicesManager.getVersions(descriptor.getLibraryGroupId(), descriptor.getLibraryArtifactId());
|
||||
List<String> suitableVersions = new ArrayList<String>();
|
||||
String minVersion = descriptor.getMinVersion();
|
||||
String maxVersion = descriptor.getMaxVersion();
|
||||
for (String version : versions) {
|
||||
if ((minVersion == null || VersionComparatorUtil.compare(minVersion, version) <= 0)
|
||||
&& (maxVersion == null || VersionComparatorUtil.compare(version, maxVersion) < 0)) {
|
||||
suitableVersions.add(version);
|
||||
}
|
||||
}
|
||||
return Collections.max(suitableVersions, VersionComparatorUtil.COMPARATOR);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Promise<Void> addLibraryDependency(@NotNull Module from, @NotNull Library library, @NotNull DependencyScope scope) {
|
||||
String name = library.getName();
|
||||
if (name != null && name.startsWith(MavenArtifact.MAVEN_LIB_PREFIX)) {
|
||||
//it would be better to use RepositoryLibraryType for libraries imported from Maven and fetch mavenId from the library properties instead
|
||||
String mavenCoordinates = StringUtil.trimStart(name, MavenArtifact.MAVEN_LIB_PREFIX);
|
||||
return addDependency(Collections.singletonList(from), RepositoryAttachHandler.getMavenId(mavenCoordinates), scope);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getMavenScope(DependencyScope scope) {
|
||||
switch (scope) {
|
||||
case RUNTIME:
|
||||
return MavenConstants.SCOPE_RUNTIME;
|
||||
case TEST:
|
||||
return MavenConstants.SCOPE_TEST;
|
||||
case PROVIDED:
|
||||
return MavenConstants.SCOPE_PROVIDED;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
-13
@@ -53,6 +53,8 @@ import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.concurrency.AsyncPromise;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
import org.jetbrains.idea.maven.importing.MavenDefaultModifiableModelsProvider;
|
||||
import org.jetbrains.idea.maven.importing.MavenFoldersImporter;
|
||||
import org.jetbrains.idea.maven.importing.MavenModifiableModelsProvider;
|
||||
@@ -780,8 +782,8 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
|
||||
doScheduleUpdateProjects(null, false, forceImportAndResolve);
|
||||
}
|
||||
|
||||
public void forceUpdateProjects(@NotNull Collection<MavenProject> projects) {
|
||||
doScheduleUpdateProjects(projects, true, true);
|
||||
public AsyncPromise<Void> forceUpdateProjects(@NotNull Collection<MavenProject> projects) {
|
||||
return doScheduleUpdateProjects(projects, true, true);
|
||||
}
|
||||
|
||||
public void forceUpdateAllProjectsOrFindAllAvailablePomFiles() {
|
||||
@@ -791,30 +793,34 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
|
||||
doScheduleUpdateProjects(null, true, true);
|
||||
}
|
||||
|
||||
private void doScheduleUpdateProjects(final Collection<MavenProject> projects,
|
||||
final boolean forceUpdate,
|
||||
final boolean forceImportAndResolve) {
|
||||
private AsyncPromise<Void> doScheduleUpdateProjects(final Collection<MavenProject> projects,
|
||||
final boolean forceUpdate,
|
||||
final boolean forceImportAndResolve) {
|
||||
final AsyncPromise<Void> promise = new AsyncPromise<Void>();
|
||||
MavenUtil.runWhenInitialized(myProject, new DumbAwareRunnable() {
|
||||
public void run() {
|
||||
if (projects == null) {
|
||||
myWatcher.scheduleUpdateAll(forceUpdate, forceImportAndResolve);
|
||||
myWatcher.scheduleUpdateAll(forceUpdate, forceImportAndResolve).processed(promise);
|
||||
}
|
||||
else {
|
||||
myWatcher.scheduleUpdate(MavenUtil.collectFiles(projects),
|
||||
Collections.<VirtualFile>emptyList(),
|
||||
forceUpdate,
|
||||
forceImportAndResolve);
|
||||
forceImportAndResolve).processed(promise);
|
||||
}
|
||||
}
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
public void scheduleImportAndResolve() {
|
||||
scheduleResolve(); // scheduleImport will be called after the scheduleResolve process has finished
|
||||
public Promise<List<Module>> scheduleImportAndResolve() {
|
||||
AsyncPromise<List<Module>> promise = scheduleResolve();// scheduleImport will be called after the scheduleResolve process has finished
|
||||
fireImportAndResolveScheduled();
|
||||
return promise;
|
||||
}
|
||||
|
||||
private void scheduleResolve() {
|
||||
private AsyncPromise<List<Module>> scheduleResolve() {
|
||||
final AsyncPromise<List<Module>> result = new AsyncPromise<List<Module>>();
|
||||
runWhenFullyOpen(new Runnable() {
|
||||
public void run() {
|
||||
LinkedHashSet<MavenProject> toResolve;
|
||||
@@ -830,7 +836,9 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
|
||||
Runnable onCompletion = it.hasNext() ? null : new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (hasScheduledProjects()) scheduleImport();
|
||||
if (hasScheduledProjects()) {
|
||||
scheduleImport().processed(result);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -839,6 +847,7 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public void evaluateEffectivePom(@NotNull final MavenProject mavenProject, @NotNull final NullableConsumer<String> consumer) {
|
||||
@@ -949,16 +958,18 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
|
||||
scheduleImport();
|
||||
}
|
||||
|
||||
private void scheduleImport() {
|
||||
private Promise<List<Module>> scheduleImport() {
|
||||
final AsyncPromise<List<Module>> result = new AsyncPromise<List<Module>>();
|
||||
runWhenFullyOpen(new Runnable() {
|
||||
public void run() {
|
||||
myImportingQueue.queue(new Update(MavenProjectsManager.this) {
|
||||
public void run() {
|
||||
importProjects();
|
||||
result.setResult(importProjects());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
|
||||
+33
-23
@@ -42,6 +42,7 @@ import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
|
||||
import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener;
|
||||
import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
@@ -50,6 +51,8 @@ import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.concurrency.AsyncPromise;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
import org.jetbrains.idea.maven.model.MavenConstants;
|
||||
import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
|
||||
import org.jetbrains.idea.maven.utils.MavenMergingUpdateQueue;
|
||||
@@ -270,38 +273,45 @@ public class MavenProjectsManagerWatcher {
|
||||
scheduleUpdateAll(false, false);
|
||||
}
|
||||
|
||||
public void scheduleUpdateAll(boolean force, final boolean forceImportAndResolve) {
|
||||
Runnable onCompletion = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myProject.isDisposed()) return;
|
||||
|
||||
if (forceImportAndResolve || myManager.getImportingSettings().isImportAutomatically()) {
|
||||
myManager.scheduleImportAndResolve();
|
||||
}
|
||||
}
|
||||
};
|
||||
public Promise<Void> scheduleUpdateAll(boolean force, final boolean forceImportAndResolve) {
|
||||
final AsyncPromise<Void> promise = new AsyncPromise<Void>();
|
||||
Runnable onCompletion = createScheduleImportAction(forceImportAndResolve, promise);
|
||||
myReadingProcessor.scheduleTask(new MavenProjectsProcessorReadingTask(force, myProjectsTree, myGeneralSettings, onCompletion));
|
||||
return promise;
|
||||
}
|
||||
|
||||
public void scheduleUpdate(List<VirtualFile> filesToUpdate,
|
||||
List<VirtualFile> filesToDelete,
|
||||
boolean force,
|
||||
final boolean forceImportAndResolve) {
|
||||
Runnable onCompletion = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (forceImportAndResolve || myManager.getImportingSettings().isImportAutomatically()) {
|
||||
myManager.scheduleImportAndResolve();
|
||||
}
|
||||
}
|
||||
};
|
||||
public Promise<Void> scheduleUpdate(List<VirtualFile> filesToUpdate,
|
||||
List<VirtualFile> filesToDelete,
|
||||
boolean force,
|
||||
final boolean forceImportAndResolve) {
|
||||
final AsyncPromise<Void> promise = new AsyncPromise<Void>();
|
||||
Runnable onCompletion = createScheduleImportAction(forceImportAndResolve, promise);
|
||||
myReadingProcessor.scheduleTask(new MavenProjectsProcessorReadingTask(filesToUpdate,
|
||||
filesToDelete,
|
||||
force,
|
||||
myProjectsTree,
|
||||
myGeneralSettings,
|
||||
onCompletion));
|
||||
return promise;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Runnable createScheduleImportAction(final boolean forceImportAndResolve, final AsyncPromise<Void> promise) {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myProject.isDisposed()) return;
|
||||
|
||||
if (forceImportAndResolve || myManager.getImportingSettings().isImportAutomatically()) {
|
||||
myManager.scheduleImportAndResolve().done(new Consumer<List<Module>>() {
|
||||
@Override
|
||||
public void consume(List<Module> modules) {
|
||||
promise.setResult(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void onSettingsChange() {
|
||||
|
||||
@@ -180,6 +180,7 @@
|
||||
|
||||
<postStartupActivity implementation="org.jetbrains.idea.maven.utils.MavenRehighlighter$MavenRehighlighterPostStartupActivity"/>
|
||||
<projectService serviceImplementation="org.jetbrains.idea.maven.utils.MavenRehighlighter"/>
|
||||
<projectModelModifier implementation="org.jetbrains.idea.maven.importing.MavenProjectModelModifier"/>
|
||||
<library.dependencyScopeSuggester implementation="org.jetbrains.idea.maven.utils.library.RepositoryLibraryDependencyScopeSuggester"/>
|
||||
</extensions>
|
||||
|
||||
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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 org.jetbrains.idea.maven.actions;
|
||||
|
||||
import com.intellij.openapi.roots.DependencyScope;
|
||||
import com.intellij.openapi.roots.ExternalLibraryDescriptor;
|
||||
import com.intellij.openapi.roots.ProjectModelModifier;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
import org.jetbrains.idea.maven.dom.MavenDomWithIndicesTestCase;
|
||||
import org.jetbrains.idea.maven.importing.MavenProjectModelModifier;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class MavenProjectModelModifierTest extends MavenDomWithIndicesTestCase {
|
||||
public void testAddExternalLibraryDependency() throws IOException {
|
||||
importProject("<groupId>test</groupId>" +
|
||||
"<artifactId>project</artifactId>" +
|
||||
"<version>1</version>");
|
||||
|
||||
Promise<Void> result =
|
||||
getExtension().addExternalLibraryDependency(Collections.singletonList(getModule("project")), new CommonsIoLibraryDescriptor(),
|
||||
DependencyScope.COMPILE);
|
||||
assertNotNull(result);
|
||||
String version = assertHasDependency(myProjectPom, "junit", "junit");
|
||||
waitUntilImported(result);
|
||||
assertModuleLibDep("project", "Maven: junit:junit:" + version);
|
||||
}
|
||||
|
||||
public void testAddModuleDependency() throws IOException {
|
||||
createTwoModulesPom("m1", "m2");
|
||||
VirtualFile m1 = createModulePom("m1", "<groupId>test</groupId>" +
|
||||
"<artifactId>m1</artifactId>" +
|
||||
"<version>1</version>");
|
||||
createModulePom("m2", "<groupId>test</groupId>" +
|
||||
"<artifactId>m2</artifactId>" +
|
||||
"<version>1</version>");
|
||||
importProject();
|
||||
|
||||
Promise<Void> result = getExtension().addModuleDependency(getModule("m1"), getModule("m2"), DependencyScope.COMPILE);
|
||||
assertNotNull(result);
|
||||
assertHasDependency(m1, "test", "m2");
|
||||
waitUntilImported(result);
|
||||
assertModuleModuleDeps("m1", "m2");
|
||||
}
|
||||
|
||||
public void testAddLibraryDependency() throws IOException {
|
||||
createTwoModulesPom("m1", "m2");
|
||||
VirtualFile m1 = createModulePom("m1", "<groupId>test</groupId>" +
|
||||
"<artifactId>m1</artifactId>" +
|
||||
"<version>1</version>");
|
||||
createModulePom("m2", "<groupId>test</groupId>" +
|
||||
"<artifactId>m2</artifactId>" +
|
||||
"<version>1</version>" +
|
||||
"<dependencies>" +
|
||||
" <dependency>" +
|
||||
" <groupId>junit</groupId>" +
|
||||
" <artifactId>junit</artifactId>" +
|
||||
" <version>4.0</version>" +
|
||||
" <scope>test</scope>" +
|
||||
" </dependency>" +
|
||||
"</dependencies>");
|
||||
importProject();
|
||||
|
||||
String libName = "Maven: junit:junit:4.0";
|
||||
assertModuleLibDep("m2", libName);
|
||||
Library library = LibraryTablesRegistrar.getInstance().getLibraryTable(myProject).getLibraryByName(libName);
|
||||
assertNotNull(library);
|
||||
Promise<Void> result = getExtension().addLibraryDependency(getModule("m1"), library, DependencyScope.COMPILE);
|
||||
assertNotNull(result);
|
||||
assertHasDependency(m1, "junit", "junit");
|
||||
waitUntilImported(result);
|
||||
assertModuleLibDep("m1", libName);
|
||||
}
|
||||
|
||||
private void createTwoModulesPom(final String m1, final String m2) throws IOException {
|
||||
createProjectPom("<groupId>test</groupId>" +
|
||||
"<artifactId>project</artifactId>" +
|
||||
"<packaging>pom</packaging>" +
|
||||
"<version>1</version>" +
|
||||
"<modules>" +
|
||||
" <module>" + m1 + "</module>" +
|
||||
" <module>" + m2 + "</module>" +
|
||||
"</modules>");
|
||||
}
|
||||
|
||||
private String assertHasDependency(VirtualFile pom, final String groupId, final String artifactId) {
|
||||
String pomText = PsiManager.getInstance(myProject).findFile(pom).getText();
|
||||
Pattern
|
||||
pattern = Pattern.compile("(?s).*<dependency>\\s*<groupId>" + groupId + "</groupId>\\s*<artifactId>" +
|
||||
artifactId + "</artifactId>\\s*<version>(.*)</version>\\s*</dependency>.*");
|
||||
Matcher matcher = pattern.matcher(pomText);
|
||||
assertTrue(matcher.matches());
|
||||
return matcher.group(1);
|
||||
}
|
||||
|
||||
private void waitUntilImported(Promise<Void> result) {
|
||||
waitForReadingCompletion();
|
||||
myProjectsManager.waitForResolvingCompletion();
|
||||
myProjectsManager.waitForArtifactsDownloadingCompletion();
|
||||
performPostImportTasks();
|
||||
myProjectsManager.performScheduledImportInTests();
|
||||
assertSame(Promise.State.FULFILLED, result.getState());
|
||||
}
|
||||
|
||||
private MavenProjectModelModifier getExtension() {
|
||||
return ContainerUtil.findInstance(ProjectModelModifier.EP_NAME.getExtensions(myProject), MavenProjectModelModifier.class);
|
||||
}
|
||||
|
||||
private static class CommonsIoLibraryDescriptor extends ExternalLibraryDescriptor {
|
||||
public CommonsIoLibraryDescriptor() {
|
||||
super("junit", "junit");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getLibraryClassesRoots() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user