Skip to content

Commit

Permalink
Allow code actions to be created if no Diagnostics is provided #1516
Browse files Browse the repository at this point in the history
  • Loading branch information
vrubezhny committed May 8, 2023
1 parent 7f66820 commit 2a7dcaf
Showing 1 changed file with 49 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018 Angelo ZERR
* Copyright (c) 2018, 2023 Angelo ZERR
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand All @@ -13,10 +13,12 @@
package org.eclipse.lemminx.services;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.services.extensions.XMLExtensionsRegistry;
Expand All @@ -27,6 +29,7 @@
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionContext;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DiagnosticSeverity;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;

Expand All @@ -39,37 +42,56 @@ public class XMLCodeActions {
private static final Logger LOGGER = Logger.getLogger(XMLCompletions.class.getName());

private final XMLExtensionsRegistry extensionsRegistry;

public static String NO_ERROR = "NoError";

public XMLCodeActions(XMLExtensionsRegistry extensionsRegistry) {
this.extensionsRegistry = extensionsRegistry;
}

public List<CodeAction> doCodeActions(CodeActionContext context, Range range, DOMDocument document,
SharedSettings sharedSettings, CancelChecker cancelChecker) {
cancelChecker.checkCanceled();
try {
cancelChecker.checkCanceled();

List<CodeAction> codeActions = new ArrayList<>();
List<Diagnostic> diagnostics = context.getDiagnostics();

// Add a "No Error" diagnostic for two reasons:
// 1) In order to allow providing Code Actions for document offsets where no Error/sWarnings/Info
// diagnostic code exist
// 2) In order to prevent duplication of Code Actions that do not require a certain diagnostic code.
// All code action participants that do not require a certain diagnostics node should react only to
// "NoError" diagnostic code - thus preventing the creation of duplicated code actions..
diagnostics = diagnostics != null ? diagnostics.stream().collect(Collectors.toList()) : new ArrayList<>();
Diagnostic noErrorDiagnostic = new Diagnostic(range, "No Error", DiagnosticSeverity.Hint, null, NO_ERROR);
if(!diagnostics.contains(noErrorDiagnostic)) {
diagnostics.add(noErrorDiagnostic);
}

List<CodeAction> codeActions = new ArrayList<>();
List<Diagnostic> diagnostics = context.getDiagnostics();
if (diagnostics != null) {
for (Diagnostic diagnostic : context.getDiagnostics()) {
for (ICodeActionParticipant codeActionParticipant : extensionsRegistry.getCodeActionsParticipants()) {
cancelChecker.checkCanceled();
try {
cancelChecker.checkCanceled();
CodeActionRequest request = new CodeActionRequest(diagnostic, range, document,
extensionsRegistry, sharedSettings);
codeActionParticipant.doCodeAction(request, codeActions, cancelChecker);
} catch (CancellationException e) {
throw e;
LOGGER.log(Level.FINER, e.getMessage(), e);
return Collections.emptyList();
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Error while processing code actions for the participant '"
+ codeActionParticipant.getClass().getName() + "'.", e);
}
}
}

cancelChecker.checkCanceled();
return codeActions;
} catch (CancellationException e) {
LOGGER.log(Level.FINER, e.getMessage(), e);
return Collections.emptyList();
}

cancelChecker.checkCanceled();
return codeActions;
}

public CodeAction resolveCodeAction(CodeAction unresolved, DOMDocument document, SharedSettings sharedSettings,
Expand All @@ -80,20 +102,25 @@ public CodeAction resolveCodeAction(CodeAction unresolved, DOMDocument document,
if (StringUtils.isEmpty(participantId)) {
return null;
}
for (ICodeActionParticipant codeActionParticipant : extensionsRegistry.getCodeActionsParticipants()) {
try {
cancelChecker.checkCanceled();
ICodeActionResolvesParticipant resolveCodeActionParticipant = codeActionParticipant
.getResolveCodeActionParticipant(participantId);
if (resolveCodeActionParticipant != null) {
return resolveCodeActionParticipant.resolveCodeAction(request, cancelChecker);
try {
for (ICodeActionParticipant codeActionParticipant : extensionsRegistry.getCodeActionsParticipants()) {
try {
cancelChecker.checkCanceled();
ICodeActionResolvesParticipant resolveCodeActionParticipant = codeActionParticipant
.getResolveCodeActionParticipant(participantId);
if (resolveCodeActionParticipant != null) {
return resolveCodeActionParticipant.resolveCodeAction(request, cancelChecker);
}
} catch (CancellationException e) {
LOGGER.log(Level.FINER, e.getMessage(), e);
return null;
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Error while processing resolve code action for the participant '"
+ codeActionParticipant.getClass().getName() + "'.", e);
}
} catch (CancellationException e) {
throw e;
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Error while processing resolve code action for the participant '"
+ codeActionParticipant.getClass().getName() + "'.", e);
}
} catch (CancellationException e) {
LOGGER.log(Level.FINER, e.getMessage(), e);
}
return null;
}
Expand Down

0 comments on commit 2a7dcaf

Please sign in to comment.