From d180dfacc3ef4f602eca704ad9c5987cf2b16b9c Mon Sep 17 00:00:00 2001 From: azerr Date: Mon, 9 Oct 2023 17:20:07 +0200 Subject: [PATCH] perf: Improve performance of Quarkus deployment jar support Fixes #1143 Signed-off-by: azerr --- .../ClasspathResourceChangedManager.java | 14 +- .../ClasspathResourceChangedNotifier.java | 25 +- .../lsp4mp4ij/psi/core/PropertiesManager.java | 9 +- .../quarkus/ProgressIndicatorWrapper.java | 129 +++++++++ .../quarkus/QuarkusDeploymentSupport.java | 274 ++++++++++++++++++ .../intellij/quarkus/QuarkusModuleUtil.java | 110 +------ .../quarkus/QuarkusProjectService.java | 170 +++++------ .../quarkus/lsp/QuarkusLanguageClient.java | 29 +- .../quarkus/maven/MavenToolDelegate.java | 60 ++-- .../intellij/quarkus/tool/ToolDelegate.java | 21 ++ src/main/resources/META-INF/plugin.xml | 1 + .../devtools/intellij/GradleTestCase.java | 16 +- .../MavenModuleImportingTestCase.java | 3 - ...esManagerLocationConfigQuickstartTest.java | 5 +- ...opertiesManagerLocationUsingVertxTest.java | 3 +- .../LSP4MPMavenModuleImportingTestCase.java | 12 +- .../core/MicroProfileMavenProjectName.java | 1 + .../PropertiesManagerClassPathKindTest.java | 2 +- .../core/PropertiesManagerLocationTest.java | 4 +- .../ConfigItemIntBoolDefaultValueTest.java | 2 +- .../MicroProfileConfigPropertyTest.java | 4 +- ...MicroProfileHealthJavaDiagnosticsTest.java | 8 +- .../MicroProfileRegisterRestClientTest.java | 2 +- .../completion/GradleQuarkusLibraryTest.java | 3 + ...enApplicationPropertiesCompletionTest.java | 18 +- .../completion/MavenQuarkusLibraryTest.java | 6 +- ...kusConfigRootAllQuarkusExtensionsTest.java | 7 +- ...uarkusConfigRootHibernateRestEasyTest.java | 6 +- .../quarkus/MavenQuarkusConfigRootTest.java | 4 +- .../MavenQuarkusHibernateORMPropertyTest.java | 2 +- .../psi/quarkus/QuarkusKubernetesTest.java | 8 +- .../QuarkusMavenModuleImportingTestCase.java | 12 +- 32 files changed, 662 insertions(+), 308 deletions(-) create mode 100644 src/main/java/com/redhat/devtools/intellij/quarkus/ProgressIndicatorWrapper.java create mode 100644 src/main/java/com/redhat/devtools/intellij/quarkus/QuarkusDeploymentSupport.java diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/classpath/ClasspathResourceChangedManager.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/classpath/ClasspathResourceChangedManager.java index fbff7dff7..e840d5a07 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/classpath/ClasspathResourceChangedManager.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/classpath/ClasspathResourceChangedManager.java @@ -69,13 +69,10 @@ public interface Listener { private final Project project; - private final List preprocessors; - public ClasspathResourceChangedManager(Project project) { this.project = project; - this.preprocessors = new ArrayList<>(); // Send source files changed in debounce mode - this.resourceChangedNotifier = new ClasspathResourceChangedNotifier(project, preprocessors); + this.resourceChangedNotifier = new ClasspathResourceChangedNotifier(project); listener = new ClasspathResourceChangedListener(this); projectConnection = project.getMessageBus().connect(); // Track end of Java libraries update @@ -105,13 +102,4 @@ Project getProject() { ClasspathResourceChangedNotifier getResourceChangedNotifier() { return resourceChangedNotifier; } - - /** - * Add a preprocessor to update classpatch when a library changed before sending the {@link Listener#librariesChanged()} event. - * - * @param preprocessor the preprocessor to add. - */ - public void addPreprocessor(RunnableProgress preprocessor) { - preprocessors.add(preprocessor); - } } diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/classpath/ClasspathResourceChangedNotifier.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/classpath/ClasspathResourceChangedNotifier.java index a2cac68c1..dfb955f6a 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/classpath/ClasspathResourceChangedNotifier.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/classpath/ClasspathResourceChangedNotifier.java @@ -14,11 +14,9 @@ package com.redhat.devtools.intellij.lsp4mp4ij.classpath; import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.module.Module; -import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; @@ -27,10 +25,10 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; -import java.util.stream.Collectors; +import java.util.HashSet; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; /** * Source file change notifier with a debounce mode. @@ -46,12 +44,10 @@ public class ClasspathResourceChangedNotifier implements Disposable { private final Set> sourceFiles; private boolean librariesChanged; - private final List processBeforeLibrariesChanged; private boolean disposed; - public ClasspathResourceChangedNotifier(Project project, List preprocessors) { + public ClasspathResourceChangedNotifier(Project project) { this.project = project; - this.processBeforeLibrariesChanged = preprocessors; sourceFiles = new HashSet<>(); } @@ -107,11 +103,7 @@ private void notifyChanges() { } if (librariesChanged) { // Java Libraries has changed - if (processBeforeLibrariesChanged.isEmpty() || ApplicationManager.getApplication().isUnitTestMode()) { - // No preprocessor or Test context, send directly the librariesChanged event. - for (var runnable : processBeforeLibrariesChanged) { - runnable.run(new EmptyProgressIndicator()); - } + if (ApplicationManager.getApplication().isUnitTestMode()) { // Send the libraries changed event project.getMessageBus().syncPublisher(ClasspathResourceChangedManager.TOPIC).librariesChanged(); librariesChanged = false; @@ -125,9 +117,6 @@ public void run(@NotNull ProgressIndicator progressIndicator) { // Execute preprocessor progressIndicator.setIndeterminate(false); progressIndicator.checkCanceled(); - for (var runnable : processBeforeLibrariesChanged) { - runnable.run(progressIndicator); - } } finally { // Send the libraries changed event project.getMessageBus().syncPublisher(ClasspathResourceChangedManager.TOPIC).librariesChanged(); @@ -152,7 +141,7 @@ public void dispose() { this.disposed = true; if (debounceTask != null) { debounceTask.cancel(); - debounceTask =null; + debounceTask = null; } if (debounceTimer != null) { debounceTimer.cancel(); diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/PropertiesManager.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/PropertiesManager.java index 4086f91b0..d8c6ec834 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/PropertiesManager.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/PropertiesManager.java @@ -153,17 +153,16 @@ private static MicroProfileProjectInfo createInfo(Module module, ClasspathKind c return info; } - private SearchScope createSearchScope(Module module, List scopes, + private SearchScope createSearchScope(@NotNull Module module, List scopes, boolean excludeTestCode) { - SearchScope searchScope = GlobalSearchScope.EMPTY_SCOPE; - + SearchScope searchScope = GlobalSearchScope.moduleRuntimeScope(module, !excludeTestCode); for (MicroProfilePropertiesScope scope : scopes) { switch (scope) { case sources: - searchScope = module != null ? searchScope.union(module.getModuleScope(!excludeTestCode)) : searchScope; + searchScope = searchScope.union(module.getModuleScope(!excludeTestCode)); break; case dependencies: - searchScope = module != null ? searchScope.union(module.getModuleWithLibrariesScope()) : searchScope; + searchScope = searchScope.union(module.getModuleWithLibrariesScope()); break; /*added missing default case */ default: diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/ProgressIndicatorWrapper.java b/src/main/java/com/redhat/devtools/intellij/quarkus/ProgressIndicatorWrapper.java new file mode 100644 index 000000000..310ee3211 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/ProgressIndicatorWrapper.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2023 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, + * and is available at https://www.eclipse.org/legal/epl-v20.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.redhat.devtools.intellij.quarkus; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.impl.CoreProgressManager; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.NlsContexts; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Progress indicator wrapper. + */ +public class ProgressIndicatorWrapper implements ProgressIndicator { + + private final ProgressIndicator progressIndicator; + + public ProgressIndicatorWrapper(ProgressIndicator progressIndicator) { + this.progressIndicator = progressIndicator; + + } + public void start() { + progressIndicator.start(); + } + + public void stop() { + progressIndicator.stop(); + } + + public boolean isRunning() { + return progressIndicator.isRunning(); + } + + public void cancel() { + progressIndicator.cancel(); + } + + public boolean isCanceled() { + return progressIndicator.isCanceled(); + } + + public void setText(@NlsContexts.ProgressText String text) { + progressIndicator.setText(text); + } + + @NlsContexts.ProgressText + public String getText() { + return progressIndicator.getText(); + } + + public void setText2(@NlsContexts.ProgressDetails String text) { + progressIndicator.setText2(text); + } + + @NlsContexts.ProgressDetails + public String getText2() { + return progressIndicator.getText2(); + } + + public double getFraction() { + return progressIndicator.getFraction(); + } + + public void setFraction(double fraction) { + progressIndicator.setFraction(fraction); + } + + public void pushState() { + progressIndicator.pushState(); + } + + public void popState() { + progressIndicator.popState(); + } + + public boolean isModal() { + return progressIndicator.isModal(); + } + + public @NotNull ModalityState getModalityState() { + return progressIndicator.getModalityState(); + } + + public void setModalityProgress(@Nullable ProgressIndicator modalityProgress) { + progressIndicator.setModalityProgress(modalityProgress); + } + + public boolean isIndeterminate() { + return progressIndicator.isIndeterminate(); + } + + public void setIndeterminate(boolean indeterminate) { + progressIndicator.setIndeterminate(indeterminate); + } + + public void checkCanceled() throws ProcessCanceledException { + progressIndicator.checkCanceled(); + if (isCanceled() /*&& isCancelable()*/) { + Throwable trace = getCancellationTrace(); + throw trace instanceof ProcessCanceledException ? (ProcessCanceledException)trace : new ProcessCanceledException(trace); + } + } + + protected @Nullable Throwable getCancellationTrace() { + return this instanceof Disposable ? Disposer.getDisposalTrace((Disposable)this) : null; + } + + public boolean isPopupWasShown() { + return progressIndicator.isPopupWasShown(); + } + + public boolean isShowing() { + return progressIndicator.isShowing(); + } + +} diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/QuarkusDeploymentSupport.java b/src/main/java/com/redhat/devtools/intellij/quarkus/QuarkusDeploymentSupport.java new file mode 100644 index 000000000..9483aa8e8 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/QuarkusDeploymentSupport.java @@ -0,0 +1,274 @@ +/******************************************************************************* + * Copyright (c) 2023 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, + * and is available at https://www.eclipse.org/legal/epl-v20.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.redhat.devtools.intellij.quarkus; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.*; +import com.intellij.openapi.roots.impl.OrderEntryUtil; +import com.intellij.openapi.roots.impl.libraries.LibraryEx; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.roots.libraries.LibraryTable; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.messages.MessageBusConnection; +import com.redhat.devtools.intellij.lsp4mp4ij.classpath.ClasspathResourceChangedManager; +import com.redhat.devtools.intellij.quarkus.search.QuarkusModuleComponent; +import com.redhat.devtools.intellij.quarkus.tool.ToolDelegate; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; + +import static com.redhat.devtools.intellij.quarkus.QuarkusModuleUtil.isQuarkusModule; + +/** + * Quarkus deployment support provides the capability to collect, download and add to a module classpath the Quarkus deployment dependencies. + */ +public class QuarkusDeploymentSupport implements ClasspathResourceChangedManager.Listener, Disposable { + + private static final Logger LOGGER = LoggerFactory.getLogger(QuarkusDeploymentSupport.class); + private static final Key> QUARKUS_DEPLOYMENT_SUPPORT_KEY = new Key<>(QuarkusDeploymentSupport.class.getName()); + + private final MessageBusConnection connection; + private final Project project; + + public static QuarkusDeploymentSupport getInstance(Project project) { + return ServiceManager.getService(project, QuarkusDeploymentSupport.class); + } + + public QuarkusDeploymentSupport(Project project) { + this.project = project; + connection = project.getMessageBus().connect(project); + connection.subscribe(ClasspathResourceChangedManager.TOPIC, this); + } + + /** + * Update module classpath with Quarkus deployment dependencies if needed in async mode. + * + * @param module the module. + * @return the future which updates the classpath. + */ + public CompletableFuture updateClasspathWithQuarkusDeploymentAsync(Module module) { + CompletableFuture deploymentSupport = module.getUserData(QUARKUS_DEPLOYMENT_SUPPORT_KEY); + if (isOutOfDated(deploymentSupport)) { + return internalUpdateClasspathWithQuarkusDeployment(module); + } + return deploymentSupport; + } + + /** + * Update module classpath with Quarkus deployment dependencies if needed. + * + * @param module the module. + * @param progressIndicator the progress indicator. + */ + public static void updateClasspathWithQuarkusDeployment(Module module, ProgressIndicator progressIndicator) { + if (module.isDisposed()) + return; + LOGGER.info("Ensuring library to " + module.getName()); + long start = System.currentTimeMillis(); + ToolDelegate toolDelegate = ToolDelegate.getDelegate(module); + if (toolDelegate != null) { + LOGGER.info("Tool delegate found for " + module.getName()); + if (isQuarkusModule(module)) { + LOGGER.info("isQuarkus module " + module.getName()); + QuarkusModuleComponent component = module.getComponent(QuarkusModuleComponent.class); + Integer previousHash = component.getHash(); + Integer actualHash = computeHash(module); + var qlib = OrderEntryUtil.findLibraryOrderEntry(ModuleRootManager.getInstance(module), QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME); + if (qlib == null || (actualHash != null && !actualHash.equals(previousHash)) || + !QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_VERSION.equals(component.getVersion())) { + ModuleRootModificationUtil.updateModel(module, model -> { + LibraryTable table = model.getModuleLibraryTable(); + Library library = table.getLibraryByName(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME); + while (library != null) { + table.removeLibrary(library); + try { + TelemetryService.instance().action(TelemetryService.MODEL_PREFIX + "removeLibrary"); + } catch (Exception e) { + + } + library = table.getLibraryByName(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME); + } + progressIndicator.checkCanceled(); + progressIndicator.setText("Adding in ''" + module.getName() + "'' Quarkus deployment dependencies to classpath..."); + List[] files = toolDelegate.getDeploymentFiles(module, progressIndicator); + LOGGER.info("Adding library to " + module.getName() + " previousHash=" + previousHash + " newHash=" + actualHash); + try { + TelemetryService.instance().action(TelemetryService.MODEL_PREFIX + "addLibrary").send(); + } catch (Exception e) { + + } + addLibrary(model, files); + }); + component.setHash(actualHash); + component.setVersion(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_VERSION); + } + } + } + LOGGER.info("ensureQuarkusLibrary ran in " + (System.currentTimeMillis() - start)); + } + + + private static boolean isOutOfDated(CompletableFuture loader) { + return loader == null; + } + + @NotNull + private synchronized static CompletableFuture internalUpdateClasspathWithQuarkusDeployment(Module module) { + CompletableFuture deploymentSupport = module.getUserData(QUARKUS_DEPLOYMENT_SUPPORT_KEY); + if (!isOutOfDated(deploymentSupport)) { + return deploymentSupport; + } + var project = module.getProject(); + final CompletableFuture future = new CompletableFuture<>(); + CompletableFuture.runAsync(() -> { + Runnable task = () -> ProgressManager.getInstance().run(new Task.Backgroundable(project, "Adding Quarkus deployment dependencies to classpath...") { + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + long start = System.currentTimeMillis(); + ProgressIndicator wrappedIndicator = new ProgressIndicatorWrapper(indicator) { + + @Override + public boolean isCanceled() { + return super.isCanceled() || future.isCancelled(); + } + }; + updateClasspathWithQuarkusDeployment(module, wrappedIndicator); + long elapsed = System.currentTimeMillis() - start; + LOGGER.info("Ensured QuarkusLibrary in " + elapsed + " ms"); + future.complete(null); + } catch (CancellationException | ProcessCanceledException e) { + future.cancel(true); + } catch (Exception e) { + LOGGER.error("Error while adding Quarkus deployment dependencies to classpath in '" + module.getName() + "'", e); + future.completeExceptionally(e); + } + } + }); + if (DumbService.getInstance(project).isDumb()) { + DumbService.getInstance(project).runWhenSmart(task); + } else { + task.run(); + } + }); + module.putUserData(QUARKUS_DEPLOYMENT_SUPPORT_KEY, future); + return future; + } + + private static void addLibrary(ModifiableRootModel model, List[] quarkusDeploymentDependencies) { + // Create Quarkus Deployment library. + LibraryEx library = (LibraryEx) model.getModuleLibraryTable().createLibrary(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME); + LibraryEx.ModifiableModelEx libraryModel = library.getModifiableModel(); + + // Add quarkus deployment dependencies binaries + for (VirtualFile rootFile : quarkusDeploymentDependencies[ToolDelegate.BINARY]) { + libraryModel.addRoot(rootFile, OrderRootType.CLASSES); + } + // Add quarkus deployment dependencies sources + for (VirtualFile rootFile : quarkusDeploymentDependencies[ToolDelegate.SOURCES]) { + libraryModel.addRoot(rootFile, OrderRootType.SOURCES); + } + + LibraryOrderEntry entry = model.findLibraryOrderEntry(library); + assert entry != null : library; + entry.setScope(DependencyScope.RUNTIME); + entry.setExported(false); + + // Update classpath + ApplicationManager.getApplication().invokeAndWait(() -> { + WriteAction.run(libraryModel::commit); + }); + } + + private static Integer computeHash(Module module) { + ModuleRootManager manager = ModuleRootManager.getInstance(module); + Set files = manager.processOrder(new RootPolicy>() { + @Override + public Set visitLibraryOrderEntry(@NotNull LibraryOrderEntry libraryOrderEntry, Set value) { + if (!isQuarkusDeploymentLibrary(libraryOrderEntry) && isQuarkusExtensionWithDeploymentArtifact(libraryOrderEntry.getLibrary())) { + for (VirtualFile file : libraryOrderEntry.getFiles(OrderRootType.CLASSES)) { + value.add(file.getPath()); + } + } + return value; + } + }, new HashSet<>()); + return files.isEmpty() ? null : files.hashCode(); + } + + + private static boolean isQuarkusDeploymentLibrary(@NotNull LibraryOrderEntry libraryOrderEntry) { + return libraryOrderEntry.getLibraryName() != null && + libraryOrderEntry.getLibraryName().equalsIgnoreCase(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME); + } + + + private static boolean isQuarkusExtensionWithDeploymentArtifact(@Nullable Library library) { + if (library != null) { + for (VirtualFile vFile : library.getFiles(OrderRootType.CLASSES)) { + if (vFile.isDirectory() && ToolDelegate.hasExtensionProperties(VfsUtilCore.virtualToIoFile(vFile))) { + return true; + } + } + } + return false; + } + + @Override + public void dispose() { + connection.dispose(); + cancelFutures(); + } + + @Override + public void librariesChanged() { + cancelFutures(); + } + + private void cancelFutures() { + if (!project.isDisposed()) { + for (var module : ModuleManager.getInstance(project).getModules()) { + CompletableFuture loader = module.getUserData(QUARKUS_DEPLOYMENT_SUPPORT_KEY); + if (loader != null) { + loader.cancel(true); + module.putUserData(QUARKUS_DEPLOYMENT_SUPPORT_KEY, null); + } + } + } + } + + @Override + public void sourceFilesChanged(Set> sources) { + // Do nothing + } + +} diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/QuarkusModuleUtil.java b/src/main/java/com/redhat/devtools/intellij/quarkus/QuarkusModuleUtil.java index 82edd8c72..27cfef282 100644 --- a/src/main/java/com/redhat/devtools/intellij/quarkus/QuarkusModuleUtil.java +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/QuarkusModuleUtil.java @@ -38,10 +38,12 @@ import com.redhat.devtools.intellij.quarkus.search.QuarkusModuleComponent; import com.redhat.devtools.intellij.quarkus.tool.ToolDelegate; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; +import java.text.MessageFormat; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -60,101 +62,6 @@ public class QuarkusModuleUtil { public static final Pattern APPLICATION_YAML = Pattern.compile("application(-.+)?\\.ya?ml"); - public static boolean isQuarkusExtensionWithDeploymentArtifact(Library library) { - boolean result = false; - if (library != null) { - VirtualFile[] files = library.getFiles(OrderRootType.CLASSES); - - for(int i=0; !result && i < files.length;++i) { - if (files[i].isDirectory()) { - result = ToolDelegate.getDeploymentJarId(VfsUtilCore.virtualToIoFile(files[i])) != null; - } - } - } - return result; - } - - /** - * Check if the Quarkus library needs to be recomputed and update it if required. - * - * @param module the module to check - * @param progressIndicator - */ - public static void ensureQuarkusLibrary(Module module, ProgressIndicator progressIndicator) { - if (module.isDisposed()) - return; - LOGGER.info("Ensuring library to " + module.getName()); - long start = System.currentTimeMillis(); - ToolDelegate toolDelegate = ToolDelegate.getDelegate(module); - if (toolDelegate != null) { - LOGGER.info("Tool delegate found for " + module.getName()); - if (isQuarkusModule(module)) { - LOGGER.info("isQuarkus module " + module.getName()); - QuarkusModuleComponent component = module.getComponent(QuarkusModuleComponent.class); - Integer previousHash = component.getHash(); - Integer actualHash = computeHash(module); - var qlib = OrderEntryUtil.findLibraryOrderEntry(ModuleRootManager.getInstance(module), QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME); - if (qlib == null || (actualHash != null && !actualHash.equals(previousHash)) || - !QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_VERSION.equals(component.getVersion())){ - ModuleRootModificationUtil.updateModel(module, model -> { - LibraryTable table = model.getModuleLibraryTable(); - Library library = table.getLibraryByName(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME); - while (library != null) { - table.removeLibrary(library); - TelemetryService.instance().action(TelemetryService.MODEL_PREFIX + "removeLibrary"); - library = table.getLibraryByName(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME); - } - progressIndicator.checkCanceled(); - progressIndicator.setText("Collecting Quarkus deployment dependencies..."); - List[] files = toolDelegate.getDeploymentFiles(module, progressIndicator); - LOGGER.info("Adding library to " + module.getName() + " previousHash=" + previousHash + " newHash=" + actualHash); - TelemetryService.instance().action(TelemetryService.MODEL_PREFIX + "addLibrary").send(); - addLibrary(model, files, module); - }); - component.setHash(actualHash); - component.setVersion(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_VERSION); - } - } - } - LOGGER.info("ensureQuarkusLibrary ran in " + (System.currentTimeMillis() - start)); - } - - private static void addLibrary(ModifiableRootModel model, List[] files, Module module) { - LibraryEx library = (LibraryEx)model.getModuleLibraryTable().createLibrary(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME); - LibraryEx.ModifiableModelEx libraryModel = library.getModifiableModel(); - - for (VirtualFile rootFile : files[ToolDelegate.BINARY]) { - libraryModel.addRoot(rootFile, OrderRootType.CLASSES); - } - for (VirtualFile rootFile : files[ToolDelegate.SOURCES]) { - libraryModel.addRoot(rootFile, OrderRootType.SOURCES); - } - - LibraryOrderEntry entry = model.findLibraryOrderEntry(library); - assert entry != null : library; - entry.setScope(DependencyScope.PROVIDED); - entry.setExported(false); - ApplicationManager.getApplication().invokeAndWait(() -> { - WriteAction.run(libraryModel::commit); - }); - } - - private static Integer computeHash(Module module) { - ModuleRootManager manager = ModuleRootManager.getInstance(module); - Set files = manager.processOrder(new RootPolicy>() { - @Override - public Set visitLibraryOrderEntry(@NotNull LibraryOrderEntry libraryOrderEntry, Set value) { - if (!isQuarkusDeploymentLibrary(libraryOrderEntry) && isQuarkusExtensionWithDeploymentArtifact(libraryOrderEntry.getLibrary())) { - for(VirtualFile file : libraryOrderEntry.getFiles(OrderRootType.CLASSES)) { - value.add(file.getPath()); - } - } - return value; - } - }, new HashSet<>()); - return files.isEmpty()?null:files.hashCode(); - } - /** * Check if the module is a Quarkus project. Should check if some class if present * but it seems PSI is not available when the module is added thus we rely on the @@ -174,13 +81,8 @@ public Boolean visitLibraryOrderEntry(@NotNull LibraryOrderEntry libraryOrderEnt } public static boolean isQuarkusLibrary(@NotNull LibraryOrderEntry libraryOrderEntry) { - return libraryOrderEntry.getLibraryName() != null && - libraryOrderEntry.getLibraryName().contains(QuarkusConstants.QUARKUS_CORE_PREFIX); - } - - public static boolean isQuarkusDeploymentLibrary(@NotNull LibraryOrderEntry libraryOrderEntry) { return libraryOrderEntry.getLibraryName() != null && - libraryOrderEntry.getLibraryName().equalsIgnoreCase(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME); + libraryOrderEntry.getLibraryName().contains(QuarkusConstants.QUARKUS_CORE_PREFIX); } private static final Pattern QUARKUS_CORE_PATTERN = Pattern.compile("quarkus-core-(\\d[a-zA-Z\\d-.]+?).jar"); @@ -204,9 +106,9 @@ public static boolean checkQuarkusVersion(Module module, Predicate pred .findFirst(); if (quarkusCoreJar.isPresent()) { Matcher quarkusCoreArtifactMatcher = QUARKUS_CORE_PATTERN.matcher(quarkusCoreJar.get().getName()); - if(quarkusCoreArtifactMatcher.matches()) { + if (quarkusCoreArtifactMatcher.matches()) { String quarkusVersion = quarkusCoreArtifactMatcher.group(1); - LOGGER.debug("Detected Quarkus version = " + quarkusVersion); + LOGGER.debug("Detected Quarkus version = " + quarkusVersion); Matcher quarkusVersionMatcher = QUARKUS_STANDARD_VERSIONING.matcher(quarkusVersion); return predicate.test(quarkusVersionMatcher); } else { @@ -219,7 +121,7 @@ public static boolean checkQuarkusVersion(Module module, Predicate pred public static Set getModulesURIs(Project project) { Set uris = new HashSet<>(); - for(Module module : ModuleManager.getInstance(project).getModules()) { + for (Module module : ModuleManager.getInstance(project).getModules()) { uris.add(PsiUtilsLSImpl.getProjectURI(module)); } return uris; diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/QuarkusProjectService.java b/src/main/java/com/redhat/devtools/intellij/quarkus/QuarkusProjectService.java index 97636622c..32a8649a5 100644 --- a/src/main/java/com/redhat/devtools/intellij/quarkus/QuarkusProjectService.java +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/QuarkusProjectService.java @@ -10,17 +10,14 @@ ******************************************************************************/ package com.redhat.devtools.intellij.quarkus; -import com.intellij.ProjectTopics; import com.intellij.json.JsonFileType; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.DumbService; -import com.intellij.openapi.project.ModuleListener; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -35,7 +32,6 @@ import org.eclipse.lsp4mp.commons.MicroProfileProjectInfo; import org.eclipse.lsp4mp.commons.MicroProfilePropertiesScope; import org.eclipse.lsp4mp.utils.JSONSchemaUtils; -import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,112 +40,84 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -public class QuarkusProjectService implements ClasspathResourceChangedManager.Listener, Disposable, ModuleListener { - private static final Logger LOGGER = LoggerFactory.getLogger(QuarkusProjectService.class); +public class QuarkusProjectService implements ClasspathResourceChangedManager.Listener, Disposable { + private static final Logger LOGGER = LoggerFactory.getLogger(QuarkusProjectService.class); - private final Map> schemas = new ConcurrentHashMap<>(); + private final Map> schemas = new ConcurrentHashMap<>(); - public static QuarkusProjectService getInstance(Project project) { - return ServiceManager.getService(project, QuarkusProjectService.class); - } + public static QuarkusProjectService getInstance(Project project) { + return ServiceManager.getService(project, QuarkusProjectService.class); + } - private final Project project; + private final MessageBusConnection connection; - private final MessageBusConnection connection; + public QuarkusProjectService(Project project) { + connection = project.getMessageBus().connect(); + connection.subscribe(ClasspathResourceChangedManager.TOPIC, this); + } - public QuarkusProjectService(Project project) { - this.project = project; - connection = project.getMessageBus().connect(); - connection.subscribe(ClasspathResourceChangedManager.TOPIC, this); - connection.subscribe(ProjectTopics.MODULES, this); - // Add the Quarkus deployment preprocessor - ClasspathResourceChangedManager.getInstance(project) - .addPreprocessor( - (progressIndicator) -> { - processModules(progressIndicator); - }); - } - @Override - public void moduleAdded(@NotNull Project project, @NotNull Module module) { - QuarkusModuleUtil.ensureQuarkusLibrary(module, new EmptyProgressIndicator()); - } - - public VirtualFile getSchema(Module module) { - var schemaEntry = schemas.get(module); - if (schemaEntry == null || !schemaEntry.getRight()) { - VirtualFile file = computeSchema(module, schemaEntry != null ? schemaEntry.getLeft() : null); - if (file != null) { - if (schemaEntry != null) { - schemaEntry.setRight(Boolean.TRUE); - } else { - schemaEntry = new MutablePair<>(file, Boolean.TRUE); - schemas.put(module, schemaEntry); - } - } - } - return schemaEntry != null ? schemaEntry.getLeft() : null; - } - - private static VirtualFile createJSONSchemaFile(String name) throws IOException { - return new LightVirtualFile(name + "-schema.json", JsonFileType.INSTANCE, ""); - } - - private VirtualFile computeSchema(Module module, VirtualFile schemaFile) { - try { - if (schemaFile == null) { - schemaFile = createJSONSchemaFile(module.getName()); - } - final VirtualFile schemaFile1 = schemaFile; - DumbService.getInstance(module.getProject()).runWhenSmart(() -> { - ApplicationManager.getApplication().runWriteAction(() -> { - try { - MicroProfileProjectInfo info = PropertiesManager.getInstance().getMicroProfileProjectInfo(module, - MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.TEST, PsiUtilsLSImpl.getInstance(module.getProject()), - DocumentFormat.Markdown, new EmptyProgressIndicator()); - String schema = JSONSchemaUtils.toJSONSchema(info, false); - VfsUtil.saveText(schemaFile1, schema); - } catch (IOException e) { - LOGGER.warn(e.getLocalizedMessage(), e); - } - }); - }); - return schemaFile; - } catch (IOException | ProcessCanceledException e) { - LOGGER.warn(e.getLocalizedMessage(), e); - } - return null; - } - - @Override - public void librariesChanged() { - // Update the JSON schema cache - schemas.forEach((module, pair) -> { - pair.setRight(Boolean.FALSE); - }); - } - - @Override - public void sourceFilesChanged(Set> sources) { - sources.forEach(pair -> schemas.computeIfPresent(pair.getSecond(), (m, p) -> { - p.setRight(Boolean.FALSE); - return p; - })); - } - - public void processModules(com.intellij.openapi.progress.ProgressIndicator progressIndicator) { - if (!project.isDisposed()) { - for (var module : ModuleManager.getInstance(project).getModules()) { - LOGGER.info("Calling ensure from processModules"); - QuarkusModuleUtil.ensureQuarkusLibrary(module, progressIndicator); + public VirtualFile getSchema(Module module) { + var schemaEntry = schemas.get(module); + if (schemaEntry == null || !schemaEntry.getRight()) { + VirtualFile file = computeSchema(module, schemaEntry != null ? schemaEntry.getLeft() : null); + if (file != null) { + if (schemaEntry != null) { + schemaEntry.setRight(Boolean.TRUE); + } else { + schemaEntry = new MutablePair<>(file, Boolean.TRUE); + schemas.put(module, schemaEntry); + } } } - } + return schemaEntry != null ? schemaEntry.getLeft() : null; + } + private static VirtualFile createJSONSchemaFile(String name) throws IOException { + return new LightVirtualFile(name + "-schema.json", JsonFileType.INSTANCE, ""); + } - @Override - public void dispose() { - connection.disconnect(); - } + private VirtualFile computeSchema(Module module, VirtualFile schemaFile) { + try { + if (schemaFile == null) { + schemaFile = createJSONSchemaFile(module.getName()); + } + final VirtualFile schemaFile1 = schemaFile; + DumbService.getInstance(module.getProject()).runWhenSmart(() -> ApplicationManager.getApplication().runWriteAction(() -> { + try { + MicroProfileProjectInfo info = PropertiesManager.getInstance().getMicroProfileProjectInfo(module, + MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.TEST, PsiUtilsLSImpl.getInstance(module.getProject()), + DocumentFormat.Markdown, new EmptyProgressIndicator()); + String schema = JSONSchemaUtils.toJSONSchema(info, false); + VfsUtil.saveText(schemaFile1, schema); + } catch (IOException e) { + LOGGER.warn(e.getLocalizedMessage(), e); + } + })); + return schemaFile; + } catch (IOException | ProcessCanceledException e) { + LOGGER.warn(e.getLocalizedMessage(), e); + } + return null; + } + + @Override + public void librariesChanged() { + // Update the JSON schema cache + schemas.forEach((module, pair) -> pair.setRight(Boolean.FALSE)); + } + + @Override + public void sourceFilesChanged(Set> sources) { + sources.forEach(pair -> schemas.computeIfPresent(pair.getSecond(), (m, p) -> { + p.setRight(Boolean.FALSE); + return p; + })); + } + + @Override + public void dispose() { + connection.disconnect(); + } } diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusLanguageClient.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusLanguageClient.java index 282cc2e35..4fd094b62 100644 --- a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusLanguageClient.java +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusLanguageClient.java @@ -33,6 +33,7 @@ import com.redhat.devtools.intellij.lsp4mp4ij.settings.MicroProfileInspectionsInfo; import com.redhat.devtools.intellij.lsp4mp4ij.settings.UserDefinedMicroProfileSettings; import com.redhat.devtools.intellij.quarkus.QuarkusModuleUtil; +import com.redhat.devtools.intellij.quarkus.QuarkusDeploymentSupport; import org.eclipse.lsp4j.*; import org.eclipse.lsp4mp.commons.*; import org.eclipse.lsp4mp.commons.codeaction.CodeActionResolveData; @@ -41,6 +42,7 @@ import org.eclipse.lsp4mp.ls.api.MicroProfileLanguageServerAPI; import org.jetbrains.annotations.NotNull; +import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -57,6 +59,9 @@ public class QuarkusLanguageClient extends IndexAwareLanguageClient implements M public QuarkusLanguageClient(Project project) { super(project); + // Call Quarkus deployment support here to react on library changed (to evict quarkus deploiement cache) before + // sending an LSP microprofile/propertiesChanged notifications + QuarkusDeploymentSupport.getInstance(project); connection = project.getMessageBus().connect(project); connection.subscribe(ClasspathResourceChangedManager.TOPIC, this); inspectionsInfo = MicroProfileInspectionsInfo.getMicroProfileInspectionInfo(project); @@ -144,11 +149,31 @@ private boolean isConfigSource(VirtualFile file) { @Override public CompletableFuture getProjectInfo(MicroProfileProjectInfoParams params) { + IPsiUtils utils = PsiUtilsLSImpl.getInstance(getProject()); + VirtualFile file = null; + try { + file = utils.findFile(params.getUri()); + } catch (IOException e) { + throw new RuntimeException(e); + } + Module module = utils.getModule(file); + if (module == null) { + throw new RuntimeException(); + } + CompletableFuture quarkusDeploymentSupport = QuarkusDeploymentSupport.getInstance(getProject()).updateClasspathWithQuarkusDeploymentAsync(module); + if (quarkusDeploymentSupport.isDone()) { + return internalGetProjectInfo(params); + } + return quarkusDeploymentSupport + .thenCompose(unused -> internalGetProjectInfo(params)); + } + + private CompletableFuture internalGetProjectInfo(MicroProfileProjectInfoParams params) { var coalesceBy = new CoalesceByKey("microprofile/projectInfo", params.getUri(), params.getScopes()); String filePath = getFilePath(params.getUri()); return runAsBackground("Computing MicroProfile properties for '" + filePath + "'.", monitor -> - PropertiesManager.getInstance().getMicroProfileProjectInfo(params, PsiUtilsLSImpl.getInstance(getProject()), monitor) - , coalesceBy); + PropertiesManager.getInstance().getMicroProfileProjectInfo(params, PsiUtilsLSImpl.getInstance(getProject()), monitor) + , coalesceBy); } @Override diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/maven/MavenToolDelegate.java b/src/main/java/com/redhat/devtools/intellij/quarkus/maven/MavenToolDelegate.java index d3b72a53e..9f6e75141 100644 --- a/src/main/java/com/redhat/devtools/intellij/quarkus/maven/MavenToolDelegate.java +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/maven/MavenToolDelegate.java @@ -31,7 +31,6 @@ import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.server.MavenEmbedderWrapper; -import org.jetbrains.idea.maven.server.MavenServerManager; import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; import org.jetbrains.idea.maven.utils.MavenUtil; import org.slf4j.Logger; @@ -39,12 +38,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; +import java.util.*; public class MavenToolDelegate implements ToolDelegate { private static final Logger LOGGER = LoggerFactory.getLogger(MavenToolDelegate.class); @@ -101,7 +95,7 @@ private void getDeploymentFiles(Module module, MavenProject mavenProject, List binaryDependencies = ensureDownloaded(module, mavenProject, toDownload, null); + progressIndicator.checkCanceled(); + progressIndicator.setText2("Collecting Quarkus deployment dependencies from the '" + toDownload.size() + "' binary dependencies"); + Set binaryDependencies = resolveDeploymentArtifacts(module, mavenProject, toDownload, null, progressIndicator); i = counter / binaryDependencies.size(); toDownload.clear(); for (MavenArtifact binaryDependency : binaryDependencies) { progressIndicator.checkCanceled(); - progressIndicator.setText2("Searching deployment descriptor in '" + binaryDependency.getArtifactId() + "'"); + progressIndicator.setText2("Searching deployment descriptor in '" + binaryDependency.getArtifactId() + "' binary"); if (!"test".equals(binaryDependency.getScope())) { if (processDependency(mavenProject, result, downloaded, binaryDependency, BINARY)) { toDownload.add(binaryDependency.getMavenId()); @@ -132,11 +128,13 @@ private void getDeploymentFiles(Module module, MavenProject mavenProject, List sourcesDependencies = ensureDownloaded(module, mavenProject, toDownload, "sources"); + progressIndicator.checkCanceled(); + progressIndicator.setText2("Collecting Quarkus deployment dependencies from the '" + toDownload.size() + "' source dependencies"); + Set sourcesDependencies = resolveDeploymentArtifacts(module, mavenProject, toDownload, "sources", progressIndicator); i = counter / sourcesDependencies.size(); for (MavenArtifact sourceDependency : sourcesDependencies) { progressIndicator.checkCanceled(); - progressIndicator.setText2("Searching deployment descriptor in '" + sourceDependency.getArtifactId() + "'"); + progressIndicator.setText2("Searching deployment descriptor in '" + sourceDependency.getArtifactId() + "' source"); processDependency(mavenProject, result, downloaded, sourceDependency, SOURCES); p+=i; progressIndicator.setFraction(p); @@ -145,7 +143,6 @@ private void getDeploymentFiles(Module module, MavenProject mavenProject, List[] result, Set downloaded, MavenArtifact dependency, int type) { boolean added = false; - if (mavenProject.findDependencies(dependency.getGroupId(), dependency.getArtifactId()).isEmpty() && !downloaded.contains(dependency)) { downloaded.add(dependency); VirtualFile jarRoot = getJarFile(dependency.getFile()); @@ -157,23 +154,46 @@ private boolean processDependency(MavenProject mavenProject, List[] return added; } - private List ensureDownloaded(Module module, MavenProject mavenProject, Set deploymentIds, String classifier) { - List result = new ArrayList<>(); - long start = System.currentTimeMillis(); + private Set resolveDeploymentArtifacts(Module module, MavenProject mavenProject, Set deploymentIds, String classifier, ProgressIndicator progressIndicator) { + Set deploymentArtifacts = new HashSet<>(); try { MavenEmbedderWrapper serverWrapper = createEmbedderWrapper(module.getProject(), mavenProject.getDirectory()); + if (serverWrapper == null) { + return Collections.emptySet(); + } if (classifier != null) { for(MavenId id : deploymentIds) { - result.add(serverWrapper.resolve(new MavenArtifactInfo(id, "jar", classifier), mavenProject.getRemoteRepositories())); + deploymentArtifacts.add(serverWrapper.resolve(new MavenArtifactInfo(id, "jar", classifier), mavenProject.getRemoteRepositories())); } } else { - List infos = deploymentIds.stream().map(id -> new MavenArtifactInfo(id, "jar", classifier)).collect(Collectors.toList()); - result = serverWrapper.resolveTransitively(infos, mavenProject.getRemoteRepositories()); + for (var deploymentId : deploymentIds) { + boolean shouldResolveArtifactTransitively = ToolDelegate.shouldResolveArtifactTransitively(deploymentId); + progressIndicator.checkCanceled(); + progressIndicator.setText2("Resolving " + (shouldResolveArtifactTransitively ? " (Transitevely) " : "") + "'" + deploymentId + "'"); + if (shouldResolveArtifactTransitively) { + // Resolving the deployment artifact and their dependencies + List infos = Arrays.asList( new MavenArtifactInfo(deploymentId, "jar", classifier)); + List resolvedArtifacts = serverWrapper.resolveArtifactTransitively(infos, mavenProject.getRemoteRepositories()).mavenResolvedArtifacts; + for (var resolvedArtifact: resolvedArtifacts) { + addDeploymentArtifact(resolvedArtifact, deploymentArtifacts); + } + } else { + // Resolving only the deployment artifact + MavenArtifact resolvedArtifact = serverWrapper.resolve(new MavenArtifactInfo(deploymentId, "jar", classifier), mavenProject.getRemoteRepositories()); //.mavenResolvedArtifacts; + addDeploymentArtifact(resolvedArtifact, deploymentArtifacts); + } + } } } catch (MavenProcessCanceledException | RuntimeException e) { LOGGER.warn(e.getLocalizedMessage(), e); } - return result; + return deploymentArtifacts; + } + + private static void addDeploymentArtifact(MavenArtifact resolvedArtifact, Set result) { + if (resolvedArtifact != null && !result.contains(resolvedArtifact)) { + result.add(resolvedArtifact); + } } /** diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/tool/ToolDelegate.java b/src/main/java/com/redhat/devtools/intellij/quarkus/tool/ToolDelegate.java index 06b9fbe68..5402c2d5c 100644 --- a/src/main/java/com/redhat/devtools/intellij/quarkus/tool/ToolDelegate.java +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/tool/ToolDelegate.java @@ -19,6 +19,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.redhat.devtools.intellij.quarkus.run.QuarkusRunConfiguration; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.maven.model.MavenId; import java.io.File; import java.io.FileReader; @@ -36,6 +37,22 @@ import static com.redhat.devtools.intellij.quarkus.QuarkusConstants.QUARKUS_EXTENSION_PROPERTIES; public interface ToolDelegate { + + static boolean shouldResolveArtifactTransitively(MavenId deploymentId) { + // The kubernetes support is only available if quarkus-kubernetes artifact is + // declared in the pom.xml + // When quarkus-kubernetes is declared, this JAR declares the deployment JAR + // quarkus-kubernetes-deployment + // This quarkus-kubernetes-deployment artifact has some dependencies to + // io.dekorate + + // In other words, to add + // io.dekorate.kubernetes.annotation.KubernetesApplication class in the search + // classpath, + // the dependencies of quarkus-kubernetes-deployment artifact must be downloaded + return "quarkus-kubernetes-deployment".equals(deploymentId.getArtifactId()) || "quarkus-openshift-deployment".equals(deploymentId.getArtifactId()); + } + static String getDeploymentJarId(File file) { String result = null; if (file.isDirectory()) { @@ -59,6 +76,10 @@ static String getDeploymentJarId(File file) { return result; } + static boolean hasExtensionProperties(File file) { + return getDeploymentJarId(file) != null; + } + static String getQuarkusExtension(Reader r) throws IOException { Properties p = new Properties(); p.load(r); diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index ea4f68ef0..c191398c0 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -332,6 +332,7 @@ + diff --git a/src/test/java/com/redhat/devtools/intellij/GradleTestCase.java b/src/test/java/com/redhat/devtools/intellij/GradleTestCase.java index cf9852f5e..77709fcb6 100644 --- a/src/test/java/com/redhat/devtools/intellij/GradleTestCase.java +++ b/src/test/java/com/redhat/devtools/intellij/GradleTestCase.java @@ -11,9 +11,6 @@ package com.redhat.devtools.intellij; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.progress.EmptyProgressIndicator; -import com.redhat.devtools.intellij.quarkus.QuarkusProjectService; import com.redhat.devtools.intellij.quarkus.gradle.AbstractGradleToolDelegate; import org.gradle.tooling.GradleConnector; import org.gradle.tooling.ProjectConnection; @@ -44,7 +41,7 @@ public static File getDependency(String path, String groupId, String artifactId, try (ProjectConnection connection = GradleConnector.newConnector().forProjectDirectory(new File(path)).connect()) { Optional dependency = (Optional) connection.getModel(IdeaProject.class).getModules().stream().flatMap(module -> module.getDependencies().stream()). filter(dep -> dep instanceof IdeaSingleEntryLibraryDependency). - map(dep -> (IdeaSingleEntryLibraryDependency)dep). + map(dep -> (IdeaSingleEntryLibraryDependency) dep). filter(library -> isCoordinateSame((IdeaSingleEntryLibraryDependency) library, groupId, artifactId, version)).findFirst(); if (dependency.isPresent()) { return dependency.get().getFile(); @@ -70,18 +67,9 @@ protected File getMavenRepository() { return new File(System.getProperty("user.home") + File.separatorChar + ".m2" + File.separator + "repository"); } - @Override - protected void importProject() { - super.importProject(); -// for(Module m : ModuleManager.getInstance(myProject).getModules()) { -// setupJdkForModule(m.getName()); -// } - QuarkusProjectService.getInstance(myProject).processModules(new EmptyProgressIndicator()); - } - @Parameterized.Parameters(name = "{index}: with Gradle-{0}") public static Collection data() { - return Arrays.asList(new Object[][] {{"6.0"}}); + return Arrays.asList(new Object[][]{{"6.0"}}); } } diff --git a/src/test/java/com/redhat/devtools/intellij/MavenModuleImportingTestCase.java b/src/test/java/com/redhat/devtools/intellij/MavenModuleImportingTestCase.java index 1b0cc4df0..a5f821c12 100644 --- a/src/test/java/com/redhat/devtools/intellij/MavenModuleImportingTestCase.java +++ b/src/test/java/com/redhat/devtools/intellij/MavenModuleImportingTestCase.java @@ -13,7 +13,6 @@ import com.intellij.maven.testFramework.MavenImportingTestCase; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.vfs.LocalFileSystem; @@ -24,7 +23,6 @@ import com.intellij.testFramework.fixtures.*; import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.utils.IPsiUtils; import com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.core.ls.PsiUtilsLSImpl; -import com.redhat.devtools.intellij.quarkus.QuarkusProjectService; import org.apache.commons.io.FileUtils; import java.io.File; @@ -78,7 +76,6 @@ protected List createMavenModules(List projectDirs) throws Excepti for(Module module : modules) { setupJdkForModule(module.getName()); } - QuarkusProjectService.getInstance(myTestFixture.getProject()).processModules(new EmptyProgressIndicator()); return Arrays.asList(modules).stream().skip(1).collect(Collectors.toList()); } protected Module createMavenModule(File projectDir) throws Exception { diff --git a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/GradlePropertiesManagerLocationConfigQuickstartTest.java b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/GradlePropertiesManagerLocationConfigQuickstartTest.java index 376e563a0..61258a2fd 100644 --- a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/GradlePropertiesManagerLocationConfigQuickstartTest.java +++ b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/GradlePropertiesManagerLocationConfigQuickstartTest.java @@ -12,6 +12,7 @@ import com.intellij.openapi.module.Module; import com.redhat.devtools.intellij.GradleTestCase; import com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.core.ls.PsiUtilsLSImpl; +import com.redhat.devtools.intellij.quarkus.QuarkusDeploymentSupport; import org.apache.commons.io.FileUtils; import org.eclipse.lsp4j.Location; import org.junit.Assert; @@ -36,8 +37,8 @@ public void setUp() throws Exception { @Test public void testConfigPropertiesMethodTest() throws Exception { - - Module javaProject = getModule("config-quickstart.main"); + Module javaProject = getModule("hibernate-orm-resteasy.main"); + QuarkusDeploymentSupport.getInstance(javaProject.getProject()).updateClasspathWithQuarkusDeploymentAsync(javaProject); // Test with method with parameters // greeting.constructor.message diff --git a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/GradlePropertiesManagerLocationUsingVertxTest.java b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/GradlePropertiesManagerLocationUsingVertxTest.java index 326cbcb9d..edd374ba3 100644 --- a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/GradlePropertiesManagerLocationUsingVertxTest.java +++ b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/GradlePropertiesManagerLocationUsingVertxTest.java @@ -12,6 +12,7 @@ import com.intellij.openapi.module.Module; import com.redhat.devtools.intellij.GradleTestCase; import com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.core.ls.PsiUtilsLSImpl; +import com.redhat.devtools.intellij.quarkus.QuarkusDeploymentSupport; import org.apache.commons.io.FileUtils; import org.eclipse.lsp4j.Location; import org.junit.Assert; @@ -36,8 +37,8 @@ public void setUp() throws Exception { @Test public void testUsingVertxTest() throws Exception { - Module javaProject = getModule("using-vertx.main"); + QuarkusDeploymentSupport.getInstance(javaProject.getProject()).updateClasspathWithQuarkusDeploymentAsync(javaProject); // Test with JAR // quarkus.datasource.url diff --git a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/LSP4MPMavenModuleImportingTestCase.java b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/LSP4MPMavenModuleImportingTestCase.java index fc99415bc..bd96c099c 100644 --- a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/LSP4MPMavenModuleImportingTestCase.java +++ b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/LSP4MPMavenModuleImportingTestCase.java @@ -13,7 +13,9 @@ import com.intellij.openapi.module.Module; +import com.intellij.openapi.progress.EmptyProgressIndicator; import com.redhat.devtools.intellij.MavenModuleImportingTestCase; +import com.redhat.devtools.intellij.quarkus.QuarkusDeploymentSupport; import java.io.File; @@ -23,7 +25,15 @@ public abstract class LSP4MPMavenModuleImportingTestCase extends MavenModuleImportingTestCase { protected Module loadMavenProject(String projectName) throws Exception { - return createMavenModule(new File("projects/lsp4mp/projects/maven/" + projectName)); + return loadMavenProject(projectName, false); + } + + protected Module loadMavenProject(String projectName, boolean collectAndAddQuarkusDeploymentDependencies) throws Exception { + Module module = createMavenModule(new File("projects/lsp4mp/projects/maven/" + projectName)); + if(collectAndAddQuarkusDeploymentDependencies) { + QuarkusDeploymentSupport.updateClasspathWithQuarkusDeployment(module, new EmptyProgressIndicator()); + } + return module; } } diff --git a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/MicroProfileMavenProjectName.java b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/MicroProfileMavenProjectName.java index 6050c1eff..1eb4e984e 100644 --- a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/MicroProfileMavenProjectName.java +++ b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/MicroProfileMavenProjectName.java @@ -35,5 +35,6 @@ public class MicroProfileMavenProjectName { public static final String microprofile_opentracing = "microprofile-opentracing"; public static final String microprofile_reactive_messaging = "microprofile-reactive-messaging"; public static final String rest_client_quickstart = "rest-client-quickstart"; + public static final String using_vertx= "using-vertx"; } diff --git a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/PropertiesManagerClassPathKindTest.java b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/PropertiesManagerClassPathKindTest.java index 0e74c80c6..57502989c 100644 --- a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/PropertiesManagerClassPathKindTest.java +++ b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/PropertiesManagerClassPathKindTest.java @@ -71,7 +71,7 @@ public void testconfigQuickstartTest() throws Exception { assertProperties(infoFromSrc, 3 /* properties from Java sources */ + // 7 /* static properties from microprofile-context-propagation-api */ + 1 /* static property from microprofile config_ordinal */ + - 187, + 180, // GreetingResource // @ConfigProperty(name = "greeting.message") diff --git a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/PropertiesManagerLocationTest.java b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/PropertiesManagerLocationTest.java index c5e3bf7f4..13aaebd39 100644 --- a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/PropertiesManagerLocationTest.java +++ b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/PropertiesManagerLocationTest.java @@ -24,12 +24,12 @@ * @author Angelo ZERR * @see https://github.com/redhat-developer/quarkus-ls/blob/master/microprofile.jdt/com.redhat.microprofile.jdt.test/src/main/java/com/redhat/microprofile/jdt/core/PropertiesManagerLocationTest.java */ -public class PropertiesManagerLocationTest extends MavenModuleImportingTestCase { +public class PropertiesManagerLocationTest extends LSP4MPMavenModuleImportingTestCase { @Test public void testUsingVertxTest() throws Exception { - Module javaProject = createMavenModule(new File("projects/lsp4mp/projects/maven/using-vertx")); + Module javaProject = loadMavenProject(MicroProfileMavenProjectName.using_vertx,true); // Test with JAR // quarkus.datasource.url Location location = PropertiesManager.getInstance().findPropertyLocation(javaProject, diff --git a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/ConfigItemIntBoolDefaultValueTest.java b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/ConfigItemIntBoolDefaultValueTest.java index 209ff20a5..5c6cd7e7f 100644 --- a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/ConfigItemIntBoolDefaultValueTest.java +++ b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/ConfigItemIntBoolDefaultValueTest.java @@ -39,7 +39,7 @@ public class ConfigItemIntBoolDefaultValueTest extends LSP4MPMavenModuleImportin @Test public void testConfigItemIntBoolDefaultValueTest() throws Exception { - Module javaProject = loadMavenProject(MicroProfileMavenProjectName.config_quickstart); + Module javaProject = loadMavenProject(MicroProfileMavenProjectName.config_quickstart, true); MicroProfileProjectInfo infoFromClasspath = PropertiesManager.getInstance().getMicroProfileProjectInfo(javaProject, MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.Markdown, new EmptyProgressIndicator()); diff --git a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/MicroProfileConfigPropertyTest.java b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/MicroProfileConfigPropertyTest.java index ebe1ca286..c252c743a 100644 --- a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/MicroProfileConfigPropertyTest.java +++ b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/MicroProfileConfigPropertyTest.java @@ -35,7 +35,7 @@ public class MicroProfileConfigPropertyTest extends LSP4MPMavenModuleImportingTestCase { public void testConfigQuickstartFromClasspath() throws Exception { - Module module = loadMavenProject(MicroProfileMavenProjectName.config_quickstart); + Module module = loadMavenProject(MicroProfileMavenProjectName.config_quickstart, true); MicroProfileProjectInfo infoFromClasspath = PropertiesManager.getInstance().getMicroProfileProjectInfo(module, MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.PlainText, new EmptyProgressIndicator()); File f = MavenArtifactUtil.getArtifactFile(myProjectsManager.findProject(module).getLocalRepository(), new MavenId("io.quarkus:quarkus-core-deployment:1.1.0.Final"), "jar").toFile(); @@ -116,7 +116,7 @@ public void testConfigQuickstartFromClasspath() throws Exception { } public void testConfigQuickstartFromJavaSources() throws Exception { - Module module = loadMavenProject(MicroProfileMavenProjectName.config_quickstart); + Module module = loadMavenProject(MicroProfileMavenProjectName.config_quickstart, true); MicroProfileProjectInfo infoFromJavaSources = PropertiesManager.getInstance().getMicroProfileProjectInfo(module, MicroProfilePropertiesScope.ONLY_SOURCES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.PlainText, new EmptyProgressIndicator()); assertProperties(infoFromJavaSources, 31 /* properties from Java sources with ConfigProperty */ + // diff --git a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/health/java/MicroProfileHealthJavaDiagnosticsTest.java b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/health/java/MicroProfileHealthJavaDiagnosticsTest.java index 81667c878..4239d4f6b 100644 --- a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/health/java/MicroProfileHealthJavaDiagnosticsTest.java +++ b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/health/java/MicroProfileHealthJavaDiagnosticsTest.java @@ -15,6 +15,8 @@ import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.redhat.devtools.intellij.MavenModuleImportingTestCase; +import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.LSP4MPMavenModuleImportingTestCase; +import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.MicroProfileMavenProjectName; import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.utils.IPsiUtils; import com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.core.ls.PsiUtilsLSImpl; import com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.health.MicroProfileHealthConstants; @@ -37,10 +39,10 @@ * @author Angelo ZERR * @see https://github.com/redhat-developer/quarkus-ls/blob/master/microprofile.jdt/com.redhat.microprofile.jdt.test/src/main/java/com/redhat/microprofile/jdt/core/health/JavaDiagnosticsMicroProfileHealthTest.java */ -public class MicroProfileHealthJavaDiagnosticsTest extends MavenModuleImportingTestCase { +public class MicroProfileHealthJavaDiagnosticsTest extends LSP4MPMavenModuleImportingTestCase { @Test public void testImplementHealthCheck() throws Exception { - Module module = createMavenModule(new File("projects/lsp4mp/projects/maven/microprofile-health-quickstart")); + Module module = loadMavenProject(MicroProfileMavenProjectName.microprofile_health_quickstart); IPsiUtils utils = PsiUtilsLSImpl.getInstance(myProject); MicroProfileJavaDiagnosticsParams diagnosticsParams = new MicroProfileJavaDiagnosticsParams(); @@ -68,7 +70,7 @@ public void testImplementHealthCheck() throws Exception { @Test public void testHealthAnnotationMissing() throws Exception { - Module module = createMavenModule(new File("projects/lsp4mp/projects/maven/microprofile-health-quickstart")); + Module module = loadMavenProject(MicroProfileMavenProjectName.microprofile_health_quickstart); IPsiUtils utils = PsiUtilsLSImpl.getInstance(myProject); MicroProfileJavaDiagnosticsParams diagnosticsParams = new MicroProfileJavaDiagnosticsParams(); diff --git a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/restclient/properties/MicroProfileRegisterRestClientTest.java b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/restclient/properties/MicroProfileRegisterRestClientTest.java index 68f32057d..ba484eeb8 100644 --- a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/restclient/properties/MicroProfileRegisterRestClientTest.java +++ b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/restclient/properties/MicroProfileRegisterRestClientTest.java @@ -33,7 +33,7 @@ public class MicroProfileRegisterRestClientTest extends LSP4MPMavenModuleImporti @Test public void testRestClientQuickstart() throws Exception { - Module module = loadMavenProject(MicroProfileMavenProjectName.rest_client_quickstart); + Module module = loadMavenProject(MicroProfileMavenProjectName.rest_client_quickstart, true); MicroProfileProjectInfo infoFromClasspath = PropertiesManager.getInstance().getMicroProfileProjectInfo(module, MicroProfilePropertiesScope.ONLY_SOURCES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.PlainText, new EmptyProgressIndicator()); // mp-rest Properties diff --git a/src/test/java/com/redhat/devtools/intellij/quarkus/completion/GradleQuarkusLibraryTest.java b/src/test/java/com/redhat/devtools/intellij/quarkus/completion/GradleQuarkusLibraryTest.java index d42ea6e75..13a945027 100644 --- a/src/test/java/com/redhat/devtools/intellij/quarkus/completion/GradleQuarkusLibraryTest.java +++ b/src/test/java/com/redhat/devtools/intellij/quarkus/completion/GradleQuarkusLibraryTest.java @@ -15,6 +15,7 @@ import com.intellij.openapi.roots.OrderRootType; import com.redhat.devtools.intellij.GradleTestCase; import com.redhat.devtools.intellij.quarkus.QuarkusConstants; +import com.redhat.devtools.intellij.quarkus.QuarkusDeploymentSupport; import org.apache.commons.io.FileUtils; import org.junit.Test; @@ -37,6 +38,8 @@ public void setUp() throws Exception { @Test public void testQuarkusLibraryDoesNotReplicateExistingDependencies() throws Exception { Module module = getModule("config-quickstart.native-test"); + QuarkusDeploymentSupport.getInstance(module.getProject()).updateClasspathWithQuarkusDeploymentAsync(module); + Optional library = Stream.of(ModuleRootManager.getInstance(module).getOrderEntries()).filter(entry -> entry instanceof LibraryOrderEntry). map(entry -> LibraryOrderEntry.class.cast(entry)).filter(entry -> entry.getLibraryName().equals(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME)).findFirst(); assertTrue(library.isPresent()); diff --git a/src/test/java/com/redhat/devtools/intellij/quarkus/completion/MavenApplicationPropertiesCompletionTest.java b/src/test/java/com/redhat/devtools/intellij/quarkus/completion/MavenApplicationPropertiesCompletionTest.java index 1845fa673..24f26082f 100644 --- a/src/test/java/com/redhat/devtools/intellij/quarkus/completion/MavenApplicationPropertiesCompletionTest.java +++ b/src/test/java/com/redhat/devtools/intellij/quarkus/completion/MavenApplicationPropertiesCompletionTest.java @@ -14,10 +14,13 @@ import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.redhat.devtools.intellij.MavenEditorTest; import com.redhat.devtools.intellij.lsp4ij.ConnectDocumentToLanguageServerSetupParticipant; +import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.MicroProfileMavenProjectName; +import com.redhat.devtools.intellij.quarkus.QuarkusDeploymentSupport; import org.junit.Test; import java.io.File; @@ -31,8 +34,7 @@ public class MavenApplicationPropertiesCompletionTest extends MavenEditorTest { @Test public void testBooleanCompletion() throws Exception { - - Module module = createMavenModule(new File("projects/quarkus/projects/maven/config-quickstart")); + Module module = loadMavenProject(MicroProfileMavenProjectName.config_quickstart, true); VirtualFile propertiesFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(ModuleUtilCore.getModuleDirPath(module) + "/src/main/resources/application.properties"); codeInsightTestFixture.configureFromExistingVirtualFile(propertiesFile); codeInsightTestFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_LINE_END); @@ -49,4 +51,16 @@ private void insertLine(String s) throws InterruptedException { } Thread.sleep(1000); } + + protected Module loadMavenProject(String projectName) throws Exception { + return loadMavenProject(projectName, false); + } + + protected Module loadMavenProject(String projectName, boolean collectAndAddQuarkusDeploymentDependencies) throws Exception { + Module module = createMavenModule(new File("projects/quarkus/projects/maven/" + projectName)); + if(collectAndAddQuarkusDeploymentDependencies) { + QuarkusDeploymentSupport.updateClasspathWithQuarkusDeployment(module, new EmptyProgressIndicator()); + } + return module; + } } diff --git a/src/test/java/com/redhat/devtools/intellij/quarkus/completion/MavenQuarkusLibraryTest.java b/src/test/java/com/redhat/devtools/intellij/quarkus/completion/MavenQuarkusLibraryTest.java index 9c1233529..b03de5deb 100644 --- a/src/test/java/com/redhat/devtools/intellij/quarkus/completion/MavenQuarkusLibraryTest.java +++ b/src/test/java/com/redhat/devtools/intellij/quarkus/completion/MavenQuarkusLibraryTest.java @@ -17,6 +17,8 @@ import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.redhat.devtools.intellij.MavenModuleImportingTestCase; +import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.LSP4MPMavenModuleImportingTestCase; +import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.MicroProfileMavenProjectName; import com.redhat.devtools.intellij.quarkus.QuarkusConstants; import org.junit.Test; @@ -26,11 +28,11 @@ /** * Quarkus library test */ -public class MavenQuarkusLibraryTest extends MavenModuleImportingTestCase { +public class MavenQuarkusLibraryTest extends LSP4MPMavenModuleImportingTestCase { @Test public void testQuarkusLibraryDoesNotReplicateExistingDependencies() throws Exception { - Module module = createMavenModule(new File("projects/maven/config-quickstart")); + Module module = loadMavenProject(MicroProfileMavenProjectName.config_quickstart, true); ModifiableRootModel model = ReadAction.compute(() -> ModuleRootManager.getInstance(module).getModifiableModel()); LibraryTable table = model.getModuleLibraryTable(); Library library = table.getLibraryByName(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME); diff --git a/src/test/java/com/redhat/microprofile/psi/quarkus/GradleQuarkusConfigRootAllQuarkusExtensionsTest.java b/src/test/java/com/redhat/microprofile/psi/quarkus/GradleQuarkusConfigRootAllQuarkusExtensionsTest.java index 27f9fa28a..13d6fcf4a 100644 --- a/src/test/java/com/redhat/microprofile/psi/quarkus/GradleQuarkusConfigRootAllQuarkusExtensionsTest.java +++ b/src/test/java/com/redhat/microprofile/psi/quarkus/GradleQuarkusConfigRootAllQuarkusExtensionsTest.java @@ -11,10 +11,12 @@ package com.redhat.microprofile.psi.quarkus; import com.intellij.openapi.application.ReadAction; +import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.EmptyProgressIndicator; import com.redhat.devtools.intellij.GradleTestCase; import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.PropertiesManager; import com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.core.ls.PsiUtilsLSImpl; +import com.redhat.devtools.intellij.quarkus.QuarkusDeploymentSupport; import org.apache.commons.io.FileUtils; import org.eclipse.lsp4mp.commons.ClasspathKind; import org.eclipse.lsp4mp.commons.DocumentFormat; @@ -39,7 +41,10 @@ public void setUp() throws Exception { @Test public void testAllExtensions() throws Exception { - MicroProfileProjectInfo info = ReadAction.compute(() ->PropertiesManager.getInstance().getMicroProfileProjectInfo(getModule("all-quarkus-extensions.main"), MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.PlainText, new EmptyProgressIndicator())); + Module module = getModule("all-quarkus-extensions.main"); + QuarkusDeploymentSupport.getInstance(module.getProject()).updateClasspathWithQuarkusDeploymentAsync(module); + + MicroProfileProjectInfo info = ReadAction.compute(() ->PropertiesManager.getInstance().getMicroProfileProjectInfo(module, MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.PlainText, new EmptyProgressIndicator())); File keycloakJARFile = getDependency(getProjectPath(), "io.quarkus", "quarkus-keycloak-authorization", "1.0.1.Final"); assertNotNull("Test existing of quarkus-keycloak-deployment*.jar", keycloakJARFile); File hibernateJARFile = getDependency(getProjectPath(), "io.quarkus", "quarkus-hibernate-orm-deployment", "1.0.1.Final"); diff --git a/src/test/java/com/redhat/microprofile/psi/quarkus/GradleQuarkusConfigRootHibernateRestEasyTest.java b/src/test/java/com/redhat/microprofile/psi/quarkus/GradleQuarkusConfigRootHibernateRestEasyTest.java index cd703adb1..f390c4a31 100644 --- a/src/test/java/com/redhat/microprofile/psi/quarkus/GradleQuarkusConfigRootHibernateRestEasyTest.java +++ b/src/test/java/com/redhat/microprofile/psi/quarkus/GradleQuarkusConfigRootHibernateRestEasyTest.java @@ -11,10 +11,12 @@ package com.redhat.microprofile.psi.quarkus; import com.intellij.openapi.application.ReadAction; +import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.EmptyProgressIndicator; import com.redhat.devtools.intellij.GradleTestCase; import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.PropertiesManager; import com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.core.ls.PsiUtilsLSImpl; +import com.redhat.devtools.intellij.quarkus.QuarkusDeploymentSupport; import org.apache.commons.io.FileUtils; import org.eclipse.lsp4mp.commons.ClasspathKind; import org.eclipse.lsp4mp.commons.DocumentFormat; @@ -42,7 +44,9 @@ public void setUp() throws Exception { @Test public void testHibernateOrmResteasy() throws Exception { - MicroProfileProjectInfo info = ReadAction.compute(() -> PropertiesManager.getInstance().getMicroProfileProjectInfo(getModule("hibernate-orm-resteasy.main"), MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.PlainText, new EmptyProgressIndicator())); + Module module = getModule("hibernate-orm-resteasy.main"); + QuarkusDeploymentSupport.getInstance(module.getProject()).updateClasspathWithQuarkusDeploymentAsync(module); + MicroProfileProjectInfo info = ReadAction.compute(() -> PropertiesManager.getInstance().getMicroProfileProjectInfo(module, MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.PlainText, new EmptyProgressIndicator())); File f = getDependency(getProjectPath(), "io.quarkus", "quarkus-hibernate-orm-deployment", "1.0.1.Final"); assertNotNull("Test existing of quarkus-hibernate-orm-deployment*.jar", f); diff --git a/src/test/java/com/redhat/microprofile/psi/quarkus/MavenQuarkusConfigRootTest.java b/src/test/java/com/redhat/microprofile/psi/quarkus/MavenQuarkusConfigRootTest.java index ba1be0cbf..73911c736 100644 --- a/src/test/java/com/redhat/microprofile/psi/quarkus/MavenQuarkusConfigRootTest.java +++ b/src/test/java/com/redhat/microprofile/psi/quarkus/MavenQuarkusConfigRootTest.java @@ -42,7 +42,7 @@ public class MavenQuarkusConfigRootTest extends QuarkusMavenModuleImportingTestCase { public void testHibernateOrmResteasy() throws Exception { - Module module = loadMavenProject(QuarkusMavenProjectName.hibernate_orm_resteasy); + Module module = loadMavenProject(QuarkusMavenProjectName.hibernate_orm_resteasy, true); MicroProfileProjectInfo info = PropertiesManager.getInstance().getMicroProfileProjectInfo(module, MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.PlainText, new EmptyProgressIndicator()); assertProperties(info, @@ -63,7 +63,7 @@ public void testHibernateOrmResteasy() throws Exception { } public void testAllQuarkusExtensions() throws Exception { - Module module = loadMavenProject(QuarkusMavenProjectName.all_quarkus_extensions); + Module module = loadMavenProject(QuarkusMavenProjectName.all_quarkus_extensions, true); MicroProfileProjectInfo info = PropertiesManager.getInstance().getMicroProfileProjectInfo(module, MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.PlainText, new EmptyProgressIndicator()); assertProperties(info, diff --git a/src/test/java/com/redhat/microprofile/psi/quarkus/MavenQuarkusHibernateORMPropertyTest.java b/src/test/java/com/redhat/microprofile/psi/quarkus/MavenQuarkusHibernateORMPropertyTest.java index 97aa29577..aef548828 100644 --- a/src/test/java/com/redhat/microprofile/psi/quarkus/MavenQuarkusHibernateORMPropertyTest.java +++ b/src/test/java/com/redhat/microprofile/psi/quarkus/MavenQuarkusHibernateORMPropertyTest.java @@ -32,7 +32,7 @@ public class MavenQuarkusHibernateORMPropertyTest extends QuarkusMavenModuleImpo @Test public void testQuarkusContainerImages() throws Exception { - Module module = loadMavenProject(QuarkusMavenProjectName.hibernate_orm_resteasy); + Module module = loadMavenProject(QuarkusMavenProjectName.hibernate_orm_resteasy, true); MicroProfileProjectInfo infoFromClasspath = PropertiesManager.getInstance().getMicroProfileProjectInfo(module, MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.PlainText, new EmptyProgressIndicator()); assertProperties(infoFromClasspath, diff --git a/src/test/java/com/redhat/microprofile/psi/quarkus/QuarkusKubernetesTest.java b/src/test/java/com/redhat/microprofile/psi/quarkus/QuarkusKubernetesTest.java index c9d16fce5..54334c4e6 100644 --- a/src/test/java/com/redhat/microprofile/psi/quarkus/QuarkusKubernetesTest.java +++ b/src/test/java/com/redhat/microprofile/psi/quarkus/QuarkusKubernetesTest.java @@ -30,7 +30,7 @@ public class QuarkusKubernetesTest extends QuarkusMavenModuleImportingTestCase { @Test public void testKubernetes() throws Exception { - Module module = loadMavenProject(QuarkusMavenProjectName.kubernetes); + Module module = loadMavenProject(QuarkusMavenProjectName.kubernetes, true); MicroProfileProjectInfo info = PropertiesManager.getInstance().getMicroProfileProjectInfo(module, MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.Markdown, new EmptyProgressIndicator()); assertProperties(info, @@ -78,7 +78,7 @@ public void testKubernetes() throws Exception { @Test public void testOpenshift() throws Exception { - Module module = loadMavenProject(QuarkusMavenProjectName.kubernetes); + Module module = loadMavenProject(QuarkusMavenProjectName.kubernetes, true); MicroProfileProjectInfo info = PropertiesManager.getInstance().getMicroProfileProjectInfo(module, MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.Markdown, new EmptyProgressIndicator()); assertProperties(info, @@ -120,7 +120,7 @@ public void testOpenshift() throws Exception { @Test public void testS2i() throws Exception { - Module module = loadMavenProject(QuarkusMavenProjectName.kubernetes); + Module module = loadMavenProject(QuarkusMavenProjectName.kubernetes, true); MicroProfileProjectInfo info = PropertiesManager.getInstance().getMicroProfileProjectInfo(module, MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.Markdown, new EmptyProgressIndicator()); assertProperties(info, @@ -157,7 +157,7 @@ public void testS2i() throws Exception { @Test public void testDocker() throws Exception { - Module module = loadMavenProject(QuarkusMavenProjectName.kubernetes); + Module module = loadMavenProject(QuarkusMavenProjectName.kubernetes, true); MicroProfileProjectInfo info = PropertiesManager.getInstance().getMicroProfileProjectInfo(module, MicroProfilePropertiesScope.SOURCES_AND_DEPENDENCIES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.Markdown, new EmptyProgressIndicator()); assertProperties(info, diff --git a/src/test/java/com/redhat/microprofile/psi/quarkus/QuarkusMavenModuleImportingTestCase.java b/src/test/java/com/redhat/microprofile/psi/quarkus/QuarkusMavenModuleImportingTestCase.java index 2d4e4b03a..a48d9b41a 100644 --- a/src/test/java/com/redhat/microprofile/psi/quarkus/QuarkusMavenModuleImportingTestCase.java +++ b/src/test/java/com/redhat/microprofile/psi/quarkus/QuarkusMavenModuleImportingTestCase.java @@ -12,7 +12,9 @@ package com.redhat.microprofile.psi.quarkus; import com.intellij.openapi.module.Module; +import com.intellij.openapi.progress.EmptyProgressIndicator; import com.redhat.devtools.intellij.MavenModuleImportingTestCase; +import com.redhat.devtools.intellij.quarkus.QuarkusDeploymentSupport; import java.io.File; @@ -23,6 +25,14 @@ public abstract class QuarkusMavenModuleImportingTestCase extends MavenModuleImportingTestCase { protected Module loadMavenProject(String projectName) throws Exception { - return createMavenModule(new File("projects/quarkus/projects/maven/" + projectName)); + return loadMavenProject(projectName, false); + } + + protected Module loadMavenProject(String projectName, boolean collectAndAddQuarkusDeploymentDependencies) throws Exception { + Module module = createMavenModule(new File("projects/quarkus/projects/maven/" + projectName)); + if(collectAndAddQuarkusDeploymentDependencies) { + QuarkusDeploymentSupport.updateClasspathWithQuarkusDeployment(module, new EmptyProgressIndicator()); + } + return module; } }