diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 191505dba..af72c2212 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -4,7 +4,7 @@ on: push: branches: '**' pull_request: - branches: [ main ] + branches: [ main, code-action-unification ] jobs: build: @@ -62,4 +62,4 @@ jobs: ./**/*liberty-tools-intellij*.zip ./**/libs/*liberty-tools-intellij*.jar if-no-files-found: warn - retention-days: 7 \ No newline at end of file + retention-days: 7 diff --git a/build.gradle b/build.gradle index 614490ed3..583952598 100644 --- a/build.gradle +++ b/build.gradle @@ -63,17 +63,16 @@ configurations { } dependencies { - // LSP4IJ dependencies - implementation 'org.microshed:lsp4ij:0.0.5' + implementation 'org.eclipse.lsp4j:org.eclipse.lsp4j:0.15.0' + implementation 'org.microshed:lsp4ij:0.0.5' // includes org.eclipse.lsp4j implementation ('org.eclipse.lsp4mp:org.eclipse.lsp4mp.ls:0.6.0') { exclude group: 'org.eclipse.lsp4j' } -// implementation 'org.eclipse.lsp4j:org.eclipse.lsp4j:0.15.0' implementation ('org.eclipse.lemminx:org.eclipse.lemminx:0.25.0') { exclude group: 'org.eclipse.lsp4j' } - implementation 'io.openliberty.tools:liberty-langserver-lemminx:2.0' - implementation ('io.openliberty.tools:liberty-langserver:2.0') { + implementation 'io.openliberty.tools:liberty-langserver-lemminx:2.1-SNAPSHOT' + implementation ('io.openliberty.tools:liberty-langserver:2.1-SNAPSHOT') { exclude group: 'org.eclipse.lsp4j' } implementation ('org.eclipse.lsp4jakarta:org.eclipse.lsp4jakarta.ls:0.1.1') { @@ -92,7 +91,7 @@ dependencies { testImplementation 'com.intellij.remoterobot:remote-robot:' + remoteRobotVersion testImplementation 'com.intellij.remoterobot:remote-fixtures:' + remoteRobotVersion testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' - testImplementation('com.jetbrains.intellij.maven:maven-test-framework:231.9011.34') { + testImplementation('com.jetbrains.intellij.maven:maven-test-framework:232.10072.27') { transitive = false } testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.2' @@ -105,16 +104,17 @@ dependencies { // Test: Video Recording. testImplementation 'com.automation-remarks:video-recorder-junit5:2.0' + // define jars to grab locally (if falling back to mavenLocal() repo) lsp('org.eclipse.lsp4mp:org.eclipse.lsp4mp.ls:0.6.0:uber') { transitive = false } lsp('org.eclipse.lemminx:org.eclipse.lemminx:0.25.0:uber') { transitive = false } - lsp('io.openliberty.tools:liberty-langserver-lemminx:2.0:jar-with-dependencies') { + lsp('io.openliberty.tools:liberty-langserver-lemminx:2.1-SNAPSHOT:jar-with-dependencies') { transitive = false } - lsp('io.openliberty.tools:liberty-langserver:2.0:jar-with-dependencies') { + lsp('io.openliberty.tools:liberty-langserver:2.1-SNAPSHOT:jar-with-dependencies') { transitive = false } lsp('org.eclipse.lsp4jakarta:org.eclipse.lsp4jakarta.ls:0.1.1:jar-with-dependencies') { @@ -137,7 +137,7 @@ runIde { intellij { // For a full list of IntelliJ IDEA releases please see https://www.jetbrains.com/intellij-repository/releases - version = '2023.1.2' + version = '2023.2.3' plugins = ['java', 'maven', 'gradle-java', 'properties', 'terminal', 'org.jetbrains.idea.maven', 'com.intellij.gradle'] updateSinceUntilBuild = false @@ -166,6 +166,11 @@ test { showStandardStreams = true exceptionFormat = 'full' } + + filter { + // disable lsp4jakarta integration tests until listener leak issue is resolved: https://github.com/OpenLiberty/liberty-tools-intellij/issues/541 + excludeTestsMatching "io.openliberty.tools.intellij.lsp4jakarta.it.*" + } } tasks { diff --git a/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyConfigLanguageClient.java b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyConfigLanguageClient.java index 269fbaec4..6737a7906 100644 --- a/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyConfigLanguageClient.java +++ b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyConfigLanguageClient.java @@ -10,37 +10,43 @@ ******************************************************************************/ package io.openliberty.tools.intellij.liberty.lsp; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.libraries.Library; -import com.intellij.openapi.vfs.VirtualFile; -import io.openliberty.tools.intellij.lsp4mp.MicroProfileProjectService; -import org.microshed.lsp4ij.LanguageClientImpl; -import org.apache.commons.lang3.tuple.Pair; +import java.util.List; +import org.eclipse.lsp4j.DidChangeWatchedFilesParams; +import org.eclipse.lsp4j.FileChangeType; +import org.eclipse.lsp4j.FileEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import java.util.List; +import com.intellij.openapi.project.Project; +import com.intellij.util.messages.MessageBusConnection; +import org.microshed.lsp4ij.LanguageClientImpl; +import org.microshed.lsp4ij.LanguageServerWrapper; /** * Client for Liberty language server * Adapted from https://github.com/redhat-developer/intellij-quarkus/blob/2585eb422beeb69631076d2c39196d6eca2f5f2e/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusLanguageClient.java */ -public class LibertyConfigLanguageClient extends LanguageClientImpl implements MicroProfileProjectService.Listener { +public class LibertyConfigLanguageClient extends LanguageClientImpl implements LibertyCustomConfigManager.Listener { private static final Logger LOGGER = LoggerFactory.getLogger(LibertyConfigLanguageClient.class); + private final MessageBusConnection connection; + public LibertyConfigLanguageClient(Project project) { super(project); + connection = project.getMessageBus().connect(project); + connection.subscribe(LibertyCustomConfigManager.TOPIC, this); + LibertyCustomConfigManager.getInstance(project); } @Override - public void libraryUpdated(Library library) { - // not needed for Liberty LS - } - - @Override - public void sourceUpdated(List> sources) { - // not needed for Liberty LS + public void processConfigXml(List uris) { + LanguageServerWrapper wrapper = getLanguageServerWrapper(); + if (wrapper != null) { + List fileEvents = uris.stream() + .map(uri -> new FileEvent(uri, FileChangeType.Changed)).toList(); + DidChangeWatchedFilesParams params = new DidChangeWatchedFilesParams(); + params.setChanges(fileEvents); + wrapper.getInitializedServer().thenAccept(ls -> ls.getWorkspaceService().didChangeWatchedFiles(params)); + } } } diff --git a/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyConfigLanguageServer.java b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyConfigLanguageServer.java index 371d0bc3e..34d0cc885 100644 --- a/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyConfigLanguageServer.java +++ b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyConfigLanguageServer.java @@ -13,11 +13,11 @@ import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.openapi.extensions.PluginId; -import org.microshed.lsp4ij.server.ProcessStreamConnectionProvider; +import io.openliberty.tools.intellij.util.JavaVersionUtil; import io.openliberty.tools.intellij.util.Constants; +import org.microshed.lsp4ij.server.ProcessStreamConnectionProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.File; import java.net.URI; import java.util.ArrayList; @@ -32,18 +32,10 @@ public class LibertyConfigLanguageServer extends ProcessStreamConnectionProvider private static final Logger LOGGER = LoggerFactory.getLogger(LibertyConfigLanguageServer.class); public LibertyConfigLanguageServer() { + String javaHome = System.getProperty("java.home"); IdeaPluginDescriptor descriptor = PluginManagerCore.getPlugin(PluginId.getId("open-liberty.intellij")); File libertyServerPath = new File(descriptor.getPluginPath().toFile(), "lib/server/liberty-langserver-jar-with-dependencies.jar"); - String javaHome = System.getProperty("java.home"); - if (javaHome == null) { - LOGGER.error("Unable to launch the Liberty language server. Could not resolve the java home system property"); - return; - } - if (!checkJavaVersion(javaHome, Constants.REQUIRED_JAVA_VERSION)) { - LOGGER.error("Unable to launch the Liberty language server." + - " Java " + Constants.REQUIRED_JAVA_VERSION + " or more recent is required to run 'Liberty Tools for IntelliJ'." + - " Change the boot Java runtime of the IDE as documented here:" + - " https://www.jetbrains.com/help/idea/switching-boot-jdk.html"); + if(!JavaVersionUtil.isJavaHomeValid(javaHome, Constants.LIBERTY_CONFIG_SERVER)){ return; } if (libertyServerPath.exists()) { diff --git a/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyCustomConfigListener.java b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyCustomConfigListener.java new file mode 100644 index 000000000..794f15f85 --- /dev/null +++ b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyCustomConfigListener.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2023 IBM Corporation. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ +package io.openliberty.tools.intellij.liberty.lsp; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.vfs.newvfs.BulkFileListener; +import com.intellij.openapi.vfs.newvfs.events.VFileEvent; +import io.openliberty.tools.intellij.lsp4mp.lsp4ij.LSPIJUtils; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class LibertyCustomConfigListener implements BulkFileListener { + private final static Logger LOGGER = Logger.getInstance(LibertyCustomConfigListener.class); + + private final LibertyCustomConfigManager manager; + public static final String LIBERTY_PLUGIN_CONFIG_XML = "liberty-plugin-config.xml"; + + public LibertyCustomConfigListener(LibertyCustomConfigManager manager) { + this.manager = manager; + } + + @Override + public void after(@NotNull List events) { + // filter file events to only liberty-plugin-config.xml + List pluginConfigList = events.stream() + .map(event -> LSPIJUtils.toUri(event.getFile()).toString()) + .filter(this::isPluginConfigXml) + .toList(); + manager.handleProcessConfigXml(pluginConfigList); + } + + private boolean isPluginConfigXml(String uri) { + return uri.endsWith(LIBERTY_PLUGIN_CONFIG_XML); + } +} diff --git a/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyCustomConfigManager.java b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyCustomConfigManager.java new file mode 100644 index 000000000..a9de78809 --- /dev/null +++ b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyCustomConfigManager.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2023 IBM Corporation. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ +package io.openliberty.tools.intellij.liberty.lsp; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.libraries.LibraryTable; +import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.util.messages.MessageBusConnection; +import com.intellij.util.messages.Topic; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class LibertyCustomConfigManager implements LibraryTable.Listener, Disposable { + + private final static Logger LOGGER = Logger.getInstance(LibertyCustomConfigManager.class); + + private final Project project; + private final MessageBusConnection appConnection; + private final LibertyCustomConfigListener listener; + + @Override + public void dispose() { + this.appConnection.disconnect(); + } + + public interface Listener { + void processConfigXml(List uris); + } + + public static LibertyCustomConfigManager getInstance(@NotNull Project project) { + return project.getService(LibertyCustomConfigManager.class); + } + + public static final Topic TOPIC = Topic.create(LibertyCustomConfigManager.class.getName(), Listener.class); + + + public LibertyCustomConfigManager(Project project) { + this.project = project; + listener = new LibertyCustomConfigListener(this); + appConnection = ApplicationManager.getApplication().getMessageBus().connect(project); + appConnection.subscribe(VirtualFileManager.VFS_CHANGES, listener); + } + + protected void handleProcessConfigXml(List uris) { + project.getMessageBus().syncPublisher(TOPIC).processConfigXml(uris); + } +} diff --git a/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyXmlServer.java b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyXmlServer.java index 309bb0c2b..9d33f244d 100644 --- a/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyXmlServer.java +++ b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/LibertyXmlServer.java @@ -13,8 +13,9 @@ import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.openapi.extensions.PluginId; -import org.microshed.lsp4ij.server.ProcessStreamConnectionProvider; +import io.openliberty.tools.intellij.util.JavaVersionUtil; import io.openliberty.tools.intellij.util.Constants; +import org.microshed.lsp4ij.server.ProcessStreamConnectionProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,19 +33,11 @@ public class LibertyXmlServer extends ProcessStreamConnectionProvider { private static final Logger LOGGER = LoggerFactory.getLogger(LibertyXmlServer.class); public LibertyXmlServer() { + String javaHome = System.getProperty("java.home"); IdeaPluginDescriptor descriptor = PluginManagerCore.getPlugin(PluginId.getId("open-liberty.intellij")); File lemminxServerPath = new File(descriptor.getPluginPath().toFile(), "lib/server/org.eclipse.lemminx-uber.jar"); File libertyServerPath = new File(descriptor.getPluginPath().toFile(), "lib/server/liberty-langserver-lemminx-jar-with-dependencies.jar"); - String javaHome = System.getProperty("java.home"); - if (javaHome == null) { - LOGGER.error("Unable to launch the LemMinX language server. Could not resolve the java home system property"); - return; - } - if (!checkJavaVersion(javaHome, Constants.REQUIRED_JAVA_VERSION)) { - LOGGER.error("Unable to launch the LemMinX language server." + - " Java " + Constants.REQUIRED_JAVA_VERSION + " or more recent is required to run 'Liberty Tools for IntelliJ'." + - " Change the boot Java runtime of the IDE as documented here:" + - " https://www.jetbrains.com/help/idea/switching-boot-jdk.html"); + if(!JavaVersionUtil.isJavaHomeValid(javaHome, Constants.LIBERTY_XML_SERVER)){ return; } if (lemminxServerPath.exists() && libertyServerPath.exists()) { diff --git a/src/main/java/io/openliberty/tools/intellij/liberty/lsp/ServerEnvFileType.java b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/ServerEnvFileType.java index d4cbdffdc..385e29d43 100644 --- a/src/main/java/io/openliberty/tools/intellij/liberty/lsp/ServerEnvFileType.java +++ b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/ServerEnvFileType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2022 IBM Corporation. + * Copyright (c) 2022, 2023 IBM Corporation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -9,11 +9,6 @@ *******************************************************************************/ package io.openliberty.tools.intellij.liberty.lsp; -import java.nio.file.FileSystems; -import java.nio.file.Path; -import java.nio.file.PathMatcher; -import java.nio.file.Paths; - import javax.swing.Icon; import com.intellij.openapi.fileTypes.PlainTextLanguage; @@ -27,8 +22,6 @@ import io.openliberty.tools.intellij.LibertyPluginIcons; -import static io.openliberty.tools.intellij.util.Constants.SERVER_ENV_GLOB_PATTERN; - /** * Custom file type for server.env files */ @@ -43,9 +36,7 @@ private ServerEnvFileType() { @Override public boolean isMyFileType(@NotNull VirtualFile file) { - Path path = Paths.get(file.getPath()); - final PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + SERVER_ENV_GLOB_PATTERN); - return matcher.matches(path); + return file.getPath().endsWith(".env"); } @Override diff --git a/src/main/java/io/openliberty/tools/intellij/liberty/lsp/ServerEnvSubstitutor.java b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/ServerEnvSubstitutor.java index ba3751455..f1ff61760 100644 --- a/src/main/java/io/openliberty/tools/intellij/liberty/lsp/ServerEnvSubstitutor.java +++ b/src/main/java/io/openliberty/tools/intellij/liberty/lsp/ServerEnvSubstitutor.java @@ -21,13 +21,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.nio.file.FileSystems; -import java.nio.file.Path; -import java.nio.file.PathMatcher; -import java.nio.file.Paths; - -import static io.openliberty.tools.intellij.util.Constants.SERVER_ENV_GLOB_PATTERN; - /** * Language Substitutor for Liberty server.env files * To re-use the IntelliJ parsing for Properties files on server.env files, categorize server.env files that are in a recognized @@ -47,8 +40,6 @@ public class ServerEnvSubstitutor extends LanguageSubstitutor { } private boolean isLibertyServerEnvFile(VirtualFile file) { - Path path = Paths.get(file.getPath()); - final PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + SERVER_ENV_GLOB_PATTERN); - return matcher.matches(path); + return file.getPath().endsWith(".env"); } } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp/JakartaLanguageServer.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp/JakartaLanguageServer.java index 098dff481..e5a61013f 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp/JakartaLanguageServer.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp/JakartaLanguageServer.java @@ -14,8 +14,9 @@ import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.openapi.extensions.PluginId; -import org.microshed.lsp4ij.server.ProcessStreamConnectionProvider; import io.openliberty.tools.intellij.util.Constants; +import io.openliberty.tools.intellij.util.JavaVersionUtil; +import org.microshed.lsp4ij.server.ProcessStreamConnectionProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,18 +32,10 @@ public class JakartaLanguageServer extends ProcessStreamConnectionProvider { private static final Logger LOGGER = LoggerFactory.getLogger(JakartaLanguageServer.class); public JakartaLanguageServer() { + String javaHome = System.getProperty("java.home"); IdeaPluginDescriptor descriptor = PluginManagerCore.getPlugin(PluginId.getId("open-liberty.intellij")); File lsp4JakartaServerPath = new File(descriptor.getPluginPath().toFile(), JAR_DIR + LANGUAGESERVER_JAR); - String javaHome = System.getProperty("java.home"); - if (javaHome == null) { - LOGGER.error("Unable to launch the Eclipse LSP4Jakarta language server. Could not resolve the java home system property"); - return; - } - if (!checkJavaVersion(javaHome, Constants.REQUIRED_JAVA_VERSION)) { - LOGGER.error("Unable to launch the Eclipse LSP4Jakarta language server." + - " Java " + Constants.REQUIRED_JAVA_VERSION + " or more recent is required to run 'Liberty Tools for IntelliJ'." + - " Change the boot Java runtime of the IDE as documented here:" + - " https://www.jetbrains.com/help/idea/switching-boot-jdk.html"); + if(!JavaVersionUtil.isJavaHomeValid(javaHome, Constants.JAKARTA_LANG_SERVER)){ return; } if (lsp4JakartaServerPath.exists()) { diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/AbstractDiagnosticsCollector.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/AbstractDiagnosticsCollector.java index 13b8f35c7..638278b24 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/AbstractDiagnosticsCollector.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/AbstractDiagnosticsCollector.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2022 IBM Corporation and others. + * Copyright (c) 2022, 2023 IBM Corporation and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -13,12 +13,16 @@ package io.openliberty.tools.intellij.lsp4jakarta.lsp4ij; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.diagnostics.IJavaDiagnosticsParticipant; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.diagnostics.JavaDiagnosticsContext; import org.eclipse.lsp4j.Diagnostic; import org.eclipse.lsp4j.DiagnosticSeverity; import org.eclipse.lsp4j.Range; @@ -28,7 +32,7 @@ * Abstract class for collecting Java diagnostics. * */ -public class AbstractDiagnosticsCollector implements DiagnosticsCollector { +public abstract class AbstractDiagnosticsCollector implements DiagnosticsCollector, IJavaDiagnosticsParticipant { /** * Constructor @@ -84,6 +88,25 @@ protected Diagnostic createDiagnostic(PsiElement el, PsiJavaFile unit, String ms return diagnostic; } + /** + * Collect diagnostics according to the context. + * + * @param context the java diagnostics context + * + * @return diagnostics list and null otherwise. + * + */ + @Override + public final List collectDiagnostics(JavaDiagnosticsContext context) { + PsiFile typeRoot = context.getTypeRoot(); + if (typeRoot instanceof PsiJavaFile) { + List diagnostics = new ArrayList<>(); + collectDiagnostics((PsiJavaFile) typeRoot, diagnostics); + return diagnostics; + } + return Collections.emptyList(); + } + /** * Returns diagnostics for the given compilation unit. * @@ -301,4 +324,5 @@ protected static String getSimpleName(String fqName) { protected static boolean isConstructorMethod(PsiMethod m) { return m.isConstructor(); } + } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/JDTUtils.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/JDTUtils.java index 7d250f4ef..d80e49e88 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/JDTUtils.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/JDTUtils.java @@ -17,8 +17,15 @@ import com.intellij.psi.PsiField; import com.intellij.psi.PsiJavaFile; import com.intellij.psi.PsiMethod; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.ExtendedCodeAction; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionContext; +import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.CodeActionKind; +import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4mp.commons.CodeActionResolveData; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class JDTUtils { @@ -73,4 +80,26 @@ public static List getFieldAccessors(PsiJavaFile unit, PsiField field } return accessors; } + + /** + * Returns CodeAction object, which contains details of quickfix. + * + * @param context JavaCodeActionContext + * @param diagnostic diagnostic message + * @param quickFixMessage quickfix message + * @param participantId participant id + * @return CodeAction + */ + public static CodeAction createCodeAction(JavaCodeActionContext context, Diagnostic diagnostic, + String quickFixMessage, String participantId) { + ExtendedCodeAction codeAction = new ExtendedCodeAction(quickFixMessage); + codeAction.setRelevance(0); + codeAction.setDiagnostics(Collections.singletonList(diagnostic)); + codeAction.setKind(CodeActionKind.QuickFix); + codeAction.setData(new CodeActionResolveData(context.getUri(), participantId, + context.getParams().getRange(), Collections.emptyMap(), + context.getParams().isResourceOperationSupported(), + context.getParams().isCommandConfigurationUpdateSupported())); + return codeAction; + } } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/PropertiesManagerForJakarta.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/PropertiesManagerForJakarta.java index dd3fa994e..76f8e8791 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/PropertiesManagerForJakarta.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/PropertiesManagerForJakarta.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020,2022 Red Hat, Inc. + * Copyright (c) 2020, 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, @@ -12,44 +12,31 @@ package io.openliberty.tools.intellij.lsp4jakarta.lsp4ij; -import com.intellij.lang.jvm.JvmTypeDeclaration; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.module.Module; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.annotations.AnnotationDiagnosticsCollector; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.beanvalidation.BeanValidationDiagnosticsCollector; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.cdi.ManagedBeanDiagnosticsCollector; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.JakartaCodeActionHandler; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.di.DependencyInjectionDiagnosticsCollector; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.jax_rs.Jax_RSClassDiagnosticsCollector; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.jax_rs.ResourceMethodDiagnosticsCollector; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.jsonb.JsonbDiagnosticsCollector; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.jsonp.JsonpDiagnosticCollector; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.persistence.PersistenceEntityDiagnosticsCollector; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.persistence.PersistenceMapKeyDiagnosticsCollector; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.servlet.FilterDiagnosticsCollector; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.servlet.ListenerDiagnosticsCollector; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.servlet.ServletDiagnosticsCollector; -import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.websocket.WebSocketDiagnosticsCollector; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.diagnostics.DiagnosticsHandler; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.utils.IPsiUtils; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.internal.core.java.codeaction.CodeActionHandler; import io.openliberty.tools.intellij.lsp4mp4ij.psi.internal.core.ls.PsiUtilsLSImpl; -import org.eclipse.lsp4j.*; +import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.PublishDiagnosticsParams; import org.eclipse.lsp4jakarta.commons.*; -import org.eclipse.lsp4mp.commons.*; +import org.eclipse.lsp4mp.commons.MicroProfileJavaCodeActionParams; +import org.eclipse.lsp4mp.commons.MicroProfileJavaDiagnosticsParams; +import org.eclipse.lsp4mp.commons.MicroProfileJavaDiagnosticsSettings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; -import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; @@ -66,24 +53,13 @@ public static PropertiesManagerForJakarta getInstance() { } private List diagnosticsCollectors = new ArrayList<>(); - private JakartaCodeActionHandler codeActionHandler = new JakartaCodeActionHandler(); + private final CodeActionHandler codeActionHandler; + + private final DiagnosticsHandler diagnosticsHandler; private PropertiesManagerForJakarta() { - diagnosticsCollectors.add(new ServletDiagnosticsCollector()); - diagnosticsCollectors.add(new AnnotationDiagnosticsCollector()); - diagnosticsCollectors.add(new FilterDiagnosticsCollector()); - diagnosticsCollectors.add(new ListenerDiagnosticsCollector()); - diagnosticsCollectors.add(new BeanValidationDiagnosticsCollector()); - diagnosticsCollectors.add(new PersistenceEntityDiagnosticsCollector()); - diagnosticsCollectors.add(new PersistenceMapKeyDiagnosticsCollector()); - diagnosticsCollectors.add(new ResourceMethodDiagnosticsCollector()); - diagnosticsCollectors.add(new Jax_RSClassDiagnosticsCollector()); - diagnosticsCollectors.add(new JsonbDiagnosticsCollector()); - diagnosticsCollectors.add(new ManagedBeanDiagnosticsCollector()); - diagnosticsCollectors.add(new DependencyInjectionDiagnosticsCollector()); - diagnosticsCollectors.add(new JsonpDiagnosticCollector()); - diagnosticsCollectors.add(new WebSocketDiagnosticsCollector()); - codeActionHandler = new JakartaCodeActionHandler(); + codeActionHandler = new CodeActionHandler("jakarta"); + diagnosticsHandler = new DiagnosticsHandler("jakarta"); } /** @@ -94,40 +70,7 @@ private PropertiesManagerForJakarta() { * @return diagnostics for the given uris list. */ public List diagnostics(JakartaDiagnosticsParams params, IPsiUtils utils) { - List uris = params.getUris(); - if (uris == null) { - return Collections.emptyList(); - } - DocumentFormat documentFormat = params.getDocumentFormat(); - List publishDiagnostics = new ArrayList(); - for (String uri : uris) { - List diagnostics = new ArrayList<>(); - PublishDiagnosticsParams publishDiagnostic = new PublishDiagnosticsParams(uri, diagnostics); - publishDiagnostics.add(publishDiagnostic); - collectDiagnostics(uri, utils, documentFormat, diagnostics); - } - return publishDiagnostics; - } - - private void collectDiagnostics(String uri, IPsiUtils utils, DocumentFormat documentFormat, List diagnostics) { - PsiFile typeRoot = ApplicationManager.getApplication().runReadAction((Computable) () -> resolveTypeRoot(uri, utils)); - if (typeRoot == null) { - return; - } - - try { - if (typeRoot instanceof PsiJavaFile) { - Module module = ApplicationManager.getApplication().runReadAction((ThrowableComputable) () -> utils.getModule(uri)); - DumbService.getInstance(module.getProject()).runReadActionInSmartMode(() -> { - PsiJavaFile unit = (PsiJavaFile) typeRoot; - for (DiagnosticsCollector collector : diagnosticsCollectors) { - collector.collectDiagnostics(unit, diagnostics); - } - }); - } - } catch (IOException e) { - LOGGER.warn(e.getLocalizedMessage(), e); - } + return diagnosticsHandler.collectDiagnostics(adapt(params), utils); } /** @@ -405,7 +348,31 @@ private static PsiFile resolveTypeRoot(String uri, Project project) { public List getCodeAction(JakartaJavaCodeActionParams params, IPsiUtils utils) { return ApplicationManager.getApplication().runReadAction((Computable>) () -> { - return codeActionHandler.codeAction(params, utils); + final List unresolvedCodeActions = codeActionHandler.codeAction(adapt(params), utils); + if (unresolvedCodeActions != null) { + final List resolvedCodeActions = new ArrayList<>(unresolvedCodeActions.size()); + unresolvedCodeActions.forEach(unresolvedCodeAction -> { + if (unresolvedCodeAction != null) { + resolvedCodeActions.add(codeActionHandler.resolveCodeAction(unresolvedCodeAction, utils)); + } + }); + return resolvedCodeActions; + } + return null; }); } + + private MicroProfileJavaDiagnosticsParams adapt(JakartaDiagnosticsParams params) { + MicroProfileJavaDiagnosticsParams mpParams = new MicroProfileJavaDiagnosticsParams(params.getUris(), + new MicroProfileJavaDiagnosticsSettings(Collections.emptyList())); + mpParams.setDocumentFormat(params.getDocumentFormat()); + return mpParams; + } + + private MicroProfileJavaCodeActionParams adapt(JakartaJavaCodeActionParams params) { + MicroProfileJavaCodeActionParams mpParams = new MicroProfileJavaCodeActionParams(params.getTextDocument(), params.getRange(), params.getContext()); + mpParams.setResourceOperationSupported(params.isResourceOperationSupported()); + mpParams.setResolveSupported(true); + return mpParams; + } } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/annotations/PostConstructReturnTypeQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/annotations/PostConstructReturnTypeQuickFix.java index 913645bab..bb17f646b 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/annotations/PostConstructReturnTypeQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/annotations/PostConstructReturnTypeQuickFix.java @@ -16,15 +16,25 @@ import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiPrimitiveType; import com.intellij.psi.util.PsiTreeUtil; +import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.JDTUtils; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal.ModifyReturnTypeProposal; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.ExtendedCodeAction; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.IJavaCodeActionParticipant; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionContext; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionResolveContext; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.corrections.proposal.ChangeCorrectionProposal; import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.CodeActionKind; import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.lsp4mp.commons.CodeActionResolveData; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Quick fix for AnnotationDiagnosticsCollector that changes the return type of a method to void. @@ -33,19 +43,45 @@ * @author Yijia Jing * */ -public class PostConstructReturnTypeQuickFix { +public class PostConstructReturnTypeQuickFix implements IJavaCodeActionParticipant { + + private static final Logger LOGGER = Logger.getLogger(PostConstructReturnTypeQuickFix.class.getName()); + private final static String TITLE_MESSAGE = Messages.getMessage("ChangeReturnTypeToVoid"); + + @Override + public String getParticipantId() { + return PostConstructReturnTypeQuickFix.class.getName(); + } + public List getCodeActions(JavaCodeActionContext context, Diagnostic diagnostic) { List codeActions = new ArrayList<>(); - PsiElement node = context.getCoveredNode(); - PsiMethod parentType = getBinding(node); - String name = Messages.getMessage("ChangeReturnTypeToVoid"); - ChangeCorrectionProposal proposal = new ModifyReturnTypeProposal(name, context.getSource().getCompilationUnit(), - context.getASTRoot(), parentType, 0, PsiPrimitiveType.VOID); - CodeAction codeAction = context.convertToCodeAction(proposal, diagnostic); - codeActions.add(codeAction); + final PsiElement node = context.getCoveredNode(); + final PsiMethod parentType = getBinding(node); + + if (parentType != null) { + codeActions.add(JDTUtils.createCodeAction(context, diagnostic, TITLE_MESSAGE, getParticipantId())); + } return codeActions; } + @Override + public CodeAction resolveCodeAction(JavaCodeActionResolveContext context) { + final CodeAction toResolve = context.getUnresolved(); + final PsiElement node = context.getCoveredNode(); + final PsiMethod parentType = getBinding(node); + + assert parentType != null; + ChangeCorrectionProposal proposal = new ModifyReturnTypeProposal(TITLE_MESSAGE, context.getSource().getCompilationUnit(), + context.getASTRoot(), parentType, 0, PsiPrimitiveType.VOID); + try { + WorkspaceEdit we = context.convertToWorkspaceEdit(proposal); + toResolve.setEdit(we); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Unable to create workspace edit for code action to change return type to void", e); + } + return toResolve; + } + protected PsiMethod getBinding(PsiElement node) { if (node instanceof PsiMethod) { return (PsiMethod) node; diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/cdi/ManagedBeanNoArgConstructorQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/cdi/ManagedBeanNoArgConstructorQuickFix.java index 388779d68..0a05b56db 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/cdi/ManagedBeanNoArgConstructorQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/cdi/ManagedBeanNoArgConstructorQuickFix.java @@ -15,18 +15,25 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiModifierListOwner; import com.intellij.psi.util.PsiTreeUtil; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal.AddConstructorProposal; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.ExtendedCodeAction; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.IJavaCodeActionParticipant; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionContext; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionResolveContext; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.corrections.proposal.ChangeCorrectionProposal; import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.CodeActionKind; import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.lsp4mp.commons.CodeActionResolveData; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @@ -37,57 +44,70 @@ * */ -public class ManagedBeanNoArgConstructorQuickFix { +public class ManagedBeanNoArgConstructorQuickFix implements IJavaCodeActionParticipant { + private static final Logger LOGGER = Logger.getLogger(ManagedBeanNoArgConstructorQuickFix.class.getName()); + + @Override + public String getParticipantId() { + return ManagedBeanNoArgConstructorQuickFix.class.getName(); + } public List getCodeActions(JavaCodeActionContext context, Diagnostic diagnostic) { PsiElement node = context.getCoveredNode(); PsiClass parentType = getBinding(node); + if (parentType != null) { - List codeActions = new ArrayList<>(); + return addConstructor(diagnostic, context); + } + return Collections.emptyList(); + } + + @Override + public CodeAction resolveCodeAction(JavaCodeActionResolveContext context) { + final CodeAction toResolve = context.getUnresolved(); + PsiElement node = context.getCoveredNode(); + PsiClass parentType = getBinding(node); - codeActions.addAll(addConstructor(diagnostic, context, parentType)); + String constructorName = toResolve.getTitle(); + ChangeCorrectionProposal proposal = new AddConstructorProposal(constructorName, + context.getSource().getCompilationUnit(), context.getASTRoot(), parentType, 0, + constructorName.equals(Messages.getMessage("AddProtectedConstructor")) ? "protected" : "public"); - return codeActions; + try { + WorkspaceEdit we = context.convertToWorkspaceEdit(proposal); + toResolve.setEdit(we); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Unable to create workspace edit for code actions to add constructors", e); } - return Collections.emptyList(); + + return toResolve; } protected PsiClass getBinding(PsiElement node) { return PsiTreeUtil.getParentOfType(node, PsiClass.class); } - private List addConstructor(Diagnostic diagnostic, JavaCodeActionContext context, PsiClass notUsed) { + private List addConstructor(Diagnostic diagnostic, JavaCodeActionContext context) { List codeActions = new ArrayList<>(); - JavaCodeActionContext targetContext = null; - PsiElement node = null; - PsiClass parentType = null; - - // option for protected constructor - targetContext = context.copy(); - node = targetContext.getCoveredNode(); - parentType = getBinding(node); - String name = Messages.getMessage("AddProtectedConstructor"); - ChangeCorrectionProposal proposal = new AddConstructorProposal(name, - targetContext.getSource().getCompilationUnit(), targetContext.getASTRoot(), parentType, 0); - CodeAction codeAction = targetContext.convertToCodeAction(proposal, diagnostic); - - if (codeAction != null) { - codeActions.add(codeAction); - } + String[] constructorNames = {Messages.getMessage("AddProtectedConstructor"), Messages.getMessage("AddPublicConstructor")}; - // option for public constructor - targetContext = context.copy(); - node = targetContext.getCoveredNode(); - parentType = getBinding(node); - name = Messages.getMessage("AddPublicConstructor"); - proposal = new AddConstructorProposal(name, - targetContext.getSource().getCompilationUnit(), targetContext.getASTRoot(), parentType, 0, "public"); - codeAction = targetContext.convertToCodeAction(proposal, diagnostic); - - if (codeAction != null) { + for (String name : constructorNames) { + CodeAction codeAction = createCodeAction(context, diagnostic, name); codeActions.add(codeAction); } - return codeActions; } -} + + private CodeAction createCodeAction(JavaCodeActionContext context, Diagnostic diagnostic, String label) { + ExtendedCodeAction codeAction = new ExtendedCodeAction(label); + codeAction.setRelevance(0); + codeAction.setDiagnostics(Collections.singletonList(diagnostic)); + codeAction.setKind(CodeActionKind.QuickFix); + codeAction.setTitle(label); + codeAction.setData(new CodeActionResolveData(context.getUri(), getParticipantId(), + context.getParams().getRange(), Collections.emptyMap(), + context.getParams().isResourceOperationSupported(), + context.getParams().isCommandConfigurationUpdateSupported())); + return codeAction; + } +} \ No newline at end of file diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/annotations/AddResourceMissingNameQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/annotations/AddResourceMissingNameQuickFix.java index 82480dc58..59ef91d0d 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/annotations/AddResourceMissingNameQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/annotations/AddResourceMissingNameQuickFix.java @@ -25,4 +25,9 @@ public class AddResourceMissingNameQuickFix extends InsertAnnotationAttributesQu public AddResourceMissingNameQuickFix() { super("jakarta.annotation.Resource", false, "name"); } + + @Override + public String getParticipantId() { + return AddResourceMissingNameQuickFix.class.getName(); + } } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/annotations/AddResourceMissingTypeQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/annotations/AddResourceMissingTypeQuickFix.java index 3a5beb446..a439ffa7d 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/annotations/AddResourceMissingTypeQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/annotations/AddResourceMissingTypeQuickFix.java @@ -26,4 +26,9 @@ public class AddResourceMissingTypeQuickFix extends InsertAnnotationAttributesQu public AddResourceMissingTypeQuickFix() { super("jakarta.annotation.Resource", false, "type"); } + + @Override + public String getParticipantId() { + return AddResourceMissingTypeQuickFix.class.getName(); + } } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/ExtendClassProposal.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/ExtendClassProposal.java index 43d8cba1c..854b08427 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/ExtendClassProposal.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/ExtendClassProposal.java @@ -14,15 +14,36 @@ *******************************************************************************/ package io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiFile; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.corrections.proposal.ASTRewriteCorrectionProposal; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.corrections.proposal.ImplementInterfaceProposal; +import org.eclipse.lsp4j.CodeActionKind; -public class ExtendClassProposal extends ImplementInterfaceProposal { +public class ExtendClassProposal extends ASTRewriteCorrectionProposal { - public ExtendClassProposal(String name, PsiFile sourceCU, PsiClass binding, PsiFile astRoot, - String interfaceType, int relevance) { - super(null, binding, astRoot, interfaceType, relevance, sourceCU); + private final PsiClass fBinding; + private final String parentClassType; + + public ExtendClassProposal(String name, PsiFile targetCU, PsiFile sourceCU, + PsiClass binding, String parentClassType, int relevance) { + super(name, CodeActionKind.QuickFix, targetCU, relevance, sourceCU); + fBinding = binding; + this.parentClassType = parentClassType; } + @Override + public void performUpdate() { + final Project project = fBinding.getProject(); + final PsiClass parentClass = JavaPsiFacade.getInstance(project). + findClass(parentClassType, GlobalSearchScope.allScope(project)); + if (parentClass != null) { + final PsiReferenceList extendsList = fBinding.getExtendsList(); + if (extendsList != null) { + extendsList.add(PsiElementFactory.getInstance(project). + createClassReferenceElement(parentClass)); + } + } + } } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/ModifyModifiersProposal.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/ModifyModifiersProposal.java index 2576c9bd3..3a9b9e115 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/ModifyModifiersProposal.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/ModifyModifiersProposal.java @@ -46,6 +46,8 @@ public class ModifyModifiersProposal extends ChangeCorrectionProposal { // list of modifiers (if they exist) to remove private final List modifiersToRemove; + private boolean isFormatRequired = true; + /** * Constructor for ModifyModifiersProposal that accepts both a list of modifiers to remove as well as to add * @@ -62,6 +64,25 @@ public ModifyModifiersProposal(String label, PsiFile sourceCU, PsiFile invocatio this.modifiersToAdd = modifiersToAdd; this.modifiersToRemove = modifiersToRemove; } + + /** + * Constructor for ModifyModifiersProposal that accepts both a list of modifiers to remove as well as to add + * this constructor having an optional parameter isFormatRequired + * + * @param modifiersToAdd list of valid modifiers as strings to be added + * @param modifiersToRemove list of modifiers as strings to be removed + */ + public ModifyModifiersProposal(String label, PsiFile sourceCU, PsiFile invocationNode, + PsiModifierListOwner binding, int relevance, PsiModifierList modifiers, List modifiersToAdd, List modifiersToRemove, boolean isFormatRequired) { + super(label, CodeActionKind.QuickFix, relevance); + this.sourceCU = sourceCU; + this.invocationNode = invocationNode; + this.binding = binding; + this.modifiers = modifiers; + this.modifiersToAdd = modifiersToAdd; + this.modifiersToRemove = modifiersToRemove; + this.isFormatRequired = isFormatRequired; + } /** * Constructor for ModifyModifiersProposal that accepts only a list of modifiers to add @@ -100,7 +121,9 @@ public Change getChange() { modifiers.setModifierProperty(modifier, true); } }); - PositionUtils.formatDocument(binding); // add the necessary new lines, must use 'binding,' it's already in the document + if (isFormatRequired) { + PositionUtils.formatDocument(binding); // add the necessary new lines, must use 'binding,' it's already in the document + } final Document document = invocationNode.getViewProvider().getDocument(); return new Change(sourceCU.getViewProvider().getDocument(), document); } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/InsertAnnotationAttributesQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/InsertAnnotationAttributesQuickFix.java index 95aebd14d..d65a08d91 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/InsertAnnotationAttributesQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/InsertAnnotationAttributesQuickFix.java @@ -20,7 +20,7 @@ * @author Lidia Ataupillco Ramos * */ -public class InsertAnnotationAttributesQuickFix extends InsertAnnotationQuickFix { +public abstract class InsertAnnotationAttributesQuickFix extends InsertAnnotationQuickFix { public InsertAnnotationAttributesQuickFix(String annotation, String... attributes) { this(annotation, false, attributes); } @@ -29,7 +29,8 @@ public InsertAnnotationAttributesQuickFix(String annotation, boolean generateOnl super(annotation, generateOnlyOneCodeAction, attributes); } - //@Override + @Override protected String getLabel(String annotation, String... attributes) { return Messages.getMessage("AddAtoB", attributes[0], annotation); } + } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/InsertAnnotationQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/InsertAnnotationQuickFix.java index e2383fe94..963c4ed7e 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/InsertAnnotationQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/InsertAnnotationQuickFix.java @@ -15,16 +15,26 @@ import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; +import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.JDTUtils; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal.ModifyAnnotationProposal; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.ExtendedCodeAction; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.IJavaCodeActionParticipant; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionContext; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionResolveContext; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.corrections.proposal.ChangeCorrectionProposal; import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.CodeActionKind; import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.lsp4mp.commons.CodeActionResolveData; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Quickfix for adding new annotations with or without attributes @@ -33,7 +43,7 @@ * @author Lidia Ataupillco Ramos * */ -public class InsertAnnotationQuickFix { +public abstract class InsertAnnotationQuickFix implements IJavaCodeActionParticipant { private final String[] attributes; @@ -41,6 +51,8 @@ public class InsertAnnotationQuickFix { protected final boolean generateOnlyOneCodeAction; + private static final Logger LOGGER = Logger.getLogger(InsertAnnotationQuickFix.class.getName()); + public InsertAnnotationQuickFix(String annotation, String... attributes) { this(annotation, false, attributes); } @@ -62,23 +74,38 @@ public InsertAnnotationQuickFix(String annotation, boolean generateOnlyOneCodeAc public List getCodeActions(JavaCodeActionContext context, Diagnostic diagnostic) { PsiElement node = context.getCoveredNode(); + List codeActions = new ArrayList<>(); + addAttributes(diagnostic, context, codeActions, this.annotation); + return codeActions; + } + + @Override + public CodeAction resolveCodeAction(JavaCodeActionResolveContext context) { + final CodeAction toResolve = context.getUnresolved(); + final PsiElement node = context.getCoveredNode(); PsiModifierListOwner binding = getBinding(node); // annotationNode is null when adding an annotation and non-null when adding attributes. PsiAnnotation annotationNode = PsiTreeUtil.getParentOfType(node, PsiAnnotation.class); - List codeActions = new ArrayList<>(); - addAttributes(diagnostic, context, binding, annotationNode, codeActions, this.annotation); - - return codeActions; + assert binding != null; + String label = getLabel(this.annotation, attributes); + ChangeCorrectionProposal proposal = new ModifyAnnotationProposal(label, context.getSource().getCompilationUnit(), + context.getASTRoot(), binding, annotationNode, 0, this.annotation, Arrays.asList(attributes)); + try { + WorkspaceEdit we = context.convertToWorkspaceEdit(proposal); + toResolve.setEdit(we); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Unable to create workspace edit for code action " + label, e); + } + return toResolve; } - protected void addAttributes(Diagnostic diagnostic, JavaCodeActionContext context, PsiModifierListOwner binding, - PsiAnnotation annotation, List codeActions, String name) { + protected void addAttributes(Diagnostic diagnostic, JavaCodeActionContext context, List codeActions, String name) { if (generateOnlyOneCodeAction) { - addAttribute(diagnostic, context, binding, annotation, codeActions, name, attributes); + addAttribute(diagnostic, context, codeActions, name, attributes); } else { for (String attribute : attributes) { - addAttribute(diagnostic, context, binding, annotation, codeActions, name, attribute); + addAttribute(diagnostic, context, codeActions, name, attribute); } } } @@ -88,16 +115,9 @@ protected void addAttributes(Diagnostic diagnostic, JavaCodeActionContext contex * collector class. * */ - private void addAttribute(Diagnostic diagnostic, JavaCodeActionContext context, PsiModifierListOwner binding, - PsiAnnotation annotation, List codeActions, String name, String... attributes) { + private void addAttribute(Diagnostic diagnostic, JavaCodeActionContext context, List codeActions, String name, String... attributes) { String label = getLabel(name, attributes); - ChangeCorrectionProposal proposal = new ModifyAnnotationProposal(label, context.getSource().getCompilationUnit(), - context.getASTRoot(), binding, annotation, 0, name, Arrays.asList(attributes)); - CodeAction codeAction = context.convertToCodeAction(proposal, diagnostic); - - if (codeAction != null) { - codeActions.add(codeAction); - } + codeActions.add(JDTUtils.createCodeAction(context, diagnostic, label, getParticipantId())); } protected PsiModifierListOwner getBinding(PsiElement node) { diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveAbstractModifierQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveAbstractModifierQuickFix.java index 65a34ac76..db8ae2b97 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveAbstractModifierQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveAbstractModifierQuickFix.java @@ -23,4 +23,9 @@ public class RemoveAbstractModifierQuickFix extends RemoveModifierConflictQuickF public RemoveAbstractModifierQuickFix() { super (false, "abstract"); } + + @Override + public String getParticipantId() { + return RemoveAbstractModifierQuickFix.class.getName(); + } } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveFinalModifierQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveFinalModifierQuickFix.java index 5e084daac..2b5b3710d 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveFinalModifierQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveFinalModifierQuickFix.java @@ -25,4 +25,9 @@ public class RemoveFinalModifierQuickFix extends RemoveModifierConflictQuickFix public RemoveFinalModifierQuickFix() { super(false, "final"); } + + @Override + public String getParticipantId() { + return RemoveFinalModifierQuickFix.class.getName(); + } } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveModifierConflictQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveModifierConflictQuickFix.java index 43b671504..f0735152a 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveModifierConflictQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveModifierConflictQuickFix.java @@ -15,11 +15,22 @@ import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; +import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.JDTUtils; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal.ModifyModifiersProposal; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.ExtendedCodeAction; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.IJavaCodeActionParticipant; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionContext; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionResolveContext; import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.CodeActionKind; import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.lsp4mp.commons.CodeActionResolveData; + + +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.ArrayList; import java.util.Arrays; @@ -32,11 +43,13 @@ * @author Himanshu Chotwani * */ -public class RemoveModifierConflictQuickFix { +public abstract class RemoveModifierConflictQuickFix implements IJavaCodeActionParticipant { private final String[] modifiers; protected final boolean generateOnlyOneCodeAction; + + private static final Logger LOGGER = Logger.getLogger(RemoveModifierConflictQuickFix.class.getName()); /** @@ -64,16 +77,16 @@ public RemoveModifierConflictQuickFix(boolean generateOnlyOneCodeAction, String. this.generateOnlyOneCodeAction = generateOnlyOneCodeAction; this.modifiers = modifiers; } - public List getCodeActions(JavaCodeActionContext context, Diagnostic diagnostic) { List codeActions = new ArrayList<>(); removeModifiers(diagnostic, context, codeActions); return codeActions; } - + + protected void removeModifiers(Diagnostic diagnostic, JavaCodeActionContext context, - List codeActions) { + List codeActions) { if (generateOnlyOneCodeAction || modifiers.length == 1) { removeModifier(diagnostic, context, codeActions, modifiers); } else { @@ -83,26 +96,35 @@ protected void removeModifiers(Diagnostic diagnostic, JavaCodeActionContext cont } } } - - /** - * use setData() API with diagnostic to pass in ElementType in diagnostic collector class. - * - */ - private void removeModifier(Diagnostic diagnostic, JavaCodeActionContext context, - List codeActions, String... modifier) { - PsiElement node = context.getCoveredNode(); - PsiClass parentType = getBinding(node); - PsiModifierListOwner modifierListOwner = PsiTreeUtil.getParentOfType(node, PsiModifierListOwner.class); - String label = getLabel(modifierListOwner, modifier); + @Override + public CodeAction resolveCodeAction(JavaCodeActionResolveContext context) { + final CodeAction toResolve = context.getUnresolved(); + final PsiElement node = context.getCoveredNode(); + final PsiClass parentType = getBinding(node); + final PsiModifierListOwner modifierListOwner = PsiTreeUtil.getParentOfType(node, PsiModifierListOwner.class); + String label = getLabel(modifierListOwner, modifiers); + + assert parentType != null; ModifyModifiersProposal proposal = new ModifyModifiersProposal(label, context.getSource().getCompilationUnit(), - context.getASTRoot(), parentType, 0, modifierListOwner.getModifierList(), Collections.emptyList(), Arrays.asList(modifier)); - CodeAction codeAction = context.convertToCodeAction(proposal, diagnostic); + context.getASTRoot(), parentType, 0, modifierListOwner.getModifierList(), Collections.emptyList(), Arrays.asList(modifiers), false); - if (codeAction != null) { - codeActions.add(codeAction); + try { + WorkspaceEdit we = context.convertToWorkspaceEdit(proposal); + toResolve.setEdit(we); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Unable to create workspace edit for code action " + label, e); } + return toResolve; + } + + private void removeModifier(Diagnostic diagnostic, JavaCodeActionContext context, + List codeActions, String... modifier) { + PsiElement node = context.getCoveredNode(); + PsiModifierListOwner modifierListOwner = PsiTreeUtil.getParentOfType(node, PsiModifierListOwner.class); + String label = getLabel(modifierListOwner, modifier); + codeActions.add(JDTUtils.createCodeAction(context, diagnostic, label, getParticipantId())); } private String getLabel(PsiModifierListOwner modifierListOwner, String... modifier) { @@ -124,5 +146,4 @@ private String getLabel(PsiModifierListOwner modifierListOwner, String... modifi protected PsiClass getBinding(PsiElement node) { return PsiTreeUtil.getParentOfType(node, PsiClass.class); } - } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveStaticModifierQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveStaticModifierQuickFix.java index d46449d2c..6bc8acf5e 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveStaticModifierQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/codeAction/proposal/quickfix/RemoveStaticModifierQuickFix.java @@ -26,4 +26,9 @@ public class RemoveStaticModifierQuickFix extends RemoveModifierConflictQuickFix public RemoveStaticModifierQuickFix() { super(false, "static"); } + + @Override + public String getParticipantId() { + return RemoveStaticModifierQuickFix.class.getName(); + } } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/jax_rs/NonPublicResourceMethodQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/jax_rs/NonPublicResourceMethodQuickFix.java index c5919256e..effd6643c 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/jax_rs/NonPublicResourceMethodQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/jax_rs/NonPublicResourceMethodQuickFix.java @@ -17,15 +17,23 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.util.PsiTreeUtil; +import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.JDTUtils; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal.ModifyModifiersProposal; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.ExtendedCodeAction; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.IJavaCodeActionParticipant; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionContext; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionResolveContext; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.corrections.proposal.ChangeCorrectionProposal; import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.CodeActionKind; import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.lsp4mp.commons.CodeActionResolveData; -import java.util.Collections; -import java.util.List; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Quick fix for ResourceMethodDiagnosticsCollector that uses @@ -34,26 +42,45 @@ * @author Matthew Shocrylas * */ -public class NonPublicResourceMethodQuickFix { +public class NonPublicResourceMethodQuickFix implements IJavaCodeActionParticipant { + + private static final Logger LOGGER = Logger.getLogger(NonPublicResourceMethodQuickFix.class.getName()); private final static String TITLE_MESSAGE = Messages.getMessage("MakeMethodPublic"); + @Override + public String getParticipantId() { + return NonPublicResourceMethodQuickFix.class.getName(); + } + public List getCodeActions(JavaCodeActionContext context, Diagnostic diagnostic) { final PsiElement node = context.getCoveredNode(); - final PsiClass parentType = PsiTreeUtil.getParentOfType(node, PsiClass.class); final PsiMethod parentMethod = PsiTreeUtil.getParentOfType(node, PsiMethod.class); if (parentMethod != null) { - ChangeCorrectionProposal proposal = new ModifyModifiersProposal(TITLE_MESSAGE, context.getSource().getCompilationUnit(), - context.getASTRoot(), parentType, 0, parentMethod.getModifierList(), Collections.singletonList("public")); - - // Convert the proposal to LSP4J CodeAction - CodeAction codeAction = context.convertToCodeAction(proposal, diagnostic); - codeAction.setTitle(TITLE_MESSAGE); - return Collections.singletonList(codeAction); + return Collections.singletonList(JDTUtils.createCodeAction(context, diagnostic, TITLE_MESSAGE, getParticipantId())); } return Collections.emptyList(); } + @Override + public CodeAction resolveCodeAction(JavaCodeActionResolveContext context) { + + final CodeAction toResolve = context.getUnresolved(); + final PsiElement node = context.getCoveredNode(); + final PsiClass parentType = PsiTreeUtil.getParentOfType(node, PsiClass.class); + final PsiMethod parentMethod = PsiTreeUtil.getParentOfType(node, PsiMethod.class); + + assert parentMethod != null; + ChangeCorrectionProposal proposal = new ModifyModifiersProposal(TITLE_MESSAGE, context.getSource().getCompilationUnit(), + context.getASTRoot(), parentType, 0, parentMethod.getModifierList(), Collections.singletonList("public")); + try { + WorkspaceEdit we = context.convertToWorkspaceEdit(proposal); + toResolve.setEdit(we); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Unable to create workspace edit for code action to make method public", e); + } + return toResolve; + } } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/persistence/PersistenceEntityQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/persistence/PersistenceEntityQuickFix.java index 3f3635ab7..5aee7f1fb 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/persistence/PersistenceEntityQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/persistence/PersistenceEntityQuickFix.java @@ -18,13 +18,22 @@ import com.intellij.psi.util.PsiTreeUtil; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal.AddConstructorProposal; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.ExtendedCodeAction; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.IJavaCodeActionParticipant; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionContext; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionResolveContext; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.corrections.proposal.ChangeCorrectionProposal; import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.CodeActionKind; import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.lsp4mp.commons.CodeActionResolveData; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; /** * QuickFix for fixing {@link PersistenceConstants#DIAGNOSTIC_CODE_MISSING_ATTRIBUTES} error @@ -54,59 +63,70 @@ * @author Leslie Dawson (lamminade) * */ -public class PersistenceEntityQuickFix { +public class PersistenceEntityQuickFix implements IJavaCodeActionParticipant { + private static final Logger LOGGER = Logger.getLogger(PersistenceEntityQuickFix.class.getName()); + + @Override + public String getParticipantId() { + return PersistenceEntityQuickFix.class.getName(); + } + public List getCodeActions(JavaCodeActionContext context, Diagnostic diagnostic) { List codeActions = new ArrayList<>(); PsiElement node = context.getCoveredNode(); PsiClass parentType = getBinding(node); + if (parentType != null) { + codeActions.addAll(addConstructor(diagnostic, context)); + } + return codeActions; + } + + @Override + public CodeAction resolveCodeAction(JavaCodeActionResolveContext context) { + final CodeAction toResolve = context.getUnresolved(); + PsiElement node = context.getCoveredNode(); + PsiClass parentType = getBinding(node); - // add constructor - if (diagnostic.getCode().getLeft().equals(PersistenceConstants.DIAGNOSTIC_CODE_MISSING_EMPTY_CONSTRUCTOR)) { - codeActions.addAll(addConstructor(diagnostic, context, parentType)); - } + String constructorName = toResolve.getTitle(); + ChangeCorrectionProposal proposal = new AddConstructorProposal(constructorName, + context.getSource().getCompilationUnit(), context.getASTRoot(), parentType, 0, + constructorName.equals(Messages.getMessage("AddNoArgProtectedConstructor")) ? "protected" : "public"); + try { + WorkspaceEdit we = context.convertToWorkspaceEdit(proposal); + toResolve.setEdit(we); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Unable to create workspace edit for code actions to add constructors", e); } - return codeActions; + return toResolve; } protected PsiClass getBinding(PsiElement node) { return PsiTreeUtil.getParentOfType(node, PsiClass.class); } - private List addConstructor(Diagnostic diagnostic, JavaCodeActionContext context, PsiClass notUsed) { + private List addConstructor(Diagnostic diagnostic, JavaCodeActionContext context) { List codeActions = new ArrayList<>(); - JavaCodeActionContext targetContext = null; - PsiElement node = null; - PsiClass parentType = null; - - // option for protected constructor - targetContext = context.copy(); - node = targetContext.getCoveredNode(); - parentType = getBinding(node); - String name = Messages.getMessage("AddNoArgProtectedConstructor"); - ChangeCorrectionProposal proposal = new AddConstructorProposal(name, - targetContext.getSource().getCompilationUnit(), targetContext.getASTRoot(), parentType, 0); - CodeAction codeAction = targetContext.convertToCodeAction(proposal, diagnostic); + String[] constructorNames = {Messages.getMessage("AddNoArgProtectedConstructor"), Messages.getMessage("AddNoArgPublicConstructor")}; - if (codeAction != null) { + for (String name : constructorNames) { + CodeAction codeAction = createCodeAction(context, diagnostic, name); codeActions.add(codeAction); } - - // option for public constructor - targetContext = context.copy(); - node = targetContext.getCoveredNode(); - parentType = getBinding(node); - name = Messages.getMessage("AddNoArgPublicConstructor"); - proposal = new AddConstructorProposal(name, - targetContext.getSource().getCompilationUnit(), targetContext.getASTRoot(), parentType, 0, "public"); - codeAction = targetContext.convertToCodeAction(proposal, diagnostic); - - if (codeAction != null) { - codeActions.add(codeAction); - } - return codeActions; } -} + private CodeAction createCodeAction(JavaCodeActionContext context, Diagnostic diagnostic, String label) { + ExtendedCodeAction codeAction = new ExtendedCodeAction(label); + codeAction.setRelevance(0); + codeAction.setDiagnostics(Collections.singletonList(diagnostic)); + codeAction.setKind(CodeActionKind.QuickFix); + codeAction.setTitle(label); + codeAction.setData(new CodeActionResolveData(context.getUri(), getParticipantId(), + context.getParams().getRange(), Collections.emptyMap(), + context.getParams().isResourceOperationSupported(), + context.getParams().isCommandConfigurationUpdateSupported())); + return codeAction; + } +} \ No newline at end of file diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/servlet/HttpServletQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/servlet/HttpServletQuickFix.java index 338f6a91d..a945e3ace 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/servlet/HttpServletQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/servlet/HttpServletQuickFix.java @@ -18,48 +18,93 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; +import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.JDTUtils; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages; import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.codeAction.proposal.ExtendClassProposal; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.ExtendedCodeAction; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.IJavaCodeActionParticipant; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionContext; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codeaction.JavaCodeActionResolveContext; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.corrections.proposal.ChangeCorrectionProposal; import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.CodeActionKind; import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.lsp4mp.commons.CodeActionResolveData; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; /** * QuickFix for fixing HttpServlet extension error by providing the code actions * which implements IJavaCodeActionParticipant - * + *

* Adapted from * https://github.com/eclipse/lsp4mp/blob/master/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/src/main/java/org/eclipse/lsp4mp/jdt/internal/health/java/ImplementHealthCheckQuickFix.java * * @author Credit to Angelo ZERR - * */ -public class HttpServletQuickFix { +public class HttpServletQuickFix implements IJavaCodeActionParticipant { + + private static final Logger LOGGER = Logger.getLogger(HttpServletQuickFix.class.getName()); + + @Override + public String getParticipantId() { + return HttpServletQuickFix.class.getName(); + } + + /** + * Generates a list of code actions based on the provided JavaCodeActionContext and Diagnostic. + * + * @param context the java code action context. + * @param diagnostic the diagnostic which must be fixed and null otherwise. + * @return + */ public List getCodeActions(JavaCodeActionContext context, Diagnostic diagnostic) { List codeActions = new ArrayList<>(); PsiElement node = context.getCoveredNode(); PsiClass parentType = getBinding(node); + if (parentType != null) { - // Create code action - // interface String title = Messages.getMessage("LetClassExtend", parentType.getName(), ServletConstants.HTTP_SERVLET); - ChangeCorrectionProposal proposal = new ExtendClassProposal(title, - context.getSource().getCompilationUnit(), parentType, context.getASTRoot(), - "jakarta.servlet.http.HttpServlet", 0); - CodeAction codeAction = context.convertToCodeAction(proposal, diagnostic); - if (codeAction != null) { - codeActions.add(codeAction); - } + codeActions.add(JDTUtils.createCodeAction(context, diagnostic, title, getParticipantId())); } return codeActions; } + /** + * this method will resolve the code for the quick actions + * + * @param context the code action context to resolve + * @return + */ + @Override + public CodeAction resolveCodeAction(JavaCodeActionResolveContext context) { + final CodeAction toResolve = context.getUnresolved(); + final PsiElement node = context.getCoveredNode(); + final PsiClass parentType = getBinding(node); + + assert parentType != null; + String title = Messages.getMessage("LetClassExtend", + parentType.getName(), + ServletConstants.HTTP_SERVLET); + ChangeCorrectionProposal proposal = new ExtendClassProposal(title, context.getCompilationUnit(), + context.getSource().getCompilationUnit(), parentType, + "jakarta.servlet.http.HttpServlet", 0); + try { + WorkspaceEdit we = context.convertToWorkspaceEdit(proposal); + toResolve.setEdit(we); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Unable to create workspace edit for code action to extend the HttpServlet class.", e); + } + return toResolve; + } + private PsiClass getBinding(PsiElement node) { return PsiTreeUtil.getParentOfType(node, PsiClass.class); } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/websocket/AddPathParamQuickFix.java b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/websocket/AddPathParamQuickFix.java index 34b24295f..bb5be1464 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/websocket/AddPathParamQuickFix.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4jakarta/lsp4ij/websocket/AddPathParamQuickFix.java @@ -25,4 +25,9 @@ public class AddPathParamQuickFix extends InsertAnnotationQuickFix { public AddPathParamQuickFix() { super("jakarta.websocket.server.PathParam", false, "value"); } + + @Override + public String getParticipantId() { + return AddPathParamQuickFix.class.getName(); + } } diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4mp/lsp/MicroProfileServer.java b/src/main/java/io/openliberty/tools/intellij/lsp4mp/lsp/MicroProfileServer.java index 5bff66223..995daf6f3 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4mp/lsp/MicroProfileServer.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4mp/lsp/MicroProfileServer.java @@ -13,8 +13,9 @@ import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.openapi.extensions.PluginId; -import org.microshed.lsp4ij.server.ProcessStreamConnectionProvider; import io.openliberty.tools.intellij.util.Constants; +import io.openliberty.tools.intellij.util.JavaVersionUtil; +import org.microshed.lsp4ij.server.ProcessStreamConnectionProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,18 +34,10 @@ public class MicroProfileServer extends ProcessStreamConnectionProvider { private static final Logger LOGGER = LoggerFactory.getLogger(MicroProfileServer.class); public MicroProfileServer() { + String javaHome = System.getProperty("java.home"); IdeaPluginDescriptor descriptor = PluginManagerCore.getPlugin(PluginId.getId("open-liberty.intellij")); File lsp4mpServerPath = new File(descriptor.getPluginPath().toFile(), "lib/server/org.eclipse.lsp4mp.ls-uber.jar"); - String javaHome = System.getProperty("java.home"); - if (javaHome == null) { - LOGGER.error("Unable to launch the Eclipse LSP4MP language server. Could not resolve the java home system property"); - return; - } - if (!checkJavaVersion(javaHome, Constants.REQUIRED_JAVA_VERSION)) { - LOGGER.error("Unable to launch the Eclipse LSP4MP language server." + - " Java " + Constants.REQUIRED_JAVA_VERSION + " or more recent is required to run 'Liberty Tools for IntelliJ'." + - " Change the boot Java runtime of the IDE as documented here:" + - " https://www.jetbrains.com/help/idea/switching-boot-jdk.html"); + if(!JavaVersionUtil.isJavaHomeValid(javaHome, Constants.MICROPROFILE_SERVER)){ return; } if (lsp4mpServerPath.exists()) { diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/core/PropertiesManagerForJava.java b/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/core/PropertiesManagerForJava.java index 25592fe70..c7cb709e8 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/core/PropertiesManagerForJava.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/core/PropertiesManagerForJava.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020 Red Hat, Inc. + * Copyright (c) 2020, 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, @@ -14,10 +14,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.module.Module; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; @@ -27,6 +24,7 @@ import com.intellij.psi.PsiModifierListOwner; import com.intellij.psi.PsiParameter; import com.intellij.psi.util.PsiTreeUtil; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.diagnostics.DiagnosticsHandler; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.utils.IPsiUtils; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codelens.IJavaCodeLensParticipant; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.codelens.JavaCodeLensContext; @@ -34,8 +32,6 @@ import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.completion.JavaCompletionContext; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.definition.IJavaDefinitionParticipant; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.definition.JavaDefinitionContext; -import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.diagnostics.IJavaDiagnosticsParticipant; -import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.diagnostics.JavaDiagnosticsContext; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.hover.IJavaHoverParticipant; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.hover.JavaHoverContext; import io.openliberty.tools.intellij.lsp4mp4ij.psi.internal.core.java.codeaction.CodeActionHandler; @@ -51,10 +47,8 @@ import org.eclipse.lsp4mp.commons.MicroProfileJavaCompletionParams; import org.eclipse.lsp4mp.commons.MicroProfileJavaDefinitionParams; import org.eclipse.lsp4mp.commons.MicroProfileJavaDiagnosticsParams; -import org.eclipse.lsp4mp.commons.MicroProfileJavaDiagnosticsSettings; import org.eclipse.lsp4mp.commons.MicroProfileJavaFileInfoParams; import org.eclipse.lsp4mp.commons.MicroProfileJavaHoverParams; -import org.eclipse.lsp4j.Diagnostic; import org.eclipse.lsp4j.Hover; import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.PublishDiagnosticsParams; @@ -86,8 +80,11 @@ public static PropertiesManagerForJava getInstance() { private final CodeActionHandler codeActionHandler; + private final DiagnosticsHandler diagnosticsHandler; + private PropertiesManagerForJava() { - this.codeActionHandler = new CodeActionHandler(); + this.codeActionHandler = new CodeActionHandler("mp"); + this.diagnosticsHandler = new DiagnosticsHandler("mp"); } /** @@ -285,53 +282,7 @@ private void collectDefinition(String uri, PsiFile typeRoot, PsiElement hyperlin * @return diagnostics for the given uris list. */ public List diagnostics(MicroProfileJavaDiagnosticsParams params, IPsiUtils utils) { - List uris = params.getUris(); - if (uris == null) { - return Collections.emptyList(); - } - DocumentFormat documentFormat = params.getDocumentFormat(); - List publishDiagnostics = new ArrayList(); - for (String uri : uris) { - List diagnostics = new ArrayList<>(); - PublishDiagnosticsParams publishDiagnostic = new PublishDiagnosticsParams(uri, diagnostics); - publishDiagnostics.add(publishDiagnostic); - collectDiagnostics(uri, utils, documentFormat, params.getSettings(), diagnostics); - } - return publishDiagnostics; - } - - private void collectDiagnostics(String uri, IPsiUtils utils, DocumentFormat documentFormat, - MicroProfileJavaDiagnosticsSettings settings, List diagnostics) { - PsiFile typeRoot = ApplicationManager.getApplication().runReadAction((Computable) () -> resolveTypeRoot(uri, utils)); - if (typeRoot == null) { - return; - } - - try { - Module module = ApplicationManager.getApplication().runReadAction((ThrowableComputable) () -> utils.getModule(uri)); - DumbService.getInstance(module.getProject()).runReadActionInSmartMode(() -> { - // Collect all adapted diagnostics participant - JavaDiagnosticsContext context = new JavaDiagnosticsContext(uri, typeRoot, utils, module, documentFormat, settings); - List definitions = IJavaDiagnosticsParticipant.EP_NAME.extensions() - .filter(definition -> definition.isAdaptedForDiagnostics(context)) - .collect(Collectors.toList()); - if (definitions.isEmpty()) { - return; - } - - // Begin, collect, end participants - definitions.forEach(definition -> definition.beginDiagnostics(context)); - definitions.forEach(definition -> { - List collectedDiagnostics = definition.collectDiagnostics(context); - if (collectedDiagnostics != null && !collectedDiagnostics.isEmpty()) { - diagnostics.addAll(collectedDiagnostics); - } - }); - definitions.forEach(definition -> definition.endDiagnostics(context)); - }); - } catch (IOException e) { - LOGGER.warn(e.getLocalizedMessage(), e); - } + return diagnosticsHandler.collectDiagnostics(params, utils); } /** diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/core/java/diagnostics/DiagnosticsHandler.java b/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/core/java/diagnostics/DiagnosticsHandler.java new file mode 100644 index 000000000..66736fa23 --- /dev/null +++ b/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/core/java/diagnostics/DiagnosticsHandler.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2020, 2023 Red Hat Inc. and others. + * All rights reserved. This program and the accompanying materials + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ + +package io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.diagnostics; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.ThrowableComputable; +import com.intellij.psi.PsiFile; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.utils.IPsiUtils; +import io.openliberty.tools.intellij.lsp4mp4ij.psi.internal.core.java.corrections.JavaDiagnosticsDefinition; +import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.PublishDiagnosticsParams; +import org.eclipse.lsp4mp.commons.DocumentFormat; +import org.eclipse.lsp4mp.commons.MicroProfileJavaDiagnosticsParams; +import org.eclipse.lsp4mp.commons.MicroProfileJavaDiagnosticsSettings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class DiagnosticsHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(DiagnosticsHandler.class); + + private final String group; + + public DiagnosticsHandler(String group) { + this.group = group; + } + + public List collectDiagnostics(MicroProfileJavaDiagnosticsParams params, IPsiUtils utils) { + List uris = params.getUris(); + if (uris == null) { + return Collections.emptyList(); + } + DocumentFormat documentFormat = params.getDocumentFormat(); + List publishDiagnostics = new ArrayList<>(); + for (String uri : uris) { + List diagnostics = new ArrayList<>(); + PublishDiagnosticsParams publishDiagnostic = new PublishDiagnosticsParams(uri, diagnostics); + publishDiagnostics.add(publishDiagnostic); + collectDiagnostics(uri, utils, documentFormat, params.getSettings(), diagnostics); + } + return publishDiagnostics; + } + + private void collectDiagnostics(String uri, IPsiUtils utils, DocumentFormat documentFormat, + MicroProfileJavaDiagnosticsSettings settings, List diagnostics) { + PsiFile typeRoot = ApplicationManager.getApplication().runReadAction((Computable) () -> resolveTypeRoot(uri, utils)); + if (typeRoot == null) { + return; + } + + try { + Module module = ApplicationManager.getApplication().runReadAction((ThrowableComputable) () -> utils.getModule(uri)); + DumbService.getInstance(module.getProject()).runReadActionInSmartMode(() -> { + // Collect all adapted diagnostic definitions + JavaDiagnosticsContext context = new JavaDiagnosticsContext(uri, typeRoot, utils, module, documentFormat, settings); + List definitions = JavaDiagnosticsDefinition.EP_NAME.extensions() + .filter(definition -> definition.isAdaptedForDiagnostics(context)) + .filter(definition -> group.equals(definition.getGroup())) + .collect(Collectors.toList()); + if (definitions.isEmpty()) { + return; + } + + // Begin, collect, end participants + definitions.forEach(definition -> definition.beginDiagnostics(context)); + definitions.forEach(definition -> { + List collectedDiagnostics = definition.collectDiagnostics(context); + if (collectedDiagnostics != null && !collectedDiagnostics.isEmpty()) { + diagnostics.addAll(collectedDiagnostics); + } + }); + definitions.forEach(definition -> definition.endDiagnostics(context)); + }); + } catch (IOException e) { + LOGGER.warn(e.getLocalizedMessage(), e); + } + } + + // REVISIT: Make this a public method on a common utility class? + private static PsiFile resolveTypeRoot(String uri, IPsiUtils utils) { + return utils.resolveCompilationUnit(uri); + } +} diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/core/java/diagnostics/IJavaDiagnosticsParticipant.java b/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/core/java/diagnostics/IJavaDiagnosticsParticipant.java index e0a088802..52d0976f7 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/core/java/diagnostics/IJavaDiagnosticsParticipant.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/core/java/diagnostics/IJavaDiagnosticsParticipant.java @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2020 Red Hat Inc. and others. +* Copyright (c) 2020, 2023 Red Hat Inc. and others. * All rights reserved. This program and the accompanying materials * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-v20.html @@ -11,11 +11,10 @@ *******************************************************************************/ package io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.diagnostics; -import java.util.List; - -import com.intellij.openapi.extensions.ExtensionPointName; import org.eclipse.lsp4j.Diagnostic; +import java.util.List; + /** * Java diagnostics participants API. * @@ -25,8 +24,6 @@ */ public interface IJavaDiagnosticsParticipant { - public static final ExtensionPointName EP_NAME = ExtensionPointName.create("open-liberty.intellij.javaDiagnosticsParticipant"); - /** * Returns true if diagnostics must be collected for the given context and false * otherwise. diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/internal/core/java/codeaction/CodeActionHandler.java b/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/internal/core/java/codeaction/CodeActionHandler.java index 713f36344..a6bf1347e 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/internal/core/java/codeaction/CodeActionHandler.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/internal/core/java/codeaction/CodeActionHandler.java @@ -47,6 +47,12 @@ */ public class CodeActionHandler { + private final String group; + + public CodeActionHandler(String group) { + this.group = group; + } + /** * Returns all the code actions applicable for the context given by the * parameters. @@ -98,6 +104,7 @@ public List codeAction(MicroProfileJavaCodeActionParams pa // Get list of code action definition for the given kind List codeActionDefinitions = io.openliberty.tools.intellij.lsp4mp4ij.psi.internal.core.java.codeaction.JavaCodeActionDefinition.EP.extensions() .filter(definition -> definition.isAdaptedForCodeAction(context)) + .filter(definition -> group.equals(definition.getGroup())) .filter(definition -> codeActionKind.equals(definition.getKind())) .collect(Collectors.toList()); if (codeActionDefinitions != null) { @@ -201,6 +208,7 @@ public CodeAction resolveCodeAction(CodeAction unresolved, IPsiUtils utils) { IJavaCodeActionParticipant participant = JavaCodeActionDefinition.EP.extensions() .filter(definition -> unresolved.getKind().startsWith(definition.getKind())) + .filter(definition -> group.equals(definition.getGroup())) .filter(definition -> participantId.equals(definition.getParticipantId())) .findFirst().orElse(null); return participant.resolveCodeAction(context.copy()); diff --git a/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/internal/core/java/codeaction/JavaCodeActionDefinition.java b/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/internal/core/java/codeaction/JavaCodeActionDefinition.java index 6d48ae62f..e452bf9f2 100644 --- a/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/internal/core/java/codeaction/JavaCodeActionDefinition.java +++ b/src/main/java/io/openliberty/tools/intellij/lsp4mp4ij/psi/internal/core/java/codeaction/JavaCodeActionDefinition.java @@ -41,11 +41,15 @@ public class JavaCodeActionDefinition extends BaseKeyedLazyInstance + implements IJavaDiagnosticsParticipant { + + public static final ExtensionPointName EP_NAME = ExtensionPointName.create("open-liberty.intellij.javaDiagnosticsParticipant"); + + private static final Logger LOGGER = Logger.getLogger(JavaDiagnosticsDefinition.class.getName()); + private static final String GROUP_ATTR = "group"; + private static final String IMPLEMENTATION_CLASS_ATTR = "implementationClass"; + + @Attribute(GROUP_ATTR) + private String group; + + @Attribute(IMPLEMENTATION_CLASS_ATTR) + public String implementationClass; + + @Override + public boolean isAdaptedForDiagnostics(JavaDiagnosticsContext context) { + try { + return getInstance().isAdaptedForDiagnostics(context); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Error while calling isAdaptedForDiagnostics", e); + return false; + } + } + + @Override + public void beginDiagnostics(JavaDiagnosticsContext context) { + try { + getInstance().beginDiagnostics(context); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Error while calling beginDiagnostics", e); + } + } + + @Override + public List collectDiagnostics(JavaDiagnosticsContext context) { + try { + List diagnostics = getInstance().collectDiagnostics(context); + return diagnostics != null ? diagnostics : Collections.emptyList(); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Error while calling collectDiagnostics", e); + return Collections.emptyList(); + } + } + + @Override + public void endDiagnostics(JavaDiagnosticsContext context) { + try { + getInstance().endDiagnostics(context); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Error while calling endDiagnostics", e); + } + } + + public @Nullable String getGroup() { + return group; + } + + @Override + protected @Nullable String getImplementationClassName() { + return implementationClass; + } +} diff --git a/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java b/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java index ea53d89dc..1266d21a6 100644 --- a/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java +++ b/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java @@ -19,10 +19,14 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.options.SettingsEditor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.JDOMExternalizerUtil; +import com.intellij.openapi.util.WriteExternalException; import io.openliberty.tools.intellij.LibertyModule; import io.openliberty.tools.intellij.LibertyModules; -import io.openliberty.tools.intellij.actions.LibertyDevStartAction; import io.openliberty.tools.intellij.util.Constants; +import org.jdom.Element; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,6 +40,8 @@ public class LibertyRunConfiguration extends ModuleBasedConfiguration

- + @@ -38,6 +38,17 @@ + + + + + + + + + + + diff --git a/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunSettingsEditor.java b/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunSettingsEditor.java index 17546de29..f0dfabdbd 100644 --- a/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunSettingsEditor.java +++ b/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunSettingsEditor.java @@ -15,6 +15,7 @@ import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.LabeledComponent; import com.intellij.ui.EditorTextField; +import com.intellij.ui.StateRestoringCheckBox; import io.openliberty.tools.intellij.LibertyModules; import org.jetbrains.annotations.NotNull; @@ -28,9 +29,7 @@ public class LibertyRunSettingsEditor extends SettingsEditor editableParams; private LabeledComponent libertyModule; - - // FIXME runInContainer - // private LabeledComponent runInContainer; + private StateRestoringCheckBox runInContainerCheckBox; public LibertyRunSettingsEditor(Project project) { libertyModule.getComponent().setModel(new DefaultComboBoxModel(LibertyModules.getInstance().getLibertyBuildFilesAsString(project).toArray())); @@ -48,8 +47,7 @@ protected void resetEditorFrom(@NotNull LibertyRunConfiguration configuration) { break; } } - // FIXME runInContainer state is not being saved, cannot "Apply" run in container checkbox change to run config, see https://github.com/OpenLiberty/liberty-tools-intellij/issues/160 - // runInContainer.getComponent().setSelected(configuration.runInContainer()); + runInContainerCheckBox.setSelected(configuration.runInContainer()); editableParams.getComponent().setText(configuration.getParams()); } @@ -57,8 +55,7 @@ protected void resetEditorFrom(@NotNull LibertyRunConfiguration configuration) { protected void applyEditorTo(@NotNull LibertyRunConfiguration configuration) throws ConfigurationException { configuration.setParams(editableParams.getComponent().getText()); configuration.setBuildFile(String.valueOf(libertyModule.getComponent().getSelectedItem())); - // FIXME runInContainer - // configuration.setRunInContainer(runInContainer.getComponent().isSelected()); + configuration.setRunInContainer(runInContainerCheckBox.isSelected()); } @NotNull @@ -73,8 +70,6 @@ public void createUIComponents() { libertyModule.setComponent(comboBox); editableParams = new LabeledComponent<>(); editableParams.setComponent(new EditorTextField()); - // FIXME runInContainer - // runInContainer = new LabeledComponent<>(); - // runInContainer.setComponent(new StateRestoringCheckBox()); + runInContainerCheckBox = new StateRestoringCheckBox(); } } \ No newline at end of file diff --git a/src/main/java/io/openliberty/tools/intellij/util/Constants.java b/src/main/java/io/openliberty/tools/intellij/util/Constants.java index b0a57e2f8..b5f2801c1 100644 --- a/src/main/java/io/openliberty/tools/intellij/util/Constants.java +++ b/src/main/java/io/openliberty/tools/intellij/util/Constants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020, 2022 IBM Corporation. + * Copyright (c) 2020, 2023 IBM Corporation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -83,7 +83,11 @@ public final class Constants { }); /** - * Constants for langauge servers + * Constants for language servers */ - public static final String SERVER_ENV_GLOB_PATTERN = "**/{src/main/liberty/config,usr/servers/**}/server.env"; + public static final String LIBERTY_XML_SERVER = "LemMinX"; + public static final String LIBERTY_CONFIG_SERVER="Liberty Config"; + public static final String JAKARTA_LANG_SERVER="Eclipse LSP4Jakarta"; + public static final String MICROPROFILE_SERVER="Eclipse LSP4MP"; + } diff --git a/src/main/java/io/openliberty/tools/intellij/util/JavaVersionUtil.java b/src/main/java/io/openliberty/tools/intellij/util/JavaVersionUtil.java new file mode 100644 index 000000000..58426dc87 --- /dev/null +++ b/src/main/java/io/openliberty/tools/intellij/util/JavaVersionUtil.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2023 IBM Corporation. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package io.openliberty.tools.intellij.util; + +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationListener; +import com.intellij.notification.NotificationType; +import com.intellij.notification.Notifications; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import io.openliberty.tools.intellij.LibertyPluginIcons; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class JavaVersionUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(JavaVersionUtil.class); + public static boolean isJavaHomeValid(String javaHome, String serverType) { + + if (javaHome == null) { + String errorMessage = LocalizedResourceUtil.getMessage("javaHome.is.null", serverType, Constants.REQUIRED_JAVA_VERSION); + LOGGER.error(errorMessage); + showErrorPopup(errorMessage); + return false; + } + + File javaHomeDir = new File(javaHome); + if (!javaHomeDir.exists()) { + String errorMessage = LocalizedResourceUtil.getMessage("javaHomeDir.does.not.exist", serverType, Constants.REQUIRED_JAVA_VERSION); + LOGGER.error(errorMessage); + showErrorPopup(errorMessage); + return false; + } + + if (!checkJavaVersion(javaHome, Constants.REQUIRED_JAVA_VERSION)) { + String errorMessage = LocalizedResourceUtil.getMessage("java.version.message", serverType, Constants.REQUIRED_JAVA_VERSION); + LOGGER.error(errorMessage); + showErrorPopup(errorMessage); + return false; + } + return true; + } + + private static void notifyError(String errMsg, Project project) { + Notification notif = new Notification(Constants.LIBERTY_DEV_DASHBOARD_ID, errMsg, NotificationType.WARNING) + .setTitle(LocalizedResourceUtil.getMessage("java.runtime.error.message")) + .setIcon(LibertyPluginIcons.libertyIcon) + .setSubtitle("") + .setListener(NotificationListener.URL_OPENING_LISTENER); + Notifications.Bus.notify(notif, project); + } + + private static void showErrorPopup(String errorMessage) { + notifyError(errorMessage, ProjectManager.getInstance().getDefaultProject()); + + } + + protected static boolean checkJavaVersion(String javaHome, int expectedVersion) { + final ProcessBuilder builder = new ProcessBuilder(javaHome + + File.separator + "bin" + File.separator + "java", "-version"); + try { + final Process p = builder.start(); + final Reader r = new InputStreamReader(p.getErrorStream()); + final StringBuilder sb = new StringBuilder(); + int i; + while ((i = r.read()) != -1) { + sb.append((char) i); + } + return parseMajorJavaVersion(sb.toString()) >= expectedVersion; + } + catch (IOException ioe) {} + return false; + } + + private static int parseMajorJavaVersion(String content) { + final String versionRegex = "version \"(.*)\""; + Pattern p = Pattern.compile(versionRegex); + Matcher m = p.matcher(content); + if (!m.find()) { + return 0; + } + String version = m.group(1); + + // Ignore '1.' prefix for legacy Java versions + if (version.startsWith("1.")) { + version = version.substring(2); + } + + // Extract the major version number. + final String numberRegex = "\\d+"; + p = Pattern.compile(numberRegex); + m = p.matcher(version); + if (!m.find()) { + return 0; + } + return Integer.parseInt(m.group()); + } +} diff --git a/src/main/resources/META-INF/lsp.xml b/src/main/resources/META-INF/lsp.xml index e7d6f6a50..0627bd8c7 100644 --- a/src/main/resources/META-INF/lsp.xml +++ b/src/main/resources/META-INF/lsp.xml @@ -30,7 +30,7 @@ clientImpl="io.openliberty.tools.intellij.liberty.lsp.LibertyConfigLanguageClient" serverInterface="org.eclipse.lsp4mp.ls.api.MicroProfileLanguageServerAPI"/> + filePattern="**/{*.properties,*.env}"/> + + \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 1cc47b632..2c29b9981 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -18,7 +18,7 @@ com.intellij.properties org.jetbrains.idea.maven com.intellij.gradle - + + beanClass="io.openliberty.tools.intellij.lsp4mp4ij.psi.internal.core.java.corrections.JavaDiagnosticsDefinition"/> + + group="mp" + implementationClass="io.openliberty.tools.intellij.lsp4mp4ij.psi.internal.core.java.validators.JavaASTDiagnosticsParticipant"/> + group="mp" + implementationClass="io.openliberty.tools.intellij.lsp4mp4ij.psi.internal.health.java.MicroProfileHealthDiagnosticsParticipant"/> + group="mp" + implementationClass="io.openliberty.tools.intellij.lsp4mp4ij.psi.internal.restclient.java.MicroProfileRestClientDiagnosticsParticipant"/> + group="mp" + implementationClass="io.openliberty.tools.intellij.lsp4mp4ij.psi.internal.metrics.java.MicroProfileMetricsDiagnosticsParticipant"/> + + + + + + + + + + + + + + + + @@ -123,35 +172,95 @@ implementation="io.openliberty.tools.intellij.lsp4mp4ij.psi.internal.restclient.java.MicroProfileRestClientCodeLensParticipant"/> + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/messages/LibertyBundles.properties b/src/main/resources/messages/LibertyBundles.properties index 09318b61a..7defa2fe7 100644 --- a/src/main/resources/messages/LibertyBundles.properties +++ b/src/main/resources/messages/LibertyBundles.properties @@ -51,6 +51,12 @@ liberty.project.file.selection.dialog.message=Select Liberty project for {0} liberty.action.selection.dialog.title=Liberty action liberty.action.selection.dialog.message=Select Liberty action to run +#Messages for Checking javaHome +javaHome.is.null=Unable to launch the {0} language server. Could not resolve the java home system property. Make sure the boot Java runtime of the IDE is set to a valid JDK of Java {1} or later. Change the boot Java runtime of the IDE as documented here https://www.jetbrains.com/help/idea/switching-boot-jdk.html +javaHomeDir.does.not.exist=Unable to launch the {0} language server. The java home directory does not exist. Make sure the boot Java runtime of the IDE is set to a valid JDK of Java {1} or later. Change the boot Java runtime of the IDE as documented here https://www.jetbrains.com/help/idea/switching-boot-jdk.html +java.version.message=Unable to launch the {0} language server. Java {1} or more recent is required to run 'Liberty Tools for IntelliJ'. Change the boot Java runtime of the IDE as documented here https://www.jetbrains.com/help/idea/switching-boot-jdk.html +java.runtime.error.message=Java runtime error + # Messages for Liberty add and remove project actions liberty.project.add=add Liberty project liberty.project.add.dialog.title=Add Liberty project diff --git a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/annotations/PostConstructAnnotationTest.java b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/annotations/PostConstructAnnotationTest.java index 025a3e7f6..62b9efa6d 100644 --- a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/annotations/PostConstructAnnotationTest.java +++ b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/annotations/PostConstructAnnotationTest.java @@ -26,7 +26,6 @@ import org.eclipse.lsp4j.TextEdit; import org.eclipse.lsp4jakarta.commons.JakartaDiagnosticsParams; import org.eclipse.lsp4jakarta.commons.JakartaJavaCodeActionParams; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -64,7 +63,46 @@ public void GeneratedAnnotation() throws Exception { assertJavaDiagnostics(diagnosticsParams, utils, d1, d2, d3); + JakartaJavaCodeActionParams codeActionParams2 = createCodeActionParams(uri, d1); + TextEdit te3 = te(0, 0, 31, 1, "package io.openliberty.sample.jakarta.annotations;\n" + + "\n" + + "import jakarta.annotation.PostConstruct;\n" + + "import jakarta.annotation.Resource;\n" + + "\n" + + "@Resource(type = Object.class, name = \"aa\")\n" + + "public class PostConstructAnnotation {\n" + + "\n" + + " private Integer studentId;\n" + + "\n" + + " private boolean isHappy;\n" + + "\n" + + " private boolean isSad;\n" + + "\n" + + " @PostConstruct()\n" + + " public void getStudentId() {\n" + + " return this.studentId;\n" + + " }\n" + + "\n" + + " @PostConstruct\n" + + " public void getHappiness(String type) {\n" + + "\n" + + " }\n" + + "\n" + + " @PostConstruct\n" + + " public void throwTantrum() throws Exception {\n" + + " System.out.println(\"I'm sad\");\n" + + " }\n" + + "\n" + + " private String emailAddress;\n" + + "\n" + + "}"); + CodeAction ca3 = ca(uri, "Change return type to void", d1, te3); + assertJavaCodeAction(codeActionParams2, utils, ca3); + + // TODO : Enable the remaining test cases once the refactoring is completed. + if (CHECK_CODE_ACTIONS) { + JakartaJavaCodeActionParams codeActionParams1 = createCodeActionParams(uri, d2); TextEdit te1 = te(19, 4, 20, 4, ""); TextEdit te2 = te(20, 29, 20, 40, ""); @@ -72,10 +110,6 @@ public void GeneratedAnnotation() throws Exception { CodeAction ca2 = ca(uri, "Remove all parameters", d2, te2); assertJavaCodeAction(codeActionParams1, utils, ca1, ca2); - JakartaJavaCodeActionParams codeActionParams2 = createCodeActionParams(uri, d1); - TextEdit te3 = te(15, 11, 15, 18, "void"); - CodeAction ca3 = ca(uri, "Change return type to void", d1, te3); - assertJavaCodeAction(codeActionParams2, utils, ca3); } } } diff --git a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/annotations/ResourceAnnotationTest.java b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/annotations/ResourceAnnotationTest.java index 118318a9b..de5e5fd9f 100644 --- a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/annotations/ResourceAnnotationTest.java +++ b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/annotations/ResourceAnnotationTest.java @@ -60,16 +60,38 @@ public void ResourceAnnotation() throws Exception { assertJavaDiagnostics(diagnosticsParams, utils, d1, d2); - if (CHECK_CODE_ACTIONS) { - JakartaJavaCodeActionParams codeActionParams = createCodeActionParams(uri, d1); - TextEdit te = te(22, 0, 22, 22, "@Resource(name = \"aa\", type = \"\")"); - CodeAction ca = ca(uri, "Add type to jakarta.annotation.Resource", d1, te); - assertJavaCodeAction(codeActionParams, utils, ca); + //TODO: uncomment this if condition, once refactoring is done for all the quick fixes. +// if (CHECK_CODE_ACTIONS) { + JakartaJavaCodeActionParams codeActionParams = createCodeActionParams(uri, d1); + String newText = "package io.openliberty.sample.jakarta.annotations;\n\nimport jakarta.annotation.Resource;" + + "\n\n@Resource(type = Object.class, name = \"aa\")\npublic class ResourceAnnotation " + + "{\n\n private Integer studentId;\n\n\n @Resource(shareable = true)\n " + + "private boolean isHappy;\n\n @Resource(name = \"test\")\n " + + " private boolean isSad;\n\n\n private String emailAddress;\n\n\n}\n\n" + + "@Resource(name = \"aa\",type=\"\")\nclass PostDoctoralStudent {\n\n " + + "private Integer studentId;\n\n\n @Resource(shareable = true)\n " + + "private boolean isHappy;\n\n @Resource\n private boolean isSad;\n\n\n " + + "private String emailAddress;\n\n}\n\n@Resource(type = Object.class)\nclass " + + "MasterStudent {\n\n private Integer studentId;\n\n} \n"; + TextEdit te = te(0, 0, 45, 0, newText); + CodeAction ca = ca(uri, "Add type to jakarta.annotation.Resource", d1, te); + assertJavaCodeAction(codeActionParams, utils, ca); - JakartaJavaCodeActionParams codeActionParams1 = createCodeActionParams(uri, d2); - TextEdit te1 = te(39, 0, 39, 30, "@Resource(type = \"\", name = \"\")"); - CodeAction ca1 = ca(uri, "Add name to jakarta.annotation.Resource", d2, te1); - assertJavaCodeAction(codeActionParams1, utils, ca1); - } + JakartaJavaCodeActionParams codeActionParams1 = createCodeActionParams(uri, d2); + newText = "package io.openliberty.sample.jakarta.annotations;\n\n" + + "import jakarta.annotation.Resource;\n\n@Resource(type = Object.class, " + + "name = \"aa\")\npublic class ResourceAnnotation {\n\n private Integer studentId;" + + "\n\n\n @Resource(shareable = true)\n private boolean isHappy;\n\n " + + "@Resource(name = \"test\")\n private boolean isSad;\n\n\n " + + "private String emailAddress;\n\n\n}\n\n@Resource(name = \"aa\")\n" + + "class PostDoctoralStudent {\n\n private Integer studentId;\n\n\n " + + "@Resource(shareable = true)\n private boolean isHappy;\n\n @Resource\n " + + "private boolean isSad;\n\n\n private String emailAddress;\n\n}\n\n" + + "@Resource(type = Object.class, name=\"\")\nclass MasterStudent {\n\n " + + "private Integer studentId;\n\n} \n"; + TextEdit te1 = te(0, 0, 45, 0, newText); + CodeAction ca1 = ca(uri, "Add name to jakarta.annotation.Resource", d2, te1); + assertJavaCodeAction(codeActionParams1, utils, ca1); +// } } } diff --git a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/cdi/ManagedBeanConstructorTest.java b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/cdi/ManagedBeanConstructorTest.java index 9c68b711e..f8a407c09 100644 --- a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/cdi/ManagedBeanConstructorTest.java +++ b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/cdi/ManagedBeanConstructorTest.java @@ -19,6 +19,7 @@ import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import io.openliberty.tools.intellij.lsp4jakarta.it.core.BaseJakartaTest; +import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.utils.IPsiUtils; import io.openliberty.tools.intellij.lsp4mp4ij.psi.internal.core.ls.PsiUtilsLSImpl; import org.eclipse.lsp4j.CodeAction; @@ -27,7 +28,6 @@ import org.eclipse.lsp4j.TextEdit; import org.eclipse.lsp4jakarta.commons.JakartaDiagnosticsParams; import org.eclipse.lsp4jakarta.commons.JakartaJavaCodeActionParams; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -59,20 +59,20 @@ public void managedBeanAnnotations() throws Exception { assertJavaDiagnostics(diagnosticsParams, utils, d); + //TODO Enable the remaining test cases once the refactoring is completed if (CHECK_CODE_ACTIONS) { - // test expected quick-fix - JakartaJavaCodeActionParams codeActionParams1 = createCodeActionParams(uri, d); TextEdit te1 = te(15, 44, 21, 1, "\nimport jakarta.inject.Inject;\n\n@Dependent\npublic class ManagedBeanConstructor {\n private int a;\n \n @Inject\n "); - TextEdit te2 = te(19, 1, 19, 1, - "protected ManagedBeanConstructor() {\n\t}\n\n\t"); - TextEdit te3 = te(19, 1, 19, 1, - "public ManagedBeanConstructor() {\n\t}\n\n\t"); CodeAction ca1 = ca(uri, "Insert @Inject", d, te1); - CodeAction ca2 = ca(uri, "Add a no-arg protected constructor to this class", d, te2); - CodeAction ca3 = ca(uri, "Add a no-arg public constructor to this class", d, te3); - assertJavaCodeAction(codeActionParams1, utils, ca1, ca2, ca3); } - } + // test expected quick-fix + JakartaJavaCodeActionParams codeActionParams1 = createCodeActionParams(uri, d); + TextEdit te2 = te(0, 0, 25, 0, "/*******************************************************************************\n * Copyright (c) 2021 IBM Corporation.\n *\n * This program and the accompanying materials are made available under the\n * terms of the Eclipse Public License v. 2.0 which is available at\n * http://www.eclipse.org/legal/epl-2.0.\n *\n * SPDX-License-Identifier: EPL-2.0\n *\n * Contributors:\n * Hani Damlaj\n *******************************************************************************/\n\npackage io.openliberty.sample.jakarta.cdi;\n\nimport jakarta.enterprise.context.Dependent;\n\n@Dependent\npublic class ManagedBeanConstructor {\n private int a;\n\n protected ManagedBeanConstructor() {\n }\n\n public ManagedBeanConstructor(int a) {\n this.a = a;\n }\n}\n"); + TextEdit te3 = te(0, 0, 25, 0, "/*******************************************************************************\n * Copyright (c) 2021 IBM Corporation.\n *\n * This program and the accompanying materials are made available under the\n * terms of the Eclipse Public License v. 2.0 which is available at\n * http://www.eclipse.org/legal/epl-2.0.\n *\n * SPDX-License-Identifier: EPL-2.0\n *\n * Contributors:\n * Hani Damlaj\n *******************************************************************************/\n\npackage io.openliberty.sample.jakarta.cdi;\n\nimport jakarta.enterprise.context.Dependent;\n\n@Dependent\npublic class ManagedBeanConstructor {\n private int a;\n\n public ManagedBeanConstructor() {\n }\n\n public ManagedBeanConstructor(int a) {\n this.a = a;\n }\n}\n"); + CodeAction ca2 = ca(uri, Messages.getMessage("AddProtectedConstructor"), d, te2); + CodeAction ca3 = ca(uri, Messages.getMessage("AddPublicConstructor"), d, te3); + assertJavaCodeAction(codeActionParams1, utils, ca2, ca3); + + } } diff --git a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/di/DependencyInjectionTest.java b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/di/DependencyInjectionTest.java index 924d70718..6ddd72b8a 100644 --- a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/di/DependencyInjectionTest.java +++ b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/di/DependencyInjectionTest.java @@ -87,30 +87,21 @@ public void DependencyInjectionDiagnostics() throws Exception { TextEdit te = JakartaForJavaAssert.te(16, 4, 17, 4, ""); CodeAction ca = JakartaForJavaAssert.ca(uri, "Remove @Inject", d1, te); - TextEdit te1 = JakartaForJavaAssert.te(17, 11, 17, 17, - ""); - CodeAction ca1 = JakartaForJavaAssert.ca(uri, "Remove the 'final' modifier from this field", d1, te1); - JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca, ca1); + JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca); // for d2 codeActionParams = JakartaForJavaAssert.createCodeActionParams(uri, d2); te = JakartaForJavaAssert.te(32, 4, 33, 4, ""); ca = JakartaForJavaAssert.ca(uri, "Remove @Inject", d2, te); - te1 = JakartaForJavaAssert.te(33, 10, 33, 19, - ""); - ca1 = JakartaForJavaAssert.ca(uri, "Remove the 'abstract' modifier from this method", d2, te1); - JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca, ca1); + JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca); // for d3 codeActionParams = JakartaForJavaAssert.createCodeActionParams(uri, d3); te = JakartaForJavaAssert.te(25, 4, 26, 4, ""); ca = JakartaForJavaAssert.ca(uri, "Remove @Inject", d3, te); - te1 = JakartaForJavaAssert.te(26, 10, 26, 16, - ""); - ca1 = JakartaForJavaAssert.ca(uri, "Remove the 'final' modifier from this method", d3, te1); - JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca, ca1); + JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca); // for d4 codeActionParams = JakartaForJavaAssert.createCodeActionParams(uri, d4); @@ -124,10 +115,136 @@ public void DependencyInjectionDiagnostics() throws Exception { te = JakartaForJavaAssert.te(36, 4, 37, 4, ""); ca = JakartaForJavaAssert.ca(uri, "Remove @Inject", d5, te); - te1 = JakartaForJavaAssert.te(37, 10, 37, 17, - ""); - ca1 = JakartaForJavaAssert.ca(uri, "Remove the 'static' modifier from this method", d5, te1); - JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca, ca1); + JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca); } + + JakartaJavaCodeActionParams codeActionParams = JakartaForJavaAssert.createCodeActionParams(uri, d1); + String textD1 = "package io.openliberty.sample.jakarta.di;\n\n" + + "import jakarta.inject.Inject;\n" + + "import jakarta.enterprise.inject.Produces;\n\n" + + "import java.util.ArrayList;\n" + + "import java.util.List;\n\n" + + "public abstract class GreetingServlet {\n\n " + + "/**\n *\n */\n " + + "private static final long serialVersionUID = 1L;\n\n " + + "// d1: test code for @Inject fields cannot be final\n " + + "@Inject\n private Greeting greeting = new Greeting();\n\n " + + "@Produces\n " + + "public GreetingNoDefaultConstructor getInstance() {\n " + + "return new GreetingNoDefaultConstructor(\"Howdy\");\n }\n\n " + + "// d2\n " + + "@Inject\n public final void injectFinal() {\n " + + "// test code for @Inject methods cannot be final\n " + + "return;\n }\n\n " + + "// d3: test code for @Inject methods cannot be abstract\n " + + "@Inject\n public abstract void injectAbstract();\n\n " + + "// d4: test code for @Inject methods cannot be static\n " + + "@Inject\n " + + "public static void injectStatic() {\n " + + "return;\n }\n\n " + + "// d5: test code for @Inject methods cannot be generic\n " + + "@Inject\n " + + "public List injectGeneric(T arg) {\n " + + "// do nothing\n " + + "return new ArrayList();\n " + + "};\n\n}\n"; + + TextEdit te1 = JakartaForJavaAssert.te(0, 0, 49, 0, textD1); + CodeAction ca1 = JakartaForJavaAssert.ca(uri, "Remove the 'final' modifier from this field", d1, te1); + JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca1); + + String textD2 = "package io.openliberty.sample.jakarta.di;\n\n" + + "import jakarta.inject.Inject;\n" + + "import jakarta.enterprise.inject.Produces;\n\n" + + "import java.util.ArrayList;\n" + + "import java.util.List;\n\n" + + "public abstract class GreetingServlet {\n\n " + + "/**\n *\n */\n " + + "private static final long serialVersionUID = 1L;\n\n " + + "// d1: test code for @Inject fields cannot be final\n " + + "@Inject\n private final Greeting greeting = new Greeting();\n\n " + + "@Produces\n public GreetingNoDefaultConstructor getInstance() {\n " + + "return new GreetingNoDefaultConstructor(\"Howdy\");\n }\n\n " + + "// d2\n @Inject\n public final void injectFinal() {\n " + + "// test code for @Inject methods cannot be final\n " + + "return;\n }\n\n " + + "// d3: test code for @Inject methods cannot be abstract\n " + + "@Inject\n public void injectAbstract();\n\n " + + "// d4: test code for @Inject methods cannot be static\n " + + "@Inject\n public static void injectStatic() {\n " + + "return;\n }\n\n " + + "// d5: test code for @Inject methods cannot be generic\n " + + "@Inject\n " + + "public List injectGeneric(T arg) {\n " + + "// do nothing\n " + + "return new ArrayList();\n " + + "};\n\n}\n"; + codeActionParams = JakartaForJavaAssert.createCodeActionParams(uri, d2); + te1 = JakartaForJavaAssert.te(0, 0, 49, 0, textD2); + ca1 = JakartaForJavaAssert.ca(uri, "Remove the 'abstract' modifier from this method", d2, te1); + JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca1); + + String textD3 = "package io.openliberty.sample.jakarta.di;\n\n" + + "import jakarta.inject.Inject;\n" + + "import jakarta.enterprise.inject.Produces;\n\n" + + "import java.util.ArrayList;\n" + + "import java.util.List;\n\n" + + "public abstract class GreetingServlet {\n\n " + + "/**\n *\n */\n " + + "private static final long serialVersionUID = 1L;\n\n // d1: test code for @Inject fields cannot be final\n " + + "@Inject\n private final Greeting greeting = new Greeting();\n\n " + + "@Produces\n " + + "public GreetingNoDefaultConstructor getInstance() {\n " + + "return new GreetingNoDefaultConstructor(\"Howdy\");\n " + + "}\n\n " + + "// d2\n @Inject\n public void injectFinal() {\n " + + "// test code for @Inject methods cannot be final\n " + + "return;\n }\n\n " + + "// d3: test code for @Inject methods cannot be abstract\n " + + "@Inject\n public abstract void injectAbstract();\n\n " + + "// d4: test code for @Inject methods cannot be static\n " + + "@Inject\n public static void injectStatic() {\n " + + "return;\n }\n\n " + + "// d5: test code for @Inject methods cannot be generic\n " + + "@Inject\n " + + "public List injectGeneric(T arg) {\n " + + "// do nothing\n " + + "return new ArrayList();\n };\n\n}\n"; + codeActionParams = JakartaForJavaAssert.createCodeActionParams(uri, d3); + te1 = JakartaForJavaAssert.te(0, 0, 49, 0, textD3); + ca1 = JakartaForJavaAssert.ca(uri, "Remove the 'final' modifier from this method", d3, te1); + JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca1); + + String textD4 = "package io.openliberty.sample.jakarta.di;\n\n" + + "import jakarta.inject.Inject;\n" + + "import jakarta.enterprise.inject.Produces;\n\n" + + "import java.util.ArrayList;\nimport java.util.List;\n\n" + + "public abstract class GreetingServlet " + + "{\n\n /**\n *\n */\n " + + "private static final long serialVersionUID = 1L;\n\n " + + "// d1: test code for @Inject fields cannot be final\n " + + "@Inject\n " + + "private final Greeting greeting = new Greeting();\n\n " + + "@Produces\n " + + "public GreetingNoDefaultConstructor getInstance() {\n " + + "return new GreetingNoDefaultConstructor(\"Howdy\");\n }\n\n " + + "// d2\n @Inject\n " + + "public final void injectFinal() {\n " + + "// test code for @Inject methods cannot be final\n " + + "return;\n }\n\n " + + "// d3: test code for @Inject methods cannot be abstract\n " + + "@Inject\n " + + "public abstract void injectAbstract();\n\n " + + "// d4: test code for @Inject methods cannot be static\n " + + "@Inject\n public void injectStatic() {\n " + + "return;\n }\n\n " + + "// d5: test code for @Inject methods cannot be generic\n " + + "@Inject\n " + + "public List injectGeneric(T arg) {\n " + + "// do nothing\n return new ArrayList();\n };\n\n}\n"; + codeActionParams = JakartaForJavaAssert.createCodeActionParams(uri, d5); + te1 = JakartaForJavaAssert.te(0, 0, 49, 0, textD4); + ca1 = JakartaForJavaAssert.ca(uri, "Remove the 'static' modifier from this method", d5, te1); + JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca1); } } diff --git a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/persistence/JakartaPersistenceTest.java b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/persistence/JakartaPersistenceTest.java index f2fc112c3..42e0300fb 100644 --- a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/persistence/JakartaPersistenceTest.java +++ b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/persistence/JakartaPersistenceTest.java @@ -18,6 +18,7 @@ import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import io.openliberty.tools.intellij.lsp4jakarta.it.core.BaseJakartaTest; +import io.openliberty.tools.intellij.lsp4jakarta.lsp4ij.Messages; import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.utils.IPsiUtils; import io.openliberty.tools.intellij.lsp4mp4ij.psi.internal.core.ls.PsiUtilsLSImpl; import org.eclipse.lsp4j.CodeAction; @@ -26,7 +27,6 @@ import org.eclipse.lsp4j.TextEdit; import org.eclipse.lsp4jakarta.commons.JakartaDiagnosticsParams; import org.eclipse.lsp4jakarta.commons.JakartaJavaCodeActionParams; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -156,16 +156,16 @@ public void addEmptyConstructor() throws Exception { assertJavaDiagnostics(diagnosticsParams, utils, d); - if (CHECK_CODE_ACTIONS) { - // test quick fixes - JakartaJavaCodeActionParams codeActionParams1 = createCodeActionParams(uri, d); - TextEdit te1 = te(7, 4, 7, 4, "protected EntityMissingConstructor() {\n\t}\n\n\t"); - CodeAction ca1 = ca(uri, "Add a no-arg protected constructor to this class", d, te1); - TextEdit te2 = te(7, 4, 7, 4, "public EntityMissingConstructor() {\n\t}\n\n\t"); - CodeAction ca2 = ca(uri, "Add a no-arg public constructor to this class", d, te2); +// if (CHECK_CODE_ACTIONS) { + // test quick fixes + JakartaJavaCodeActionParams codeActionParams1 = createCodeActionParams(uri, d); + TextEdit te1 = te(0, 0, 9, 1, "package io.openliberty.sample.jakarta.persistence;\n\nimport jakarta.persistence.Entity;\n\n@Entity\npublic class EntityMissingConstructor {\n\n protected EntityMissingConstructor() {\n }\n\n private EntityMissingConstructor(int x) {\n }\n\n}"); + CodeAction ca1 = ca(uri, Messages.getMessage("AddNoArgProtectedConstructor"), d, te1); + TextEdit te2 = te(0, 0, 9, 1, "package io.openliberty.sample.jakarta.persistence;\n\nimport jakarta.persistence.Entity;\n\n@Entity\npublic class EntityMissingConstructor {\n\n public EntityMissingConstructor() {\n }\n\n private EntityMissingConstructor(int x) {\n }\n\n}"); + CodeAction ca2 = ca(uri, Messages.getMessage("AddNoArgPublicConstructor"), d, te2); - assertJavaCodeAction(codeActionParams1, utils, ca1, ca2); - } + assertJavaCodeAction(codeActionParams1, utils, ca1, ca2); +// } } @Test diff --git a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/servlet/JakartaServletTest.java b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/servlet/JakartaServletTest.java index 688fa6b62..9a2e1989a 100644 --- a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/servlet/JakartaServletTest.java +++ b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/servlet/JakartaServletTest.java @@ -1,15 +1,15 @@ /******************************************************************************* -* Copyright (c) 2021, 2023 IBM Corporation and others. -* -* This program and the accompanying materials are made available under the -* terms of the Eclipse Public License v. 2.0 which is available at -* http://www.eclipse.org/legal/epl-2.0. -* -* SPDX-License-Identifier: EPL-2.0 -* -* Contributors: -* IBM Corporation - initial API and implementation -*******************************************************************************/ + * Copyright (c) 2021, 2023 IBM Corporation and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ package io.openliberty.tools.intellij.lsp4jakarta.it.servlet; @@ -57,13 +57,19 @@ public void ExtendWebServlet() throws Exception { JakartaForJavaAssert.assertJavaDiagnostics(diagnosticsParams, utils, d); - if (CHECK_CODE_ACTIONS) { - // test associated quick-fix code action - JakartaJavaCodeActionParams codeActionParams = JakartaForJavaAssert.createCodeActionParams(uri, d); - TextEdit te = JakartaForJavaAssert.te(5, 34, 5, 34, " extends HttpServlet"); - CodeAction ca = JakartaForJavaAssert.ca(uri, "Let 'DontExtendHttpServlet' extend 'HttpServlet'", d, te); - JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca); - } + //TODO: this condition will be enabled when all quickfixes are refactored. + // if (CHECK_CODE_ACTIONS) { + // test associated quick-fix code action + JakartaJavaCodeActionParams codeActionParams = JakartaForJavaAssert.createCodeActionParams(uri, d); + String newText = "package io.openliberty.sample.jakarta.servlet;\n\n" + + "import jakarta.servlet.annotation.WebServlet;\nimport jakarta.servlet.http.HttpServlet;\n\n" + + "@WebServlet(name = \"demoServlet\", urlPatterns = {\"/demo\"})\n" + + "public class DontExtendHttpServlet extends HttpServlet {\n\n}"; + + TextEdit te = JakartaForJavaAssert.te(0, 0, 7, 1, newText); + CodeAction ca = JakartaForJavaAssert.ca(uri, "Let 'DontExtendHttpServlet' extend 'HttpServlet'", d, te); + JakartaForJavaAssert.assertJavaCodeAction(codeActionParams, utils, ca); + // } } @Test diff --git a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/websocket/JakartaWebSocketTest.java b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/websocket/JakartaWebSocketTest.java index 56b410a0e..c82baf304 100644 --- a/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/websocket/JakartaWebSocketTest.java +++ b/src/test/java/io/openliberty/tools/intellij/lsp4jakarta/it/websocket/JakartaWebSocketTest.java @@ -36,6 +36,8 @@ import java.io.File; import java.util.Arrays; +import static io.openliberty.tools.intellij.lsp4jakarta.it.core.JakartaForJavaAssert.*; + @RunWith(JUnit4.class) public class JakartaWebSocketTest extends BaseJakartaTest { @@ -56,30 +58,40 @@ public void addPathParamsAnnotation() throws Exception { "Parameters of type String, any Java primitive type, or boxed version thereof must be annotated with @PathParams.", DiagnosticSeverity.Error, "jakarta-websocket", "AddPathParamsAnnotation" ); - + // OnClose PathParams Annotation check Diagnostic d2 = JakartaForJavaAssert.d(24, 49, 67, "Parameters of type String, any Java primitive type, or boxed version thereof must be annotated with @PathParams.", DiagnosticSeverity.Error, "jakarta-websocket", "AddPathParamsAnnotation" ); - + Diagnostic d3 = JakartaForJavaAssert.d(24, 76, 94, "Parameters of type String, any Java primitive type, or boxed version thereof must be annotated with @PathParams.", DiagnosticSeverity.Error, "jakarta-websocket", "AddPathParamsAnnotation" ); - JakartaForJavaAssert.assertJavaDiagnostics(diagnosticsParams, utils, d1, d2, d3); - if (CHECK_CODE_ACTIONS) { - // Expected code actions - JakartaJavaCodeActionParams codeActionsParams = JakartaForJavaAssert.createCodeActionParams(uri, d1); - String newText = "\nimport jakarta.websocket.server.PathParam;\nimport jakarta.websocket.server.ServerEndpoint;\nimport jakarta.websocket.Session;\n\n" - + "/**\n * Expected Diagnostics are related to validating that the parameters have the \n * valid annotation @PathParam (code: AddPathParamsAnnotation)\n * See issue #247 (onOpen) and #248 (onClose)\n */\n" - + "@ServerEndpoint(value = \"/infos\")\npublic class AnnotationTest {\n // @PathParam missing annotation for \"String missingAnnotation\"\n @OnOpen\n public void OnOpen(Session session, @PathParam(value = \"\") "; - TextEdit te = JakartaForJavaAssert.te(5, 32, 18, 40, newText); - CodeAction ca = JakartaForJavaAssert.ca(uri, "Insert @jakarta.websocket.server.PathParam", d1, te); - JakartaForJavaAssert.assertJavaCodeAction(codeActionsParams, utils, ca); - } + //TODO: uncomment this if condition, once refactoring is done for all the quick fixes. +// if (CHECK_CODE_ACTIONS) { + // Expected code actions + JakartaJavaCodeActionParams codeActionsParams = createCodeActionParams(uri, d1); + String newText = "package io.openliberty.sample.jakarta.websocket;\n\nimport java.io.IOException;" + + "\n\nimport jakarta.websocket.OnClose;\nimport jakarta.websocket.OnOpen;\n" + + "import jakarta.websocket.server.PathParam;import jakarta.websocket.server.ServerEndpoint;\n" + + "import jakarta.websocket.Session;\n\n/**\n * Expected Diagnostics are related to validating that the " + + "parameters have the \n * valid annotation @PathParam (code: AddPathParamsAnnotation)\n * " + + "See issue #247 (onOpen) and #248 (onClose)\n */\n@ServerEndpoint(value = \"/infos\")\n" + + "public class AnnotationTest {\n // @PathParam missing annotation for \"String missingAnnotation\"\n" + + " @OnOpen\n public void OnOpen(Session session, @PathParam(\"\") String missingAnnotation) " + + "throws IOException {\n System.out.println(\"Websocket opened: \" + session.getId().toString());" + + "\n }\n \n // Used to check that the expected diagnostic handle more than one case\n " + + "@OnClose\n public void OnClose(Session session, Integer missingAnnotation1, " + + "String missingAnnotation2) {\n System.out.println(\"Websocket opened: \" + " + + "session.getId().toString());\n }\n}\n"; + TextEdit te = te(0, 0, 28, 0, newText); + CodeAction ca = ca(uri, "Insert @jakarta.websocket.server.PathParam", d1, te); + JakartaForJavaAssert.assertJavaCodeAction(codeActionsParams, utils, ca); +// } } @Test diff --git a/src/test/resources/ci/scripts/run.sh b/src/test/resources/ci/scripts/run.sh index 149ff20ab..1018a51ac 100755 --- a/src/test/resources/ci/scripts/run.sh +++ b/src/test/resources/ci/scripts/run.sh @@ -35,9 +35,9 @@ prefetchDependencies() { # Run through dev mode server install/create and feature installation for the Maven app. cd "src/test/resources/projects/maven/singleModMavenMP" - ./mvnw liberty:install-server + ./mvnw liberty:install-server -ntp ./mvnw liberty:create - ./mvnw liberty:install-feature + ./mvnw liberty:install-feature -ntp # Run through dev mode server install/create and feature installation for the Gradle app. cd "$workingDir" diff --git a/src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/PostConstructAnnotation.java b/src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/PostConstructAnnotation.java index 52b1166c8..64c7b3ba2 100644 --- a/src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/PostConstructAnnotation.java +++ b/src/test/resources/projects/maven/jakarta-sample/src/main/java/io/openliberty/sample/jakarta/annotations/PostConstructAnnotation.java @@ -29,4 +29,4 @@ public void throwTantrum() throws Exception { private String emailAddress; -} +} \ No newline at end of file