Skip to content

Commit

Permalink
Improve CodeAction performance with CodeAction#data & resolveCodeAction
Browse files Browse the repository at this point in the history
Fixes eclipse-lemminx#941

Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr committed Jun 14, 2022
1 parent 85a2e05 commit 82abfce
Show file tree
Hide file tree
Showing 73 changed files with 1,962 additions and 417 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.eclipse.lemminx.services.DocumentSymbolsResult;
import org.eclipse.lemminx.services.SymbolInformationResult;
import org.eclipse.lemminx.services.XMLLanguageService;
import org.eclipse.lemminx.services.data.DataEntryField;
import org.eclipse.lemminx.services.extensions.save.AbstractSaveContext;
import org.eclipse.lemminx.settings.CompositeSettings;
import org.eclipse.lemminx.settings.SharedSettings;
Expand Down Expand Up @@ -202,6 +203,7 @@ public void updateClientCapabilities(ClientCapabilities capabilities,
TextDocumentClientCapabilities textDocumentClientCapabilities = capabilities.getTextDocument();
if (textDocumentClientCapabilities != null) {
sharedSettings.getCompletionSettings().setCapabilities(textDocumentClientCapabilities.getCompletion());
sharedSettings.getCodeActionSettings().setCapabilities(textDocumentClientCapabilities.getCodeAction());
sharedSettings.getFoldingSettings().setCapabilities(textDocumentClientCapabilities.getFoldingRange());
sharedSettings.getHoverSettings().setCapabilities(textDocumentClientCapabilities.getHover());
sharedSettings.getValidationSettings()
Expand Down Expand Up @@ -478,6 +480,13 @@ public CompletableFuture<List<Either<Command, CodeAction>>> codeAction(CodeActio
});
}

@Override
public CompletableFuture<CodeAction> resolveCodeAction(CodeAction unresolved) {
return computeDOMAsync(unresolved.getData(), (xmlDocument, cancelChecker) -> {
return getXMLLanguageService().resolveCodeAction(unresolved, xmlDocument, sharedSettings, cancelChecker);
});
}

/**
* Returns the indentation settings (`xml.format.tabSize` and
* `xml.format.insertSpaces`) for the document with the given URI.
Expand Down Expand Up @@ -730,6 +739,15 @@ public boolean documentIsOpen(String uri) {
return document != null;
}

private <R> CompletableFuture<R> computeDOMAsync(Object data, BiFunction<DOMDocument, CancelChecker, R> code) {
String uri = DataEntryField.getUri(data);
if (uri == null) {
return CompletableFuture.completedFuture(null);
}
TextDocumentIdentifier identifier = new TextDocumentIdentifier(uri);
return computeDOMAsync(identifier, code);
}

/**
* Compute the DOM Document for a given uri in a future and then apply the given
* function.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ public static CodeAction insert(String title, Position position, String insertTe
insertContentAction.setDiagnostics(Arrays.asList(diagnostic));
TextDocumentEdit textDocumentEdit = insertEdit(insertText, position, document);
WorkspaceEdit workspaceEdit = new WorkspaceEdit(Collections.singletonList(Either.forLeft(textDocumentEdit)));

insertContentAction.setEdit(workspaceEdit);
return insertContentAction;
}
Expand Down Expand Up @@ -145,47 +144,59 @@ public static CodeAction replaceAt(String title, String replaceText, TextDocumen
* Makes a CodeAction to create a file and add content to the file.
*
* @param title The displayed name of the CodeAction
* @param docURI The file to create
* @param content The text to put into the newly created document.
* @param fileURI The file to create
* @param fileContent The text to put into the newly created document.
* @param diagnostic The diagnostic that this CodeAction will fix
*/
public static CodeAction createFile(String title, String docURI, String content, Diagnostic diagnostic) {
public static CodeAction createFile(String title, String fileURI, String fileContent, Diagnostic diagnostic) {
WorkspaceEdit createAndAddContentEdit = createFileEdit(fileURI, fileContent);
CodeAction codeAction = new CodeAction(title);
codeAction.setEdit(createAndAddContentEdit);
codeAction.setDiagnostics(Collections.singletonList(diagnostic));
codeAction.setKind(CodeActionKind.QuickFix);
return codeAction;
}

/**
* Returns the file edit to create the file with the given <code>fileURI</code>
* and the given <code>fileContent</code>.
*
* @param fileURI the file URI to create.
* @param fileContent the file content.
* @return the file edit to create the file with the given <code>fileURI</code>
* and the given <code>fileContent</code>.
*/
public static WorkspaceEdit createFileEdit(String fileURI, String fileContent) {
List<Either<TextDocumentEdit, ResourceOperation>> actionsToTake = new ArrayList<>(2);

// 1. create an empty file
actionsToTake.add(Either.forRight(new CreateFile(docURI, new CreateFileOptions(false, true))));
actionsToTake.add(Either.forRight(new CreateFile(fileURI, new CreateFileOptions(false, true))));

// 2. update the created file with the given content
VersionedTextDocumentIdentifier identifier = new VersionedTextDocumentIdentifier(docURI, 0);
TextEdit te = new TextEdit(new Range(new Position(0, 0), new Position(0, 0)), content);
VersionedTextDocumentIdentifier identifier = new VersionedTextDocumentIdentifier(fileURI, 0);
TextEdit te = new TextEdit(new Range(new Position(0, 0), new Position(0, 0)), fileContent);
actionsToTake.add(Either.forLeft(new TextDocumentEdit(identifier, Collections.singletonList(te))));

WorkspaceEdit createAndAddContentEdit = new WorkspaceEdit(actionsToTake);

CodeAction codeAction = new CodeAction(title);
codeAction.setEdit(createAndAddContentEdit);
codeAction.setDiagnostics(Collections.singletonList(diagnostic));
codeAction.setKind(CodeActionKind.QuickFix);

return codeAction;
return createAndAddContentEdit;
}

/**
* Makes a CodeAction to call a command from the available server commands.
*
* @param title The displayed name of the CodeAction
* @param commandId The id of the given command to add as CodeAction
* @param commandParams The document URI of the document the command is called on
* @param commandParams The document URI of the document the command is called
* on
* @param diagnostic The diagnostic that this CodeAction will fix
*/
public static CodeAction createCommand(String title, String commandId, List<Object> commandParams, Diagnostic diagnostic) {
public static CodeAction createCommand(String title, String commandId, List<Object> commandParams,
Diagnostic diagnostic) {
CodeAction codeAction = new CodeAction(title);
Command command = new Command(title, commandId, commandParams);
codeAction.setCommand(command);
codeAction.setDiagnostics(Collections.singletonList(diagnostic));
codeAction.setKind(CodeActionKind.QuickFix);

return codeAction;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLValidationSettings;
import org.eclipse.lemminx.services.IXMLDocumentProvider;
import org.eclipse.lemminx.services.IXMLValidationService;
import org.eclipse.lemminx.services.extensions.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.ICompletionParticipant;
import org.eclipse.lemminx.services.extensions.IDocumentLinkParticipant;
import org.eclipse.lemminx.services.extensions.IHoverParticipant;
import org.eclipse.lemminx.services.extensions.ITypeDefinitionParticipant;
import org.eclipse.lemminx.services.extensions.IXMLExtension;
import org.eclipse.lemminx.services.extensions.XMLExtensionsRegistry;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.codelens.ICodeLensParticipant;
import org.eclipse.lemminx.services.extensions.commands.IXMLCommandService;
import org.eclipse.lemminx.services.extensions.diagnostics.IDiagnosticsParticipant;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import javax.xml.parsers.SAXParserFactory;

import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.NoGrammarConstraintsCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.nogrammarconstraints.NoGrammarConstraintsCodeAction;
import org.eclipse.lemminx.services.IXMLDocumentProvider;
import org.eclipse.lemminx.services.extensions.commands.AbstractDOMDocumentCommandHandler;
import org.eclipse.lemminx.services.extensions.commands.ArgumentsUtils;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,13 @@
import java.util.List;
import java.util.Map;

import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.extensions.xsd.participants.XSDErrorCode;
import org.eclipse.lemminx.services.extensions.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.IComponentProvider;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionRequest;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionResolvesParticipant;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;

/**
Expand All @@ -35,23 +34,38 @@ public class ContentModelCodeActionParticipant implements ICodeActionParticipant
private final Map<String, ICodeActionParticipant> codeActionParticipants;

public ContentModelCodeActionParticipant() {
super();
codeActionParticipants = new HashMap<>();
}

@Override
public void doCodeAction(Diagnostic diagnostic, Range range, DOMDocument document, List<CodeAction> codeActions,
SharedSettings sharedSettings, IComponentProvider componentProvider, CancelChecker cancelChecker) {
public void doCodeAction(ICodeActionRequest request, List<CodeAction> codeActions, CancelChecker cancelChecker) {
Diagnostic diagnostic = request.getDiagnostic();
if (diagnostic == null || diagnostic.getCode() == null || !diagnostic.getCode().isLeft()) {
return;
}
SharedSettings sharedSettings = request.getSharedSettings();
registerCodeActionsIfNeeded(sharedSettings);
ICodeActionParticipant participant = codeActionParticipants.get(diagnostic.getCode().getLeft());
if (participant != null) {
participant.doCodeAction(diagnostic, range, document, codeActions, sharedSettings, componentProvider,
cancelChecker);
participant.doCodeAction(request, codeActions, cancelChecker);
}
}

@Override
public ICodeActionResolvesParticipant getResolveCodeActionParticipant(String participantId) {
// Loop for each code action participant to retrieve the proper resolver with
// the given participant ID.
for (ICodeActionParticipant participant : codeActionParticipants.values()) {
ICodeActionResolvesParticipant resolveParticipant = participant
.getResolveCodeActionParticipant(participantId);
if (resolveParticipant != null) {
return resolveParticipant;
}
}
return null;
}

/**
* Register code action if needed.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@
import org.eclipse.lemminx.dom.DOMRange;
import org.eclipse.lemminx.dom.DTDDeclParameter;
import org.eclipse.lemminx.dom.DTDEntityDecl;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.DTDNotFoundCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.ElementDeclUnterminatedCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.EntityNotDeclaredCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.FixMissingSpaceCodeAction;
import org.eclipse.lemminx.services.extensions.ICodeActionParticipant;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.missinggrammar.DTDNotFoundCodeAction;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.diagnostics.IXMLErrorCode;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.utils.XMLPositionUtility;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import java.util.Map;

import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.DownloadDisabledResourceCodeAction;
import org.eclipse.lemminx.services.extensions.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.diagnostics.IXMLErrorCode;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.cvc_elt_1_aCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.cvc_enumeration_validCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.cvc_type_3_1_1CodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.schema_reference_4CodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.missinggrammar.schema_reference_4CodeAction;
import org.eclipse.lemminx.extensions.xsd.utils.XSDUtils;
import org.eclipse.lemminx.services.extensions.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.diagnostics.IXMLErrorCode;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.utils.DOMUtils;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.ElementUnterminatedCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.EqRequiredInAttributeCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.MarkupEntityMismatchCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.NoGrammarConstraintsCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.OpenQuoteExpectedCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.RootElementTypeMustMatchDoctypedeclCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.SemicolonRequiredInReferenceCodeAction;
import org.eclipse.lemminx.services.extensions.ICodeActionParticipant;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.nogrammarconstraints.NoGrammarConstraintsCodeAction;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.diagnostics.IXMLErrorCode;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.utils.XMLPositionUtility;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@
import org.eclipse.lemminx.dom.DOMElement;
import org.eclipse.lemminx.dom.DOMNode;
import org.eclipse.lemminx.dom.LineIndentInfo;
import org.eclipse.lemminx.services.extensions.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.IComponentProvider;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.codeaction.ICodeActionRequest;
import org.eclipse.lemminx.utils.XMLPositionUtility;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.Diagnostic;
Expand All @@ -36,8 +35,9 @@
public class CloseTagCodeAction implements ICodeActionParticipant {

@Override
public void doCodeAction(Diagnostic diagnostic, Range range, DOMDocument document, List<CodeAction> codeActions,
SharedSettings sharedSettings, IComponentProvider componentProvider, CancelChecker cancelChecker) {
public void doCodeAction(ICodeActionRequest request, List<CodeAction> codeActions, CancelChecker cancelChecker) {
Diagnostic diagnostic = request.getDiagnostic();
DOMDocument document = request.getDocument();
Range diagnosticRange = diagnostic.getRange();
try {
int startOffset = document.offsetAt(diagnosticRange.getStart()) + 1;
Expand Down
Loading

0 comments on commit 82abfce

Please sign in to comment.