Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always show Organize imports in Quick Fixes for import declaration #1936

Merged
merged 4 commits into from
Nov 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -157,18 +157,5 @@ public static void removeImportStatementProposals(IInvocationContext context, IP
JavaLanguageServerPlugin.log(e);
}
}

final ICompilationUnit cu= context.getCompilationUnit();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we remove this part since we will always show the quick fix.

String name= CorrectionMessages.ReorgCorrectionsSubProcessor_organizeimports_description;
CUCorrectionProposal proposal = new CUCorrectionProposal(name, CodeActionKind.QuickFix, cu, null, IProposalRelevance.ORGANIZE_IMPORTS) {

@Override
protected void addEdits(IDocument document, TextEdit editRoot) throws CoreException {
CompilationUnit astRoot = context.getASTRoot();
OrganizeImportsOperation op = new OrganizeImportsOperation(cu, astRoot, true, false, true, null);
editRoot.addChild(op.createTextEdit(null));
}
};
proposals.add(proposal);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.manipulation.CoreASTProvider;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.codemanipulation.GenerateGetterSetterOperation;
Expand Down Expand Up @@ -72,10 +71,10 @@ public static TextEdit generateAccessors(IType type, AccessorField[] accessors,
CompilationUnit astRoot = CoreASTProvider.getInstance().getAST(type.getCompilationUnit(), CoreASTProvider.WAIT_YES, monitor);
if (astRoot != null && cursor != null) {
ASTNode node = NodeFinder.perform(astRoot, DiagnosticsHelper.getStartOffset(type.getCompilationUnit(), cursor), DiagnosticsHelper.getLength(type.getCompilationUnit(), cursor));
declarationNode = SourceAssistProcessor.getDeclarationNode(node);
declarationNode = SourceAssistProcessor.getTypeDeclarationNode(node);
}
// If cursor position is not specified, then insert to the last by default.
IJavaElement insertPosition = (declarationNode instanceof TypeDeclaration) ? CodeGenerationUtils.findInsertElement(type, null) : CodeGenerationUtils.findInsertElement(type, cursor);
IJavaElement insertPosition = (declarationNode != null) ? CodeGenerationUtils.findInsertElement(type, null) : CodeGenerationUtils.findInsertElement(type, cursor);
GenerateGetterSetterOperation operation = new GenerateGetterSetterOperation(type, null, generateComments, insertPosition);
return operation.createTextEdit(null, accessors);
} catch (OperationCanceledException | CoreException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.manipulation.CoreASTProvider;
import org.eclipse.jdt.internal.corext.codemanipulation.AddCustomConstructorOperation;
Expand Down Expand Up @@ -165,10 +164,10 @@ public static TextEdit generateConstructors(IType type, LspMethodBinding[] const
ASTNode declarationNode = null;
if (cursor != null) {
ASTNode node = NodeFinder.perform(astRoot, DiagnosticsHelper.getStartOffset(type.getCompilationUnit(), cursor), DiagnosticsHelper.getLength(type.getCompilationUnit(), cursor));
declarationNode = SourceAssistProcessor.getDeclarationNode(node);
declarationNode = SourceAssistProcessor.getTypeDeclarationNode(node);
}
// If cursor position is not specified, then insert to the last by default.
IJavaElement insertPosition = (declarationNode instanceof TypeDeclaration) ? CodeGenerationUtils.findInsertElementAfterLastField(type) : CodeGenerationUtils.findInsertElement(type, cursor);
IJavaElement insertPosition = (declarationNode != null) ? CodeGenerationUtils.findInsertElementAfterLastField(type) : CodeGenerationUtils.findInsertElement(type, cursor);

Map<String, IVariableBinding> fieldBindings = new HashMap<>();
for (IVariableBinding binding : typeBinding.getDeclaredFields()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.manipulation.CoreASTProvider;
import org.eclipse.jdt.internal.corext.codemanipulation.tostringgeneration.GenerateToStringOperation;
import org.eclipse.jdt.internal.corext.codemanipulation.tostringgeneration.ToStringGenerationSettingsCore;
Expand Down Expand Up @@ -99,10 +98,10 @@ public static WorkspaceEdit generateToString(GenerateToStringParams params, IPro
CompilationUnit astRoot = CoreASTProvider.getInstance().getAST(type.getCompilationUnit(), CoreASTProvider.WAIT_YES, monitor);
if (astRoot != null && range != null) {
ASTNode node = NodeFinder.perform(astRoot, DiagnosticsHelper.getStartOffset(type.getCompilationUnit(), range), DiagnosticsHelper.getLength(type.getCompilationUnit(), range));
declarationNode = SourceAssistProcessor.getDeclarationNode(node);
declarationNode = SourceAssistProcessor.getTypeDeclarationNode(node);
}
// If cursor position is not specified, then insert to the last by default.
IJavaElement insertPosition = (declarationNode instanceof TypeDeclaration) ? CodeGenerationUtils.findInsertElement(type, null) : CodeGenerationUtils.findInsertElement(type, range);
IJavaElement insertPosition = (declarationNode != null) ? CodeGenerationUtils.findInsertElement(type, null) : CodeGenerationUtils.findInsertElement(type, range);
TextEdit edit = generateToString(type, params.fields, insertPosition, monitor);
return (edit == null) ? null : SourceAssistProcessor.convertToWorkspaceEdit(type.getCompilationUnit(), edit);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.manipulation.CoreASTProvider;
import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
import org.eclipse.jdt.internal.corext.codemanipulation.GenerateHashCodeEqualsOperation;
Expand Down Expand Up @@ -118,9 +117,9 @@ public static TextEdit generateHashCodeEqualsTextEdit(IType type, LspVariableBin
codeGenSettings.createComments = generateComments;
codeGenSettings.overrideAnnotation = true;
ASTNode node = NodeFinder.perform(astRoot, DiagnosticsHelper.getStartOffset(type.getCompilationUnit(), cursor), DiagnosticsHelper.getLength(type.getCompilationUnit(), cursor));
ASTNode declarationNode = SourceAssistProcessor.getDeclarationNode(node);
ASTNode declarationNode = SourceAssistProcessor.getTypeDeclarationNode(node);
// If cursor position is not specified, then insert to the last by default.
IJavaElement insertPosition = (declarationNode instanceof TypeDeclaration) ? CodeGenerationUtils.findInsertElement(type, null) : CodeGenerationUtils.findInsertElement(type, cursor);
IJavaElement insertPosition = (declarationNode != null) ? CodeGenerationUtils.findInsertElement(type, null) : CodeGenerationUtils.findInsertElement(type, cursor);
GenerateHashCodeEqualsOperation operation = new GenerateHashCodeEqualsOperation(typeBinding, variableBindings, astRoot, insertPosition, codeGenSettings, useInstanceof, useJava7Objects, regenerate, false, false);
operation.setUseBlocksForThen(useBlocks);
operation.run(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.manipulation.CoreASTProvider;
import org.eclipse.jdt.ls.core.internal.codemanipulation.OverrideMethodsOperation;
import org.eclipse.jdt.ls.core.internal.codemanipulation.OverrideMethodsOperation.OverridableMethod;
Expand Down Expand Up @@ -51,10 +50,10 @@ public static WorkspaceEdit addOverridableMethods(AddOverridableMethodParams par
CompilationUnit astRoot = CoreASTProvider.getInstance().getAST(type.getCompilationUnit(), CoreASTProvider.WAIT_YES, monitor);
if (astRoot != null && range != null) {
ASTNode node = NodeFinder.perform(astRoot, DiagnosticsHelper.getStartOffset(type.getCompilationUnit(), range), DiagnosticsHelper.getLength(type.getCompilationUnit(), range));
declarationNode = SourceAssistProcessor.getDeclarationNode(node);
declarationNode = SourceAssistProcessor.getTypeDeclarationNode(node);
}
// If cursor position is not specified, then insert to the last by default.
IJavaElement insertPosition = (declarationNode instanceof TypeDeclaration) ? CodeGenerationUtils.findInsertElement(type, null) : CodeGenerationUtils.findInsertElement(type, range);
IJavaElement insertPosition = (declarationNode != null) ? CodeGenerationUtils.findInsertElement(type, null) : CodeGenerationUtils.findInsertElement(type, range);
TextEdit edit = OverrideMethodsOperation.addOverridableMethods(type, params.overridableMethods, insertPosition, monitor);
if (edit == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.manipulation.CoreASTProvider;
Expand Down Expand Up @@ -103,6 +104,7 @@ public List<Either<Command, CodeAction>> getSourceActionCommands(CodeActionParam
ICompilationUnit cu = context.getCompilationUnit();
IType type = getSelectionType(context);
boolean isInTypeDeclaration = isInTypeDeclaration(context);
boolean isInImportDeclaration = isInImportDeclaration(context);

try {
// Generate Constructor QuickAssist
Expand All @@ -120,16 +122,29 @@ public List<Either<Command, CodeAction>> getSourceActionCommands(CodeActionParam

// Organize Imports
if (preferenceManager.getClientPreferences().isAdvancedOrganizeImportsSupported()) {
Optional<Either<Command, CodeAction>> organizeImports = getOrganizeImportsAction(params);
addSourceActionCommand($, params.getContext(), organizeImports);
// Generate QuickAssist
if (isInImportDeclaration) {
Optional<Either<Command, CodeAction>> quickAssistOrganizeImports = getOrganizeImportsAction(params, JavaCodeActionKind.QUICK_ASSIST);
addSourceActionCommand($, params.getContext(), quickAssistOrganizeImports);
}
// Generate Source Action
Optional<Either<Command, CodeAction>> sourceOrganizeImports = getOrganizeImportsAction(params, CodeActionKind.SourceOrganizeImports);
addSourceActionCommand($, params.getContext(), sourceOrganizeImports);
} else {
CodeActionProposal organizeImportsProposal = (pm) -> {
TextEdit edit = getOrganizeImportsProposal(context, pm);
return convertToWorkspaceEdit(cu, edit);
};
Optional<Either<Command, CodeAction>> organizeImports = getCodeActionFromProposal(params.getContext(), context.getCompilationUnit(), CorrectionMessages.ReorgCorrectionsSubProcessor_organizeimports_description,
// Generate QuickAssist
if (isInImportDeclaration) {
Optional<Either<Command, CodeAction>> sourceOrganizeImports = getCodeActionFromProposal(params.getContext(), context.getCompilationUnit(), CorrectionMessages.ReorgCorrectionsSubProcessor_organizeimports_description,
JavaCodeActionKind.QUICK_ASSIST, organizeImportsProposal);
addSourceActionCommand($, params.getContext(), sourceOrganizeImports);
}
// Generate Source Action
Optional<Either<Command, CodeAction>> sourceOrganizeImports = getCodeActionFromProposal(params.getContext(), context.getCompilationUnit(), CorrectionMessages.ReorgCorrectionsSubProcessor_organizeimports_description,
CodeActionKind.SourceOrganizeImports, organizeImportsProposal);
addSourceActionCommand($, params.getContext(), organizeImports);
addSourceActionCommand($, params.getContext(), sourceOrganizeImports);
}

if (!UNSUPPORTED_RESOURCES.contains(cu.getResource().getName())) {
Expand Down Expand Up @@ -248,12 +263,12 @@ private TextEdit getOrganizeImportsProposal(IInvocationContext context, IProgres
return null;
}

private Optional<Either<Command, CodeAction>> getOrganizeImportsAction(CodeActionParams params) {
private Optional<Either<Command, CodeAction>> getOrganizeImportsAction(CodeActionParams params, String kind) {
Command command = new Command(CorrectionMessages.ReorgCorrectionsSubProcessor_organizeimports_description, COMMAND_ID_ACTION_ORGANIZEIMPORTS, Collections.singletonList(params));
CodeAction codeAction = new CodeAction(CorrectionMessages.ReorgCorrectionsSubProcessor_organizeimports_description);
codeAction.setKind(CodeActionKind.SourceOrganizeImports);
codeAction.setKind(kind);
codeAction.setCommand(command);
codeAction.setDiagnostics(Collections.EMPTY_LIST);
codeAction.setDiagnostics(Collections.emptyList());
return Optional.of(Either.forRight(codeAction));

}
Expand Down Expand Up @@ -577,7 +592,7 @@ public static ICompilationUnit getCompilationUnit(CodeActionParams params) {
return JDTUtils.resolveCompilationUnit(params.getTextDocument().getUri());
}

public static ASTNode getDeclarationNode(ASTNode node) {
public static ASTNode getTypeDeclarationNode(ASTNode node) {
if (node == null) {
return null;
}
Expand All @@ -587,15 +602,32 @@ public static ASTNode getDeclarationNode(ASTNode node) {
while (node != null && !(node instanceof BodyDeclaration) && !(node instanceof Statement)) {
node = node.getParent();
}
return node;
return node instanceof TypeDeclaration ? node : null;
}

private static ASTNode getImportDeclarationNode(ASTNode node) {
if (node == null) {
return null;
}
while (node != null && !(node instanceof ImportDeclaration) && !(node instanceof Statement)) {
node = node.getParent();
}
return node instanceof ImportDeclaration ? node : null;
}

private static boolean isInTypeDeclaration(IInvocationContext context) {
ASTNode node = context.getCoveredNode();
if (node == null) {
node = context.getCoveringNode();
}
ASTNode declarationNode = getDeclarationNode(node);
return declarationNode instanceof TypeDeclaration;
return getTypeDeclarationNode(node) != null;
}

private static boolean isInImportDeclaration(IInvocationContext context) {
ASTNode node = context.getCoveredNode();
if (node == null) {
node = context.getCoveringNode();
}
return getImportDeclarationNode(node) != null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.eclipse.jdt.ls.core.internal.WorkspaceHelper;
import org.eclipse.jdt.ls.core.internal.codemanipulation.AbstractSourceTestCase;
import org.eclipse.jdt.ls.core.internal.correction.AbstractQuickFixTest;
import org.eclipse.jdt.ls.core.internal.corrections.CorrectionMessages;
import org.eclipse.jdt.ls.core.internal.preferences.ClientPreferences;
import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager;
import org.eclipse.lsp4j.CodeAction;
Expand Down Expand Up @@ -114,7 +115,7 @@ public void testCodeAction_removeUnusedImport() throws Exception{
Assert.assertTrue(codeActions.size() >= 3);
List<Either<Command, CodeAction>> quickAssistActions = findActions(codeActions, CodeActionKind.QuickFix);
Assert.assertNotNull(quickAssistActions);
Assert.assertTrue(quickAssistActions.size() >= 2);
Assert.assertTrue(quickAssistActions.size() >= 1);
List<Either<Command, CodeAction>> organizeImportActions = findActions(codeActions, CodeActionKind.SourceOrganizeImports);
Assert.assertNotNull(organizeImportActions);
Assert.assertEquals(1, organizeImportActions.size());
Expand Down Expand Up @@ -175,6 +176,30 @@ public void testCodeAction_organizeImportsSourceActionOnly() throws Exception {
}
}

@Test
public void testCodeAction_organizeImportsQuickFix() throws Exception {
ICompilationUnit unit = getWorkingCopy(
"src/java/Foo.java",
"import java.util.List;\n"+
"public class Foo {\n"+
" void foo() {\n"+
" String bar = \"astring\";"+
" }\n"+
"}\n");
CodeActionParams params = CodeActionUtil.constructCodeActionParams(unit, "util");
List<Either<Command, CodeAction>> codeActions = server.codeAction(params).join();

Assert.assertNotNull(codeActions);
List<Either<Command, CodeAction>> quickAssistActions = findActions(codeActions, JavaCodeActionKind.QUICK_ASSIST);
Assert.assertTrue(CodeActionHandlerTest.commandExists(quickAssistActions, CodeActionHandler.COMMAND_ID_APPLY_EDIT, CorrectionMessages.ReorgCorrectionsSubProcessor_organizeimports_description));
// Test if the quick assist exists only for type declaration
params = CodeActionUtil.constructCodeActionParams(unit, "String bar");
codeActions = server.codeAction(params).join();
Assert.assertNotNull(codeActions);
quickAssistActions = CodeActionHandlerTest.findActions(codeActions, JavaCodeActionKind.QUICK_ASSIST);
Assert.assertFalse(CodeActionHandlerTest.commandExists(quickAssistActions, CodeActionHandler.COMMAND_ID_APPLY_EDIT, CorrectionMessages.ReorgCorrectionsSubProcessor_organizeimports_description));
}

@Test
public void testCodeAction_refactorActionsOnly() throws Exception {
ICompilationUnit unit = getWorkingCopy(
Expand Down Expand Up @@ -480,7 +505,7 @@ public void testCodeAction_ignoringOtherDiagnosticWithoutCode() throws Exception
Assert.assertTrue(codeActions.size() >= 3);
List<Either<Command, CodeAction>> quickAssistActions = findActions(codeActions, CodeActionKind.QuickFix);
Assert.assertNotNull(quickAssistActions);
Assert.assertTrue(quickAssistActions.size() >= 2);
Assert.assertTrue(quickAssistActions.size() >= 1);
List<Either<Command, CodeAction>> organizeImportActions = findActions(codeActions, CodeActionKind.SourceOrganizeImports);
Assert.assertNotNull(organizeImportActions);
Assert.assertEquals(1, organizeImportActions.size());
Expand Down