diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/RefactorProcessor.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/RefactorProcessor.java index 3236d4db6a..59d1ab9f14 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/RefactorProcessor.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/RefactorProcessor.java @@ -525,10 +525,11 @@ private static boolean getConvertVarTypeToResolvedTypeProposal(IInvocationContex return false; } - if (!(node instanceof SimpleName)) { + SimpleName name = getSimpleNameForVariable(node); + if (name == null) { return false; } - SimpleName name = (SimpleName) node; + IBinding binding = name.resolveBinding(); if (!(binding instanceof IVariableBinding)) { return false; @@ -569,6 +570,26 @@ private static boolean getConvertVarTypeToResolvedTypeProposal(IInvocationContex return true; } + private static SimpleName getSimpleNameForVariable(ASTNode node) { + if (!(node instanceof SimpleName)) { + return null; + } + SimpleName name = (SimpleName) node; + if (!name.isDeclaration()) { + while (node instanceof Name || node instanceof Type) { + node = node.getParent(); + } + if (node instanceof VariableDeclarationStatement) { + List fragments = ((VariableDeclarationStatement) node).fragments(); + if (fragments.size() > 0) { + // var is not allowed in a compound declaration + name = fragments.get(0).getName(); + } + } + } + return name; + } + private static boolean getConvertResolvedTypeToVarTypeProposal(IInvocationContext context, ASTNode node, Collection proposals) { CompilationUnit astRoot = context.getASTRoot(); IJavaElement root = astRoot.getJavaElement(); @@ -583,10 +604,11 @@ private static boolean getConvertResolvedTypeToVarTypeProposal(IInvocationContex return false; } - if (!(node instanceof SimpleName)) { + SimpleName name = getSimpleNameForVariable(node); + if (name == null) { return false; } - SimpleName name = (SimpleName) node; + IBinding binding = name.resolveBinding(); if (!(binding instanceof IVariableBinding)) { return false; diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/ConvertVarQuickFixTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/ConvertVarQuickFixTest.java index ca7437676a..c82f895945 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/ConvertVarQuickFixTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/ConvertVarQuickFixTest.java @@ -22,9 +22,12 @@ import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.ls.core.internal.CodeActionUtil; import org.eclipse.jdt.ls.core.internal.WorkspaceHelper; import org.eclipse.lsp4j.CodeAction; +import org.eclipse.lsp4j.CodeActionKind; import org.eclipse.lsp4j.Command; +import org.eclipse.lsp4j.Range; import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.junit.Before; import org.junit.Test; @@ -58,6 +61,31 @@ public void testConvertVarTypeToResolvedType() throws Exception { assertNotNull(codeAction); } + @Test + public void testConvertVarTypeToResolvedType2() throws Exception { + IPackageFragment pack1 = sourceFolder.createPackageFragment("foo.bar", false, null); + StringBuilder buf = new StringBuilder(); + buf.append("package foo.bar;\n"); + buf.append("public class Test {\n"); + buf.append(" public void test() {\n"); + buf.append(" var/*cursor*/ name = \"test\";\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu = pack1.createCompilationUnit("Test.java", buf.toString(), false, null); + + buf = new StringBuilder(); + buf.append("package foo.bar;\n"); + buf.append("public class Test {\n"); + buf.append(" public void test() {\n"); + buf.append(" String name = \"test\";\n"); + buf.append(" }\n"); + buf.append("}\n"); + + Expected expected = new Expected("Change type of 'name' to 'String'", buf.toString(), CodeActionKind.Refactor); + Range range = CodeActionUtil.getRange(cu, "/*cursor*/", 0); + assertCodeActions(cu, range, expected); + } + @Test public void testConvertResolvedTypeToVar() throws Exception { IPackageFragment pack1 = sourceFolder.createPackageFragment("foo.bar", false, null); @@ -74,4 +102,29 @@ public void testConvertResolvedTypeToVar() throws Exception { assertNotNull(codeAction); } + @Test + public void testConvertResolvedTypeToVar2() throws Exception { + IPackageFragment pack1 = sourceFolder.createPackageFragment("foo.bar", false, null); + StringBuilder buf = new StringBuilder(); + buf.append("package foo.bar;\n"); + buf.append("public class Test {\n"); + buf.append(" public void test() {\n"); + buf.append(" String/*cursor*/ name = \"test\";\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu = pack1.createCompilationUnit("Test.java", buf.toString(), false, null); + + buf = new StringBuilder(); + buf.append("package foo.bar;\n"); + buf.append("public class Test {\n"); + buf.append(" public void test() {\n"); + buf.append(" var name = \"test\";\n"); + buf.append(" }\n"); + buf.append("}\n"); + + Expected expected = new Expected("Change type of 'name' to 'var'", buf.toString(), CodeActionKind.Refactor); + Range range = CodeActionUtil.getRange(cu, "/*cursor*/", 0); + assertCodeActions(cu, range, expected); + } + }