Skip to content

Commit

Permalink
Merge pull request #502 from mrglavas/jakarta-diagnostic-collector-poc
Browse files Browse the repository at this point in the history
Transform the Jakarta EE diagnostic collectors on to a common extension point shared with MicroProfile.
  • Loading branch information
mrglavas authored Oct 19, 2023
2 parents 586068e + c680d1f commit 2c799e2
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 138 deletions.
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
Expand All @@ -28,7 +32,7 @@
* Abstract class for collecting Java diagnostics.
*
*/
public class AbstractDiagnosticsCollector implements DiagnosticsCollector {
public abstract class AbstractDiagnosticsCollector implements DiagnosticsCollector, IJavaDiagnosticsParticipant {

/**
* Constructor
Expand Down Expand Up @@ -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<Diagnostic> collectDiagnostics(JavaDiagnosticsContext context) {
PsiFile typeRoot = context.getTypeRoot();
if (typeRoot instanceof PsiJavaFile) {
List<Diagnostic> diagnostics = new ArrayList<>();
collectDiagnostics((PsiJavaFile) typeRoot, diagnostics);
return diagnostics;
}
return Collections.emptyList();
}

/**
* Returns diagnostics for the given compilation unit.
*
Expand Down Expand Up @@ -301,4 +324,5 @@ protected static String getSimpleName(String fqName) {
protected static boolean isConstructorMethod(PsiMethod m) {
return m.isConstructor();
}

}
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -12,44 +12,30 @@

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.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.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;
Expand All @@ -65,25 +51,13 @@ public static PropertiesManagerForJakarta getInstance() {
return INSTANCE;
}

private List<DiagnosticsCollector> diagnosticsCollectors = new ArrayList<>();
private JakartaCodeActionHandler codeActionHandler = new JakartaCodeActionHandler();

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();
diagnosticsHandler = new DiagnosticsHandler("jakarta");
}

/**
Expand All @@ -94,40 +68,7 @@ private PropertiesManagerForJakarta() {
* @return diagnostics for the given uris list.
*/
public List<PublishDiagnosticsParams> diagnostics(JakartaDiagnosticsParams params, IPsiUtils utils) {
List<String> uris = params.getUris();
if (uris == null) {
return Collections.emptyList();
}
DocumentFormat documentFormat = params.getDocumentFormat();
List<PublishDiagnosticsParams> publishDiagnostics = new ArrayList<PublishDiagnosticsParams>();
for (String uri : uris) {
List<Diagnostic> 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<Diagnostic> diagnostics) {
PsiFile typeRoot = ApplicationManager.getApplication().runReadAction((Computable<PsiFile>) () -> resolveTypeRoot(uri, utils));
if (typeRoot == null) {
return;
}

try {
if (typeRoot instanceof PsiJavaFile) {
Module module = ApplicationManager.getApplication().runReadAction((ThrowableComputable<Module, IOException>) () -> 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);
}

/**
Expand Down Expand Up @@ -408,4 +349,11 @@ public List<CodeAction> getCodeAction(JakartaJavaCodeActionParams params, IPsiUt
return codeActionHandler.codeAction(params, utils);
});
}

private MicroProfileJavaDiagnosticsParams adapt(JakartaDiagnosticsParams params) {
MicroProfileJavaDiagnosticsParams mpParams = new MicroProfileJavaDiagnosticsParams(params.getUris(),
new MicroProfileJavaDiagnosticsSettings(Collections.emptyList()));
mpParams.setDocumentFormat(params.getDocumentFormat());
return mpParams;
}
}
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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;
Expand All @@ -27,15 +24,14 @@
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;
import io.openliberty.tools.intellij.lsp4mp4ij.psi.core.java.completion.IJavaCompletionParticipant;
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;
Expand All @@ -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;
Expand Down Expand Up @@ -86,8 +80,11 @@ public static PropertiesManagerForJava getInstance() {

private final CodeActionHandler codeActionHandler;

private final DiagnosticsHandler diagnosticsHandler;

private PropertiesManagerForJava() {
this.codeActionHandler = new CodeActionHandler();
this.diagnosticsHandler = new DiagnosticsHandler("mp");
}

/**
Expand Down Expand Up @@ -285,53 +282,7 @@ private void collectDefinition(String uri, PsiFile typeRoot, PsiElement hyperlin
* @return diagnostics for the given uris list.
*/
public List<PublishDiagnosticsParams> diagnostics(MicroProfileJavaDiagnosticsParams params, IPsiUtils utils) {
List<String> uris = params.getUris();
if (uris == null) {
return Collections.emptyList();
}
DocumentFormat documentFormat = params.getDocumentFormat();
List<PublishDiagnosticsParams> publishDiagnostics = new ArrayList<PublishDiagnosticsParams>();
for (String uri : uris) {
List<Diagnostic> 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<Diagnostic> diagnostics) {
PsiFile typeRoot = ApplicationManager.getApplication().runReadAction((Computable<PsiFile>) () -> resolveTypeRoot(uri, utils));
if (typeRoot == null) {
return;
}

try {
Module module = ApplicationManager.getApplication().runReadAction((ThrowableComputable<Module, IOException>) () -> utils.getModule(uri));
DumbService.getInstance(module.getProject()).runReadActionInSmartMode(() -> {
// Collect all adapted diagnostics participant
JavaDiagnosticsContext context = new JavaDiagnosticsContext(uri, typeRoot, utils, module, documentFormat, settings);
List<IJavaDiagnosticsParticipant> 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<Diagnostic> 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);
}

/**
Expand Down
Loading

0 comments on commit 2c799e2

Please sign in to comment.