Skip to content

Commit

Permalink
Take advantage of CodeActionLiteral client capability
Browse files Browse the repository at this point in the history
If client advertises `CodeActionLiteralSupport`, using that for
`java.apply.workspaceEdit` would allow clients to use a generic
algorithm, instead of being forced to provide a special case for jdt.ls.

Fixes #376

Signed-off-by: Boris Staletic <boris.staletic@gmail.com>
  • Loading branch information
Boris Staletic authored and fbricon committed Nov 13, 2019
1 parent a8360c9 commit 2a2e09b
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,13 @@ private Optional<Either<Command, CodeAction>> getCodeActionFromProposal(ChangeCo
}

if (preferenceManager.getClientPreferences().isSupportedCodeActionKind(proposal.getKind())) {
// TODO: Should set WorkspaceEdit directly instead of Command
CodeAction codeAction = new CodeAction(name);
codeAction.setKind(proposal.getKind());
codeAction.setCommand(command);
if (preferenceManager.getClientPreferences().isSupportedCodeActionLiteral()) {
codeAction.setEdit((WorkspaceEdit)command.getArguments().get(0));
} else {
codeAction.setCommand(command);
}
codeAction.setDiagnostics(context.getDiagnostics());
return Optional.of(Either.forRight(codeAction));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,20 @@ public boolean isSemanticHighlightingSupported() {

/**
* {@code true} if the client has explicitly set the
* {@code textDocument.documentSymbol.hierarchicalDocumentSymbolSupport} to
* {@code true} when initializing the LS. Otherwise, {@code false}.
* {@code textDocument.codeAction.codeActionLiteralSupport}
* when initializing the LS. Otherwise, {@code false}.
*/
public boolean isSupportedCodeActionLiteral() {
//@formatter:off
return v3supported && capabilities.getTextDocument().getCodeAction() != null
&& capabilities.getTextDocument().getCodeAction().getCodeActionLiteralSupport() != null;
//@formatter:on
}

/**
* {@code true} if the client has listed {@code kind} in
* {@code textDocument.codeAction.codeActionLiteralSupport.codeActionKind.valueSet}
* when initializing the LS. Otherwise, {@code false}.
*/
public boolean isSupportedCodeActionKind(String kind) {
//@formatter:off
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,11 @@ private Optional<Either<Command, CodeAction>> convertToWorkspaceEditAction(CodeA
if (preferenceManager.getClientPreferences().isSupportedCodeActionKind(kind)) {
CodeAction codeAction = new CodeAction(name);
codeAction.setKind(kind);
codeAction.setCommand(command);
if (preferenceManager.getClientPreferences().isSupportedCodeActionLiteral()) {
codeAction.setEdit(workspaceEdit);
} else {
codeAction.setCommand(command);
}
codeAction.setDiagnostics(context.getDiagnostics());
return Optional.of(Either.forRight(codeAction));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.Mockito.when;

/**
* @author Gorkem Ercan
Expand Down Expand Up @@ -97,6 +98,32 @@ public void testCodeAction_removeUnusedImport() throws Exception{
Assert.assertEquals(CodeActionHandler.COMMAND_ID_APPLY_EDIT, c.getCommand());
}

@Test
public void testCodeActionLiteral_removeUnusedImport() throws Exception{
when(preferenceManager.getClientPreferences().isSupportedCodeActionLiteral()).thenReturn(true);
ICompilationUnit unit = getWorkingCopy(
"src/java/Foo.java",
"import java.sql.*; \n" +
"public class Foo {\n"+
" void foo() {\n"+
" }\n"+
"}\n");

CodeActionParams params = new CodeActionParams();
params.setTextDocument(new TextDocumentIdentifier(JDTUtils.toURI(unit)));
final Range range = CodeActionUtil.getRange(unit, "java.sql");
params.setRange(range);
params.setContext(new CodeActionContext(Arrays.asList(getDiagnostic(Integer.toString(IProblem.UnusedImport), range))));
List<Either<Command, CodeAction>> codeActions = getCodeActions(params);
Assert.assertNotNull(codeActions);
Assert.assertTrue(codeActions.size() >= 3);
Assert.assertEquals(codeActions.get(0).getRight().getKind(), CodeActionKind.QuickFix);
Assert.assertEquals(codeActions.get(1).getRight().getKind(), CodeActionKind.QuickFix);
Assert.assertEquals(codeActions.get(2).getRight().getKind(), CodeActionKind.SourceOrganizeImports);
WorkspaceEdit w = codeActions.get(0).getRight().getEdit();
Assert.assertNotNull(w);
}

@Test
public void testCodeAction_sourceActionsOnly() throws Exception {
//@formatter:off
Expand Down Expand Up @@ -228,6 +255,30 @@ public void testCodeAction_removeUnterminatedString() throws Exception{
Assert.assertEquals(CodeActionHandler.COMMAND_ID_APPLY_EDIT, c.getCommand());
}

@Test
public void testCodeActionLiteral_removeUnterminatedString() throws Exception{
when(preferenceManager.getClientPreferences().isSupportedCodeActionLiteral()).thenReturn(true);
ICompilationUnit unit = getWorkingCopy(
"src/java/Foo.java",
"public class Foo {\n"+
" void foo() {\n"+
"String s = \"some str\n" +
" }\n"+
"}\n");

CodeActionParams params = new CodeActionParams();
params.setTextDocument(new TextDocumentIdentifier(JDTUtils.toURI(unit)));
final Range range = CodeActionUtil.getRange(unit, "some str");
params.setRange(range);
params.setContext(new CodeActionContext(Arrays.asList(getDiagnostic(Integer.toString(IProblem.UnterminatedString), range))));
List<Either<Command, CodeAction>> codeActions = getCodeActions(params);
Assert.assertNotNull(codeActions);
Assert.assertFalse(codeActions.isEmpty());
Assert.assertEquals(codeActions.get(0).getRight().getKind(), CodeActionKind.QuickFix);
WorkspaceEdit w = codeActions.get(0).getRight().getEdit();
Assert.assertNotNull(w);
}

@Test
public void testCodeAction_exception() throws JavaModelException {
URI uri = project.getFile("nopackage/Test.java").getRawLocationURI();
Expand Down

0 comments on commit 2a2e09b

Please sign in to comment.