Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workspace symbols for JAX-RS endpoints #313

Merged
merged 1 commit into from
Jan 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ You can build all projects at once by running the `buildAll.sh` script (`buildAl

## Features

#### General

When you open a MicroProfile project, lsp4mp provides:

- Symbols to help you navigate to JAX-RS REST endpoint methods, searchable using the naming convention: `@/api/endpointName: GET`

#### Properties files

In `microprofile-config.properties` files, you will benefit with:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,19 @@ Export-Package: io.quarkus.runtime.util,
org.eclipse.lsp4mp.jdt.internal.core.utils;x-friends:="org.eclipse.lsp4mp.jdt.test",
org.eclipse.lsp4mp.jdt.internal.faulttolerance;x-friends:="org.eclipse.lsp4mp.jdt.test",
org.eclipse.lsp4mp.jdt.internal.faulttolerance.java;x-friends:="org.eclipse.lsp4mp.jdt.test",
org.eclipse.lsp4mp.jdt.internal.reactivemessaging;x-friends:="org.eclipse.lsp4mp.jdt.test",
org.eclipse.lsp4mp.jdt.internal.reactivemessaging.java;x-friends:="org.eclipse.lsp4mp.jdt.test",
org.eclipse.lsp4mp.jdt.internal.health;x-friends:="org.eclipse.lsp4mp.jdt.test",
org.eclipse.lsp4mp.jdt.internal.health.java;x-friends:="org.eclipse.lsp4mp.jdt.test",
org.eclipse.lsp4mp.jdt.internal.jaxrs.java;x-friends:="org.eclipse.lsp4mp.jdt.test",
org.eclipse.lsp4mp.jdt.internal.metrics;x-friends:="org.eclipse.lsp4mp.jdt.test",
org.eclipse.lsp4mp.jdt.internal.metrics.java;x-friends:="org.eclipse.lsp4mp.jdt.test",
org.eclipse.lsp4mp.jdt.internal.reactivemessaging;x-friends:="org.eclipse.lsp4mp.jdt.test",
org.eclipse.lsp4mp.jdt.internal.reactivemessaging.java;x-friends:="org.eclipse.lsp4mp.jdt.test",
org.eclipse.lsp4mp.jdt.internal.restclient;x-friends:="org.eclipse.lsp4mp.jdt.test"
Bundle-ClassPath: .
Import-Package: com.google.gson,
Import-Package: com.google.common.graph,
com.google.gson,
com.google.gson.stream,
io.smallrye.common.constraint,
io.smallrye.common.expression,
io.smallrye.common.function,
io.smallrye.common.constraint,
org.jboss.logging,
com.google.common.graph
org.jboss.logging
3 changes: 3 additions & 0 deletions microprofile.jdt/org.eclipse.lsp4mp.jdt.core/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<command id="microprofile/java/definition"/>
<command id="microprofile/java/diagnostics"/>
<command id="microprofile/java/hover"/>
<command id="microprofile/java/workspaceSymbols"/>
</delegateCommandHandler>
</extension>

Expand Down Expand Up @@ -325,5 +326,7 @@
<extension point="org.eclipse.lsp4mp.jdt.core.javaFeatureParticipants">
<!-- Java URL codeLens for JAX-RS -->
<codeLens class="org.eclipse.lsp4mp.jdt.internal.jaxrs.java.JaxRsCodeLensParticipant" />
<workspaceSymbols
class="org.eclipse.lsp4mp.jdt.internal.jaxrs.java.JaxRsWorkspaceSymbolParticipant" />
</extension>
</plugin>
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<element ref="diagnostics" minOccurs="0" maxOccurs="unbounded"/>
<element ref="definition" minOccurs="0" maxOccurs="unbounded"/>
<element ref="hover" minOccurs="0" maxOccurs="unbounded"/>
<element ref="workspaceSymbols" minOccurs="0" maxOccurs="unbounded"/>
</choice>
</sequence>
<attribute name="point" type="string" use="required">
Expand Down Expand Up @@ -198,6 +199,26 @@
</complexType>
</element>

<element name="workspaceSymbols">
<annotation>
<documentation>
Java workspaceSymbols participant.
</documentation>
</annotation>
<complexType>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
Name of a class that implements IJavaWorkspaceSymbolParticipant
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.eclipse.lsp4mp.jdt.core.java.symbol.IJavaWorkspaceSymbolsParticipant"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>

<annotation>
<appinfo>
<meta.section type="since"/>
Expand Down Expand Up @@ -238,7 +259,4 @@
</documentation>
</annotation>




</schema>
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.ISourceRange;
Expand Down Expand Up @@ -52,6 +55,7 @@
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.PublishDiagnosticsParams;
import org.eclipse.lsp4j.jsonrpc.validation.NonNull;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4mp.commons.DocumentFormat;
import org.eclipse.lsp4mp.commons.JavaCursorContextKind;
import org.eclipse.lsp4mp.commons.JavaCursorContextResult;
Expand All @@ -72,13 +76,15 @@
import org.eclipse.lsp4mp.jdt.core.java.hover.JavaHoverContext;
import org.eclipse.lsp4mp.jdt.core.utils.ASTNodeUtils;
import org.eclipse.lsp4mp.jdt.core.utils.IJDTUtils;
import org.eclipse.lsp4mp.jdt.core.utils.JDTMicroProfileUtils;
import org.eclipse.lsp4mp.jdt.internal.core.java.JavaFeaturesRegistry;
import org.eclipse.lsp4mp.jdt.internal.core.java.codeaction.CodeActionHandler;
import org.eclipse.lsp4mp.jdt.internal.core.java.codelens.JavaCodeLensDefinition;
import org.eclipse.lsp4mp.jdt.internal.core.java.completion.JavaCompletionDefinition;
import org.eclipse.lsp4mp.jdt.internal.core.java.definition.JavaDefinitionDefinition;
import org.eclipse.lsp4mp.jdt.internal.core.java.diagnostics.JavaDiagnosticsDefinition;
import org.eclipse.lsp4mp.jdt.internal.core.java.hover.JavaHoverDefinition;
import org.eclipse.lsp4mp.jdt.internal.core.java.symbols.JavaWorkspaceSymbolsDefinition;

/**
* JDT MicroProfile manager for Java files.
Expand Down Expand Up @@ -585,6 +591,36 @@ private void collectHover(String uri, ITypeRoot typeRoot, IJavaElement hoverElem
definitions.forEach(definition -> definition.endHover(context, monitor));
}

/**
* Returns the workspace symbols for the given java project.
*
* @param projectUri the uri of the java project
* @param utils the JDT utils
* @param monitor the progress monitor
* @return the workspace symbols for the given java project
*/
public List<SymbolInformation> workspaceSymbols(String projectUri, IJDTUtils utils, IProgressMonitor monitor) {
List<SymbolInformation> symbols = new ArrayList<>();
Optional<IJavaProject> projectOpt = Stream.of(JDTMicroProfileUtils.getJavaProjects()) //
.filter(project -> projectUri.equals(JDTMicroProfileUtils.getProjectURI(project))) //
.findFirst();
if (projectOpt.isEmpty()) {
return symbols;
}
collectWorkspaceSymbols(projectOpt.get(), utils, symbols, monitor);
return symbols;
}

private void collectWorkspaceSymbols(IJavaProject project, IJDTUtils utils, List<SymbolInformation> symbols,
IProgressMonitor monitor) {
List<JavaWorkspaceSymbolsDefinition> definitions = JavaFeaturesRegistry.getInstance()
.getJavaWorkspaceSymbolsDefinitions();
if (definitions.isEmpty()) {
return;
}
definitions.forEach(definition -> definition.collectSymbols(project, utils, symbols, monitor));
}

/**
* Given the uri returns a {@link ITypeRoot}. May return null if it can not
* associate the uri with a Java file or class file.
Expand Down Expand Up @@ -755,4 +791,4 @@ private static int offsetOfFirstNonAnnotationModifier(BodyDeclaration node) {
}
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. 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, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.lsp4mp.jdt.core.java.symbols;

import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4mp.jdt.core.utils.IJDTUtils;

/**
* Represents an object that can collect workspace symbols for java projects.
*/
public interface IJavaWorkspaceSymbolsParticipant {

/**
* Fill in <code>symbols</code> with workspace symbols of the given project.
*
* @param project the project to collect workspace symbols from
* @param utils the JDT utils
* @param symbols the list of symbols to add to
* @param monitor the progress monitor
*/
void collectSymbols(IJavaProject project, IJDTUtils utils, List<SymbolInformation> symbols,
IProgressMonitor monitor);

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package org.eclipse.lsp4mp.jdt.core.jaxrs;

import static org.eclipse.lsp4mp.jdt.core.jaxrs.JaxRsUtils.getJaxRsApplicationPathValue;
import static org.eclipse.lsp4mp.jdt.internal.jaxrs.JaxRsConstants.JAKARTA_WS_RS_APPLICATIONPATH_ANNOTATION;
import static org.eclipse.lsp4mp.jdt.internal.jaxrs.JaxRsConstants.JAVAX_WS_RS_APPLICATIONPATH_ANNOTATION;

import java.util.concurrent.atomic.AtomicReference;
Expand Down Expand Up @@ -45,6 +46,12 @@ public class JaxRsContext {

private static final String CONTEXT_KEY = JaxRsContext.class.getName();

private static final SearchPattern SEARCH_PATTERN = SearchPattern.createOrPattern(
SearchPattern.createPattern(JAVAX_WS_RS_APPLICATIONPATH_ANNOTATION, IJavaSearchConstants.ANNOTATION_TYPE,
IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE, SearchPattern.R_EXACT_MATCH),
SearchPattern.createPattern(JAKARTA_WS_RS_APPLICATIONPATH_ANNOTATION, IJavaSearchConstants.ANNOTATION_TYPE,
IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE, SearchPattern.R_EXACT_MATCH));

private int serverPort;

// The quarkus.http.root-path property in application.properties
Expand All @@ -53,11 +60,11 @@ public class JaxRsContext {
// The value of the @ApplicationPath annotation
private String applicationPath;

private final JavaCodeLensContext javaCodeLensContext;
private final IJavaProject javaProject;

public JaxRsContext(JavaCodeLensContext javaCodeLensContext) {
public JaxRsContext(IJavaProject javaProject) {
setServerPort(DEFAULT_PORT);
this.javaCodeLensContext = javaCodeLensContext;
this.javaProject = javaProject;
}

public int getServerPort() {
Expand Down Expand Up @@ -95,9 +102,13 @@ public void setRootPath(String rootPath) {
*/
public String getApplicationPath(IProgressMonitor monitor) throws CoreException {
if (applicationPath == null) {
IType applicationPathType = JDTTypeUtils.findType(javaCodeLensContext.getJavaProject(),
IType applicationPathType = JDTTypeUtils.findType(javaProject,
JAVAX_WS_RS_APPLICATIONPATH_ANNOTATION);
applicationPath = findApplicationPath(applicationPathType, javaCodeLensContext, monitor);
if (applicationPathType == null) {
applicationPathType = JDTTypeUtils.findType(javaProject,
JAKARTA_WS_RS_APPLICATIONPATH_ANNOTATION);
}
applicationPath = findApplicationPath(javaProject, monitor);
}
return applicationPath;
}
Expand All @@ -114,7 +125,7 @@ public void setApplicationPath(String applicationPath) {
public static JaxRsContext getJaxRsContext(JavaCodeLensContext context) {
JaxRsContext jaxRsContext = (JaxRsContext) context.get(CONTEXT_KEY);
if (jaxRsContext == null) {
jaxRsContext = new JaxRsContext(context);
jaxRsContext = new JaxRsContext(context.getJavaProject());
context.put(CONTEXT_KEY, jaxRsContext);
}
return jaxRsContext;
Expand Down Expand Up @@ -150,16 +161,13 @@ public String getLocalBaseURL() {
* @return the value of the @ApplicationPath annotation, or null if not found
* @throws CoreException
*/
private static String findApplicationPath(IType annotationType, JavaCodeLensContext context,
private static String findApplicationPath(IJavaProject javaProject,
IProgressMonitor monitor) throws CoreException {
AtomicReference<String> applicationPathRef = new AtomicReference<String>();
SearchPattern pattern = SearchPattern.createPattern(JAVAX_WS_RS_APPLICATIONPATH_ANNOTATION,
IJavaSearchConstants.ANNOTATION_TYPE, IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE,
SearchPattern.R_EXACT_MATCH);
SearchEngine engine = new SearchEngine();
engine.search(pattern, new SearchParticipant[] {
engine.search(SEARCH_PATTERN, new SearchParticipant[] {
SearchEngine.getDefaultSearchParticipant()
}, createSearchScope(annotationType.getJavaProject()), new SearchRequestor() {
}, createSearchScope(javaProject), new SearchRequestor() {

@Override
public void acceptSearchMatch(SearchMatch match) throws CoreException {
Expand All @@ -170,8 +178,9 @@ public void acceptSearchMatch(SearchMatch match) throws CoreException {
}

private void collectApplicationPath(IType type) throws CoreException {
if (AnnotationUtils.hasAnnotation(type, JAVAX_WS_RS_APPLICATIONPATH_ANNOTATION)) {
applicationPathRef.set(getJaxRsApplicationPathValue(type));
String applicationPathValue = getJaxRsApplicationPathValue(type);
if (applicationPathValue != null) {
applicationPathRef.set(applicationPathValue);
}
}
}, monitor);
Expand Down
Loading