Skip to content

Commit 869ead4

Browse files
committed
feat: Workspace symbols for JAX-RS endpoints
Fixes #1363 Signed-off-by: azerr <azerr@redhat.com>
1 parent f55035d commit 869ead4

File tree

20 files changed

+506
-95
lines changed

20 files changed

+506
-95
lines changed

projects/lsp4mp/projects/maven/config-quickstart/src/main/java/org/acme/config/GreetingResource.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.Optional;
44

55
import javax.ws.rs.GET;
6+
import javax.ws.rs.PATCH;
67
import javax.ws.rs.Path;
78
import javax.ws.rs.Produces;
89
import javax.ws.rs.core.MediaType;
@@ -40,4 +41,9 @@ public String hello2() {
4041
public String hello3() {
4142
return message + " 4 " + name.orElse("world") + suffix;
4243
}
44+
45+
@PATCH
46+
@Path("hello5")
47+
public String hello5() {
48+
}
4349
}

src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/PropertiesManagerForJava.java

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.intellij.openapi.application.ApplicationManager;
1515
import com.intellij.openapi.editor.Document;
1616
import com.intellij.openapi.module.Module;
17+
import com.intellij.openapi.module.ModuleManager;
1718
import com.intellij.openapi.progress.ProgressIndicator;
1819
import com.intellij.openapi.project.DumbService;
1920
import com.intellij.openapi.util.Computable;
@@ -27,21 +28,15 @@
2728
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.java.completion.JavaCompletionContext;
2829
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.java.definition.IJavaDefinitionParticipant;
2930
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.java.definition.JavaDefinitionContext;
31+
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.java.symbols.IJavaWorkspaceSymbolsParticipant;
3032
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.utils.IPsiUtils;
3133
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.java.diagnostics.IJavaDiagnosticsParticipant;
3234
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.java.diagnostics.JavaDiagnosticsContext;
3335
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.java.hover.IJavaHoverParticipant;
3436
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.java.hover.JavaHoverContext;
3537
import com.redhat.devtools.intellij.lsp4mp4ij.psi.internal.core.java.codeaction.CodeActionHandler;
36-
import org.eclipse.lsp4j.CodeAction;
37-
import org.eclipse.lsp4j.CodeLens;
38-
import org.eclipse.lsp4j.CompletionItem;
39-
import org.eclipse.lsp4j.CompletionList;
38+
import org.eclipse.lsp4j.*;
4039
import org.eclipse.lsp4mp.commons.*;
41-
import org.eclipse.lsp4j.Diagnostic;
42-
import org.eclipse.lsp4j.Hover;
43-
import org.eclipse.lsp4j.Position;
44-
import org.eclipse.lsp4j.PublishDiagnosticsParams;
4540
import org.jetbrains.annotations.NotNull;
4641
import org.jetbrains.annotations.Nullable;
4742
import org.slf4j.Logger;
@@ -637,4 +632,43 @@ public CodeAction resolveCodeAction(CodeAction unresolved, IPsiUtils utils) {
637632
return codeActionHandler.resolveCodeAction(unresolved, utils);
638633
}
639634

635+
/**
636+
* Returns the workspace symbols for the given java project.
637+
*
638+
* @param projectUri the uri of the java project
639+
* @param utils the JDT utils
640+
* @param monitor the progress monitor
641+
* @return the workspace symbols for the given java project
642+
*/
643+
public List<SymbolInformation> workspaceSymbols(String projectUri, IPsiUtils utils, ProgressIndicator monitor) {
644+
List<SymbolInformation> symbols = new ArrayList<>();
645+
Module module = getModule(projectUri, utils);
646+
if (module != null) {
647+
collectWorkspaceSymbols(module, utils, symbols, monitor);
648+
}
649+
return symbols;
650+
}
651+
652+
private static @Nullable Module getModule(String uri, IPsiUtils utils) {
653+
Module[] modules = ModuleManager.getInstance(utils.getProject()).getModules();
654+
for (Module module : modules) {
655+
if (uri.equals(module.getName())) {
656+
return module;
657+
}
658+
}
659+
return null;
660+
}
661+
662+
private void collectWorkspaceSymbols(Module project, IPsiUtils utils, List<SymbolInformation> symbols,
663+
ProgressIndicator monitor) {
664+
if (monitor.isCanceled()) {
665+
return;
666+
}
667+
668+
List<IJavaWorkspaceSymbolsParticipant> definitions = IJavaWorkspaceSymbolsParticipant.EP_NAME.getExtensionList();
669+
if (definitions.isEmpty()) {
670+
return;
671+
}
672+
definitions.forEach(definition -> definition.collectSymbols(project, utils, symbols, monitor));
673+
}
640674
}

src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/java/codelens/IJavaCodeLensParticipant.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
*
2727
*/
2828
public interface IJavaCodeLensParticipant {
29-
public static final ExtensionPointName<IJavaCodeLensParticipant> EP_NAME = ExtensionPointName.create("com.redhat.devtools.intellij.quarkus.javaCodeLensParticipant");
29+
30+
ExtensionPointName<IJavaCodeLensParticipant> EP_NAME = ExtensionPointName.create("com.redhat.devtools.intellij.quarkus.javaCodeLensParticipant");
3031

3132

3233
/**

src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/java/completion/IJavaCompletionParticipant.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
* @author datho7561
2525
*/
2626
public interface IJavaCompletionParticipant {
27-
public static final ExtensionPointName<IJavaCompletionParticipant> EP_NAME = ExtensionPointName.create("com.redhat.devtools.intellij.quarkus.javaCompletionParticipant");
27+
28+
ExtensionPointName<IJavaCompletionParticipant> EP_NAME = ExtensionPointName.create("com.redhat.devtools.intellij.quarkus.javaCompletionParticipant");
2829

2930
/**
3031
* Returns true if this completion feature should be active in this context, and false otherwise

src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/java/definition/IJavaDefinitionParticipant.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
*
2626
*/
2727
public interface IJavaDefinitionParticipant {
28-
public static final ExtensionPointName<IJavaDefinitionParticipant> EP_NAME = ExtensionPointName.create("com.redhat.devtools.intellij.quarkus.javaDefinitionParticipant");
28+
29+
ExtensionPointName<IJavaDefinitionParticipant> EP_NAME = ExtensionPointName.create("com.redhat.devtools.intellij.quarkus.javaDefinitionParticipant");
2930

3031
/**
3132
* Returns true if definition must be collected for the given context and false

src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/java/diagnostics/IJavaDiagnosticsParticipant.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
*/
2626
public interface IJavaDiagnosticsParticipant {
2727

28-
public static final ExtensionPointName<IJavaDiagnosticsParticipant> EP_NAME = ExtensionPointName.create("com.redhat.devtools.intellij.quarkus.javaDiagnosticsParticipant");
28+
ExtensionPointName<IJavaDiagnosticsParticipant> EP_NAME = ExtensionPointName.create("com.redhat.devtools.intellij.quarkus.javaDiagnosticsParticipant");
2929

3030
/**
3131
* Returns true if diagnostics must be collected for the given context and false

src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/java/hover/IJavaHoverParticipant.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
*/
2424
public interface IJavaHoverParticipant {
2525

26-
public static final ExtensionPointName<IJavaHoverParticipant> EP_NAME = ExtensionPointName.create("com.redhat.devtools.intellij.quarkus.javaHoverParticipant");
26+
ExtensionPointName<IJavaHoverParticipant> EP_NAME = ExtensionPointName.create("com.redhat.devtools.intellij.quarkus.javaHoverParticipant");
2727

2828
/**
2929
* Returns true if hover must be collected for the given context and false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 Red Hat Inc. and others.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7+
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
8+
*
9+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10+
*
11+
* Contributors:
12+
* Red Hat Inc. - initial API and implementation
13+
*******************************************************************************/
14+
package com.redhat.devtools.intellij.lsp4mp4ij.psi.core.java.symbols;
15+
16+
import com.intellij.openapi.extensions.ExtensionPointName;
17+
import com.intellij.openapi.module.Module;
18+
import com.intellij.openapi.progress.ProgressIndicator;
19+
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.utils.IPsiUtils;
20+
import org.eclipse.lsp4j.SymbolInformation;
21+
22+
import java.util.List;
23+
24+
/**
25+
* Represents an object that can collect workspace symbols for java projects.
26+
*/
27+
public interface IJavaWorkspaceSymbolsParticipant {
28+
29+
ExtensionPointName<IJavaWorkspaceSymbolsParticipant> EP_NAME = ExtensionPointName.create("com.redhat.devtools.intellij.quarkus.javaWorkspaceSymbolsParticipant");
30+
31+
/**
32+
* Fill in <code>symbols</code> with workspace symbols of the given project.
33+
*
34+
* @param project the project to collect workspace symbols from
35+
* @param utils the JDT utils
36+
* @param symbols the list of symbols to add to
37+
* @param monitor the progress monitor
38+
*/
39+
void collectSymbols(Module project, IPsiUtils utils, List<SymbolInformation> symbols,
40+
ProgressIndicator monitor);
41+
42+
}

src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/jaxrs/IJaxRsInfoProvider.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,17 @@ public interface IJaxRsInfoProvider {
4343
* Returns a non-null set of all the classes in the given project that this provider can provide JAX-RS method information for.
4444
*
4545
* @param javaProject the project to check for JAX-RS method information
46+
* @param utils the Psi utilities.
4647
* @param monitor the progress monitor
4748
* @return a non-null set of all the classes in the given project that this provider can provide JAX-RS method information for
4849
*/
49-
@NotNull Set<PsiClass> getAllJaxRsClasses(@NotNull Module javaProject, @NotNull ProgressIndicator monitor);
50+
@NotNull Set<PsiClass> getAllJaxRsClasses(@NotNull Module javaProject, @NotNull IPsiUtils utils, @NotNull ProgressIndicator monitor);
5051

5152
/**
5253
* Returns a list of all the JAX-RS methods in the given type.
5354
*
5455
* @param type the type to check for JAX-RS methods
56+
* @param jaxrsContext the JAX-RS context.
5557
* @param monitor the progress monitor
5658
* @return a list of all the JAX-RS methods in the given type
5759
*/

src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/internal/jaxrs/java/DefaultJaxRsInfoProvider.java

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,20 @@
1818
import com.intellij.openapi.progress.ProgressIndicator;
1919
import com.intellij.openapi.project.IndexNotReadyException;
2020
import com.intellij.psi.*;
21+
import com.intellij.psi.search.SearchScope;
22+
import com.intellij.psi.search.searches.AnnotatedElementsSearch;
2123
import com.intellij.psi.util.PsiTreeUtil;
24+
import com.intellij.util.MergeQuery;
25+
import com.intellij.util.Query;
2226
import com.redhat.devtools.lsp4ij.LSPIJUtils;
2327
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.jaxrs.*;
2428
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.utils.IPsiUtils;
2529
import com.redhat.devtools.intellij.lsp4mp4ij.psi.core.utils.PsiTypeUtils;
30+
import org.jetbrains.annotations.NotNull;
2631

27-
import java.util.ArrayList;
28-
import java.util.Collection;
29-
import java.util.Collections;
30-
import java.util.List;
31-
import java.util.Set;
32+
import java.util.*;
3233
import java.util.concurrent.CancellationException;
34+
import java.util.function.Consumer;
3335
import java.util.logging.Level;
3436
import java.util.logging.Logger;
3537

@@ -49,14 +51,58 @@ public class DefaultJaxRsInfoProvider implements IJaxRsInfoProvider {
4951
private static final Logger LOGGER = Logger.getLogger(DefaultJaxRsInfoProvider.class.getName());
5052

5153
@Override
52-
public boolean canProvideJaxRsMethodInfoForClass(PsiFile typeRoot, Module javaProject, ProgressIndicator monitor) {
54+
public boolean canProvideJaxRsMethodInfoForClass(@NotNull PsiFile typeRoot, Module javaProject, ProgressIndicator monitor) {
5355
return PsiTypeUtils.findType(javaProject, JAVAX_WS_RS_PATH_ANNOTATION) != null
5456
|| PsiTypeUtils.findType(javaProject, JAKARTA_WS_RS_PATH_ANNOTATION) != null;
5557
}
5658

5759
@Override
58-
public Set<PsiClass> getAllJaxRsClasses(Module javaProject, ProgressIndicator monitor) {
59-
// TODO: implement when LSP4IJ will support workspace symbols
60+
public Set<PsiClass> getAllJaxRsClasses(Module javaProject, IPsiUtils utils, ProgressIndicator monitor) {
61+
if (monitor.isCanceled()) {
62+
return Collections.emptySet();
63+
}
64+
65+
try {
66+
SearchScope scope = javaProject.getModuleScope(false);
67+
68+
Query<PsiModifierListOwner> query = null;
69+
for (var httpAnnotation : JaxRsConstants.HTTP_METHOD_ANNOTATIONS) {
70+
PsiClass annotationClass = utils.findClass(javaProject, httpAnnotation);
71+
if (annotationClass != null) {
72+
Query<PsiModifierListOwner> annotationQuery = AnnotatedElementsSearch.searchElements(annotationClass, scope, PsiModifierListOwner.class);
73+
if (query == null) {
74+
query = annotationQuery;
75+
} else {
76+
query = new MergeQuery<>(query, annotationQuery);
77+
}
78+
}
79+
}
80+
if (query == null) {
81+
return Collections.emptySet();
82+
}
83+
84+
Set<PsiClass> jaxRsClasses = new HashSet<>();
85+
query.forEach((Consumer<? super PsiModifierListOwner>) item -> {
86+
if (item instanceof PsiMember) {
87+
PsiClass cl = ((PsiMember) item).getContainingClass();
88+
if (cl != null) {
89+
jaxRsClasses.add(cl);
90+
}
91+
}
92+
});
93+
if (monitor.isCanceled()) {
94+
return Collections.emptySet();
95+
}
96+
return jaxRsClasses;
97+
} catch (ProcessCanceledException e) {
98+
//Since 2024.2 ProcessCanceledException extends CancellationException so we can't use multicatch to keep backward compatibility
99+
//TODO delete block when minimum required version is 2024.2
100+
throw e;
101+
} catch (IndexNotReadyException | CancellationException e) {
102+
throw e;
103+
} catch (Exception e) {
104+
LOGGER.log(Level.SEVERE, "While collecting JAX-RS method information for project " + javaProject.getName(), e);
105+
}
60106
return Collections.emptySet();
61107
}
62108

src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/internal/jaxrs/java/JaxRsInfoProviderRegistry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public static JaxRsInfoProviderRegistry getInstance() {
6262
return null;
6363
}
6464

65-
private List<IJaxRsInfoProvider> getProviders() {
65+
public List<IJaxRsInfoProvider> getProviders() {
6666
if (!initialized) {
6767
providers = loadProviders();
6868
return providers;

0 commit comments

Comments
 (0)