From bff2b303f3e6bae05c2ca9d0f592f38ccb9e6985 Mon Sep 17 00:00:00 2001 From: Rome Li Date: Wed, 25 Sep 2019 21:27:23 +0800 Subject: [PATCH] Support Diagnostic Tag (#1161) Signed-off-by: Rome Li --- .../internal/handlers/DiagnosticsHandler.java | 58 ++++++++++++++++++- .../internal/handlers/JDTLanguageServer.java | 3 +- .../handlers/WorkspaceDiagnosticsHandler.java | 52 ++++++++++++----- .../preferences/ClientPreferences.java | 13 +++++ .../correction/AbstractQuickFixTest.java | 2 +- .../handlers/DiagnosticHandlerTest.java | 27 ++++++++- .../DocumentLifeCycleHandlerTest.java | 2 +- .../WorkspaceDiagnosticsHandlerTest.java | 3 +- 8 files changed, 138 insertions(+), 22 deletions(-) diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DiagnosticsHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DiagnosticsHandler.java index 475867b530..1fda2dd650 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DiagnosticsHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DiagnosticsHandler.java @@ -13,6 +13,7 @@ import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -28,6 +29,7 @@ import org.eclipse.jdt.ls.core.internal.ResourceUtils; import org.eclipse.lsp4j.Diagnostic; import org.eclipse.lsp4j.DiagnosticSeverity; +import org.eclipse.lsp4j.DiagnosticTag; import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.PublishDiagnosticsParams; import org.eclipse.lsp4j.Range; @@ -116,7 +118,8 @@ public void beginReporting() { @Override public void endReporting() { JavaLanguageServerPlugin.logInfo(problems.size() + " problems reported for " + this.uri.substring(this.uri.lastIndexOf('/'))); - PublishDiagnosticsParams $ = new PublishDiagnosticsParams(ResourceUtils.toClientUri(uri), toDiagnosticsArray(this.cu, problems)); + boolean isDiagnosticTagSupported = JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().isDiagnosticTagSupported(); + PublishDiagnosticsParams $ = new PublishDiagnosticsParams(ResourceUtils.toClientUri(uri), toDiagnosticsArray(this.cu, problems, isDiagnosticTagSupported)); this.connection.publishDiagnostics($); } @@ -125,7 +128,12 @@ public boolean isActive() { return true; } + @Deprecated public static List toDiagnosticsArray(IOpenable openable, List problems) { + return toDiagnosticsArray(openable, problems, false); + } + + public static List toDiagnosticsArray(IOpenable openable, List problems, boolean isDiagnosticTagSupported) { List array = new ArrayList<>(problems.size()); for (IProblem problem : problems) { Diagnostic diag = new Diagnostic(); @@ -134,11 +142,59 @@ public static List toDiagnosticsArray(IOpenable openable, List getDiagnosticTag(int id) { + switch (id) { + case IProblem.UsingDeprecatedType: + case IProblem.UsingDeprecatedField: + case IProblem.UsingDeprecatedMethod: + case IProblem.UsingDeprecatedConstructor: + case IProblem.OverridingDeprecatedMethod: + case IProblem.JavadocUsingDeprecatedField: + case IProblem.JavadocUsingDeprecatedConstructor: + case IProblem.JavadocUsingDeprecatedMethod: + case IProblem.JavadocUsingDeprecatedType: + case IProblem.UsingTerminallyDeprecatedType: + case IProblem.UsingTerminallyDeprecatedMethod: + case IProblem.UsingTerminallyDeprecatedConstructor: + case IProblem.UsingTerminallyDeprecatedField: + case IProblem.OverridingTerminallyDeprecatedMethod: + case IProblem.UsingDeprecatedSinceVersionType: + case IProblem.UsingDeprecatedSinceVersionMethod: + case IProblem.UsingDeprecatedSinceVersionConstructor: + case IProblem.UsingDeprecatedSinceVersionField: + case IProblem.OverridingDeprecatedSinceVersionMethod: + case IProblem.UsingTerminallyDeprecatedSinceVersionType: + case IProblem.UsingTerminallyDeprecatedSinceVersionMethod: + case IProblem.UsingTerminallyDeprecatedSinceVersionConstructor: + case IProblem.UsingTerminallyDeprecatedSinceVersionField: + case IProblem.OverridingTerminallyDeprecatedSinceVersionMethod: + case IProblem.UsingDeprecatedPackage: + case IProblem.UsingDeprecatedSinceVersionPackage: + case IProblem.UsingTerminallyDeprecatedPackage: + case IProblem.UsingTerminallyDeprecatedSinceVersionPackage: + case IProblem.UsingDeprecatedModule: + case IProblem.UsingDeprecatedSinceVersionModule: + case IProblem.UsingTerminallyDeprecatedModule: + case IProblem.UsingTerminallyDeprecatedSinceVersionModule: + return Arrays.asList(DiagnosticTag.Deprecated); + case IProblem.UnnecessaryCast: + case IProblem.UnnecessaryInstanceof: + case IProblem.UnnecessaryElse: + case IProblem.UnnecessaryNLSTag: + return Arrays.asList(DiagnosticTag.Unnecessary); + } + + return null; + } + private static DiagnosticSeverity convertSeverity(IProblem problem) { if(problem.isError()) { return DiagnosticSeverity.Error; diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java index 769f3aa5a6..ce23796209 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java @@ -254,6 +254,7 @@ public void initialized(InitializedParams params) { // we do not have the user setting initialized yet at this point but we should // still call to enable defaults in case client does not support configuration changes syncCapabilitiesToSettings(); + Job initializeWorkspace = new Job("Initialize workspace") { @Override @@ -261,7 +262,7 @@ public IStatus run(IProgressMonitor monitor) { try { JobHelpers.waitForBuildJobs(60 * 60 * 1000); // 1 hour logInfo(">> build jobs finished"); - workspaceDiagnosticsHandler = new WorkspaceDiagnosticsHandler(JDTLanguageServer.this.client, pm); + workspaceDiagnosticsHandler = new WorkspaceDiagnosticsHandler(JDTLanguageServer.this.client, pm, preferenceManager.getClientPreferences()); workspaceDiagnosticsHandler.publishDiagnostics(monitor); workspaceDiagnosticsHandler.addResourceChangeListener(); pm.registerWatchers(); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandler.java index e6085aaa76..3663ab2d6a 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandler.java @@ -42,6 +42,7 @@ import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; import org.eclipse.jdt.ls.core.internal.ResourceUtils; import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager; +import org.eclipse.jdt.ls.core.internal.preferences.ClientPreferences; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.lsp4j.Diagnostic; @@ -64,10 +65,17 @@ public final class WorkspaceDiagnosticsHandler implements IResourceChangeListene public static final String PROJECT_CONFIGURATION_IS_NOT_UP_TO_DATE_WITH_POM_XML = "Project configuration is not up-to-date with pom.xml, requires an update."; private final JavaClientConnection connection; private final ProjectsManager projectsManager; + private final boolean isDiagnosticTagSupported; + @Deprecated public WorkspaceDiagnosticsHandler(JavaClientConnection connection, ProjectsManager projectsManager) { + this(connection, projectsManager, null); + } + + public WorkspaceDiagnosticsHandler(JavaClientConnection connection, ProjectsManager projectsManager, ClientPreferences prefs) { this.connection = connection; this.projectsManager = projectsManager; + this.isDiagnosticTagSupported = prefs != null ? prefs.isDiagnosticTagSupported() : false; } public void addResourceChangeListener() { @@ -150,7 +158,7 @@ else if (projectsManager.isBuildFile(file)) { } if (document != null) { String uri = JDTUtils.getFileURI(resource); - this.connection.publishDiagnostics(new PublishDiagnosticsParams(ResourceUtils.toClientUri(uri), toDiagnosticsArray(document, markers))); + this.connection.publishDiagnostics(new PublishDiagnosticsParams(ResourceUtils.toClientUri(uri), toDiagnosticsArray(document, markers, isDiagnosticTagSupported))); } return false; } @@ -173,13 +181,13 @@ private void publishMarkers(IProject project, IMarker[] markers) throws CoreExce projectMarkers.add(marker); } } - List diagnostics = toDiagnosticArray(range, projectMarkers); + List diagnostics = toDiagnosticArray(range, projectMarkers, isDiagnosticTagSupported); String clientUri = ResourceUtils.toClientUri(uri); connection.publishDiagnostics(new PublishDiagnosticsParams(clientUri, diagnostics)); if (pom.exists()) { IDocument document = JsonRpcHelpers.toDocument(pom); - diagnostics = toDiagnosticsArray(document, pom.findMarkers(null, true, IResource.DEPTH_ZERO)); - List diagnosicts2 = toDiagnosticArray(range, pomMarkers); + diagnostics = toDiagnosticsArray(document, pom.findMarkers(null, true, IResource.DEPTH_ZERO), isDiagnosticTagSupported); + List diagnosicts2 = toDiagnosticArray(range, pomMarkers, isDiagnosticTagSupported); diagnostics.addAll(diagnosicts2); connection.publishDiagnostics(new PublishDiagnosticsParams(ResourceUtils.toClientUri(clientUri + "/pom.xml"), diagnostics)); } @@ -252,13 +260,16 @@ private void publishDiagnostics(List markers) { document = JsonRpcHelpers.toDocument(file); } if (document != null) { - List diagnostics = WorkspaceDiagnosticsHandler.toDiagnosticsArray(document, entry.getValue().toArray(new IMarker[0])); + List diagnostics = WorkspaceDiagnosticsHandler.toDiagnosticsArray(document, entry.getValue().toArray(new IMarker[0]), isDiagnosticTagSupported); connection.publishDiagnostics(new PublishDiagnosticsParams(ResourceUtils.toClientUri(uri), diagnostics)); } } } - + @Deprecated + public static List toDiagnosticArray(Range range, Collection markers) { + return toDiagnosticArray(range, markers, false); + } /** * Transforms {@link IMarker}s into a list of {@link Diagnostic}s @@ -267,12 +278,12 @@ private void publishDiagnostics(List markers) { * @param markers * @return a list of {@link Diagnostic}s */ - public static List toDiagnosticArray(Range range, Collection markers) { - List diagnostics = markers.stream().map(m -> toDiagnostic(range, m)).filter(d -> d != null).collect(Collectors.toList()); + public static List toDiagnosticArray(Range range, Collection markers, boolean isDiagnosticTagSupported) { + List diagnostics = markers.stream().map(m -> toDiagnostic(range, m, isDiagnosticTagSupported)).filter(d -> d != null).collect(Collectors.toList()); return diagnostics; } - private static Diagnostic toDiagnostic(Range range, IMarker marker) { + private static Diagnostic toDiagnostic(Range range, IMarker marker, boolean isDiagnosticTagSupported) { if (marker == null || !marker.exists()) { return null; } @@ -284,11 +295,20 @@ private static Diagnostic toDiagnostic(Range range, IMarker marker) { } d.setMessage(message); d.setSeverity(convertSeverity(marker.getAttribute(IMarker.SEVERITY, -1))); - d.setCode(String.valueOf(marker.getAttribute(IJavaModelMarker.ID, 0))); + int problemId = marker.getAttribute(IJavaModelMarker.ID, 0); + d.setCode(String.valueOf(problemId)); + if (isDiagnosticTagSupported) { + d.setTags(DiagnosticsHandler.getDiagnosticTag(problemId)); + } d.setRange(range); return d; } + @Deprecated + public static List toDiagnosticsArray(IDocument document, IMarker[] markers) { + return toDiagnosticsArray(document, markers, false); + } + /** * Transforms {@link IMarker}s of a {@link IDocument} into a list of * {@link Diagnostic}s. @@ -297,24 +317,28 @@ private static Diagnostic toDiagnostic(Range range, IMarker marker) { * @param markers * @return a list of {@link Diagnostic}s */ - public static List toDiagnosticsArray(IDocument document, IMarker[] markers) { + public static List toDiagnosticsArray(IDocument document, IMarker[] markers, boolean isDiagnosticTagSupported) { List diagnostics = Stream.of(markers) - .map(m -> toDiagnostic(document, m)) + .map(m -> toDiagnostic(document, m, isDiagnosticTagSupported)) .filter(d -> d != null) .collect(Collectors.toList()); return diagnostics; } - private static Diagnostic toDiagnostic(IDocument document, IMarker marker) { + private static Diagnostic toDiagnostic(IDocument document, IMarker marker, boolean isDiagnosticTagSupported) { if (marker == null || !marker.exists()) { return null; } Diagnostic d = new Diagnostic(); d.setSource(JavaLanguageServerPlugin.SERVER_SOURCE_ID); d.setMessage(marker.getAttribute(IMarker.MESSAGE, "")); - d.setCode(String.valueOf(marker.getAttribute(IJavaModelMarker.ID, 0))); + int problemId = marker.getAttribute(IJavaModelMarker.ID, 0); + d.setCode(String.valueOf(problemId)); d.setSeverity(convertSeverity(marker.getAttribute(IMarker.SEVERITY, -1))); d.setRange(convertRange(document, marker)); + if (isDiagnosticTagSupported) { + d.setTags(DiagnosticsHandler.getDiagnosticTag(problemId)); + } return d; } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java index 6a2bc74348..8ee8e16c55 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/ClientPreferences.java @@ -274,4 +274,17 @@ public boolean isSupportedCodeActionKind(String kind) { .stream().filter(k -> kind.startsWith(k)).findAny().isPresent(); //@formatter:on } + + /** + * {@code true} if the client has explicitly set the + * {@code textDocument.publishDiagnostics.tagSupport} to + * {@code true} when initializing the LS. Otherwise, {@code false}. + */ + public boolean isDiagnosticTagSupported() { + //@formatter:off + return v3supported && capabilities.getTextDocument().getPublishDiagnostics() != null + && capabilities.getTextDocument().getPublishDiagnostics().getTagSupport() != null + && capabilities.getTextDocument().getPublishDiagnostics().getTagSupport().booleanValue(); + //@formatter:on + } } diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/AbstractQuickFixTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/AbstractQuickFixTest.java index 15b46e8641..cab9e654f2 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/AbstractQuickFixTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/AbstractQuickFixTest.java @@ -250,7 +250,7 @@ protected List> evaluateCodeActions(ICompilationUnit parms.setTextDocument(textDocument); parms.setRange(range); CodeActionContext context = new CodeActionContext(); - context.setDiagnostics(DiagnosticsHandler.toDiagnosticsArray(cu, Arrays.asList(problems))); + context.setDiagnostics(DiagnosticsHandler.toDiagnosticsArray(cu, Arrays.asList(problems), true)); context.setOnly(onlyKinds); parms.setContext(context); diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DiagnosticHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DiagnosticHandlerTest.java index 5d745a62bc..0e0ad62522 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DiagnosticHandlerTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DiagnosticHandlerTest.java @@ -35,6 +35,7 @@ import org.eclipse.jdt.ls.core.internal.managers.AbstractProjectsManagerBasedTest; import org.eclipse.lsp4j.Diagnostic; import org.eclipse.lsp4j.DiagnosticSeverity; +import org.eclipse.lsp4j.DiagnosticTag; import org.eclipse.lsp4j.Range; import org.junit.Before; import org.junit.Test; @@ -73,7 +74,7 @@ public void testMultipleLineRange() throws Exception { CompilationUnit astRoot = CoreASTProvider.getInstance().getAST(cu, CoreASTProvider.WAIT_YES, monitor); IProblem[] problems = astRoot.getProblems(); - List diagnostics = DiagnosticsHandler.toDiagnosticsArray(cu, Arrays.asList(problems)); + List diagnostics = DiagnosticsHandler.toDiagnosticsArray(cu, Arrays.asList(problems), true); assertEquals(1, diagnostics.size()); Range range = diagnostics.get(0).getRange(); assertNotEquals(range.getStart().getLine(), range.getEnd().getLine()); @@ -122,7 +123,7 @@ public IProblemRequestor getProblemRequestor(ICompilationUnit workingCopy) { cu.reconcile(ICompilationUnit.NO_AST, true, wcOwner, null); List problems = handler.getProblems(); assertEquals(problems.size(), 1); - List diagnostics = DiagnosticsHandler.toDiagnosticsArray(cu, problems); + List diagnostics = DiagnosticsHandler.toDiagnosticsArray(cu, problems, true); assertEquals(diagnostics.size(), 1); DiagnosticSeverity severity = diagnostics.get(0).getSeverity(); assertEquals(severity, DiagnosticSeverity.Information); @@ -174,7 +175,7 @@ public IProblemRequestor getProblemRequestor(ICompilationUnit workingCopy) { cu.reconcile(ICompilationUnit.NO_AST, true, wcOwner, null); List problems = handler.getProblems(); assertEquals(problems.size(), 1); - List diagnostics = DiagnosticsHandler.toDiagnosticsArray(cu, problems); + List diagnostics = DiagnosticsHandler.toDiagnosticsArray(cu, problems, true); assertEquals(diagnostics.size(), 1); DiagnosticSeverity severity = diagnostics.get(0).getSeverity(); assertEquals(severity, DiagnosticSeverity.Warning); @@ -183,4 +184,24 @@ public IProblemRequestor getProblemRequestor(ICompilationUnit workingCopy) { } } + @Test + public void testDeprecated() throws Exception { + IJavaProject javaProject = newEmptyProject(); + IPackageFragmentRoot sourceFolder = javaProject.getPackageFragmentRoot(javaProject.getProject().getFolder("src")); + IPackageFragment pack1 = sourceFolder.createPackageFragment("test1", false, null); + + StringBuilder buf = new StringBuilder(); + buf.append("package test1;\n"); + buf.append("import java.security.Certificate;\n"); + ICompilationUnit cu = pack1.createCompilationUnit("E.java", buf.toString(), false, null); + + CompilationUnit astRoot = CoreASTProvider.getInstance().getAST(cu, CoreASTProvider.WAIT_YES, monitor); + IProblem[] problems = astRoot.getProblems(); + List diagnostics = DiagnosticsHandler.toDiagnosticsArray(cu, Arrays.asList(problems), true); + assertEquals(2, diagnostics.size()); + List tags = diagnostics.get(0).getTags(); + assertEquals(1, tags.size()); + assertEquals(DiagnosticTag.Deprecated, tags.get(0)); + } + } diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifeCycleHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifeCycleHandlerTest.java index 12c87e12fd..4e4b96be8d 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifeCycleHandlerTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifeCycleHandlerTest.java @@ -168,7 +168,7 @@ protected List> getCodeActions(ICompilationUnit cu) parms.setTextDocument(textDocument); parms.setRange(range); CodeActionContext context = new CodeActionContext(); - context.setDiagnostics(DiagnosticsHandler.toDiagnosticsArray(cu, Arrays.asList(problems))); + context.setDiagnostics(DiagnosticsHandler.toDiagnosticsArray(cu, Arrays.asList(problems), true)); context.setOnly(Arrays.asList(CodeActionKind.QuickFix)); parms.setContext(context); diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandlerTest.java index 370a5079b4..5824efc3e0 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandlerTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandlerTest.java @@ -35,6 +35,7 @@ import org.eclipse.jdt.ls.core.internal.JavaClientConnection; import org.eclipse.jdt.ls.core.internal.ResourceUtils; import org.eclipse.jdt.ls.core.internal.managers.AbstractProjectsManagerBasedTest; +import org.eclipse.jdt.ls.core.internal.preferences.ClientPreferences; import org.eclipse.jdt.ls.tests.Unstable; import org.eclipse.jface.text.IDocument; import org.eclipse.lsp4j.Diagnostic; @@ -66,7 +67,7 @@ public class WorkspaceDiagnosticsHandlerTest extends AbstractProjectsManagerBase @Before public void setup() throws Exception { - handler = new WorkspaceDiagnosticsHandler(connection, projectsManager); + handler = new WorkspaceDiagnosticsHandler(connection, projectsManager, preferenceManager.getClientPreferences()); handler.addResourceChangeListener(); }