From 79ac82614e6dc71d8a7fcf802eee07098026adb8 Mon Sep 17 00:00:00 2001 From: Markus Keller Date: Tue, 21 Feb 2012 18:57:56 +0100 Subject: Bug 371078: [clean up] Regression: Remove unnecessary casts deletes code / causes compile errors --- .../eclipse/jdt/ui/tests/quickfix/CleanUpTest.java | 57 +++++++++++++++++++++- .../jdt/internal/corext/fix/UnusedCodeFix.java | 52 +++++++++++++++----- 2 files changed, 94 insertions(+), 15 deletions(-) diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/CleanUpTest.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/CleanUpTest.java index a465082b9e..d2b114a2da 100644 --- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/CleanUpTest.java +++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/CleanUpTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -927,7 +927,7 @@ public class CleanUpTest extends CleanUpTestCase { buf.append("\n"); buf.append("public class E1 {\n"); buf.append(" public void foo(Integer n) {\n"); - buf.append(" int i = (n).intValue();\n"); + buf.append(" int i = n.intValue();\n"); buf.append(" }\n"); buf.append("}\n"); String expected1= buf.toString(); @@ -962,6 +962,59 @@ public class CleanUpTest extends CleanUpTestCase { assertRefactoringResultAsExpected(new ICompilationUnit[] { cu1 }, new String[] { expected1 }); } + public void testUnusedCodeBug371078_1() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + + buf.append("package test1;\n"); + buf.append("class E1 {\n"); + buf.append(" public static Object create(final int a, final int b) {\n"); + buf.append(" return (Double) ((double) (a * Math.pow(10, -b)));\n"); + buf.append(" }\n"); + buf.append("}\n"); + + ICompilationUnit cu1= pack1.createCompilationUnit("IntComp.java", buf.toString(), false, null); + + enable(CleanUpConstants.REMOVE_UNNECESSARY_CASTS); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("class E1 {\n"); + buf.append(" public static Object create(final int a, final int b) {\n"); + buf.append(" return (a * Math.pow(10, -b));\n"); + buf.append(" }\n"); + buf.append("}\n"); + String expected1= buf.toString(); + + assertRefactoringResultAsExpected(new ICompilationUnit[] { cu1 }, new String[] { expected1 }); + } + + public void testUnusedCodeBug371078_2() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + + buf.append("package test1;\n"); + buf.append("public class NestedCasts {\n"); + buf.append(" void foo(Integer i) {\n"); + buf.append(" Object o= ((((Number) (((Integer) i)))));\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu1= pack1.createCompilationUnit("NestedCasts.java", buf.toString(), false, null); + + enable(CleanUpConstants.REMOVE_UNNECESSARY_CASTS); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public class NestedCasts {\n"); + buf.append(" void foo(Integer i) {\n"); + buf.append(" Object o= i;\n"); + buf.append(" }\n"); + buf.append("}\n"); + String expected1= buf.toString(); + + assertRefactoringResultAsExpected(new ICompilationUnit[] { cu1 }, new String[] { expected1 }); + } + public void testJava5001() throws Exception { IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); StringBuffer buf= new StringBuffer(); diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/UnusedCodeFix.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/UnusedCodeFix.java index b43d979b86..341d8baa6e 100644 --- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/UnusedCodeFix.java +++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/UnusedCodeFix.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -474,26 +474,52 @@ public class UnusedCodeFix extends CompilationUnitRewriteOperationsFix { while (fUnnecessaryCasts.size() > 0) { CastExpression castExpression= fUnnecessaryCasts.iterator().next(); fUnnecessaryCasts.remove(castExpression); + + /* + * ASTRewrite doesn't allow replacing (deleting) of moved nodes. To solve problems + * with nested casts, we need to replace all casts at once. + * + * The loops first proceed downwards to find the innermost expression that stays in the result + * and then proceeds towards the top to find the outermost cast that needs to be replaced. + * Both loops also skip unnecessary parenthesized nodes. + */ CastExpression down= castExpression; - while (fUnnecessaryCasts.contains(down.getExpression())) { - down= (CastExpression)down.getExpression(); - fUnnecessaryCasts.remove(down); + ASTNode downChild= down.getExpression(); + while (true) { + if (fUnnecessaryCasts.contains(downChild)) { + down= (CastExpression) downChild; + fUnnecessaryCasts.remove(down); + downChild= down.getExpression(); + } else if (downChild instanceof ParenthesizedExpression) { + if (!NecessaryParenthesesChecker.needsParentheses(castExpression, downChild.getParent(), downChild.getLocationInParent())) { + downChild= ((ParenthesizedExpression) downChild).getExpression(); + if (downChild instanceof CastExpression) + down= (CastExpression) downChild; + } else { + break; + } + } else { + break; + } } Expression expression= down.getExpression(); ASTNode move= rewrite.createMoveTarget(expression); - CastExpression top= castExpression; - while (fUnnecessaryCasts.contains(top.getParent())) { - top= (CastExpression)top.getParent(); - fUnnecessaryCasts.remove(top); + ASTNode top= castExpression; + while (true) { + ASTNode parent= top.getParent(); + if (fUnnecessaryCasts.contains(parent)) { + top= parent; + fUnnecessaryCasts.remove(top); + } else if (parent instanceof ParenthesizedExpression && !NecessaryParenthesesChecker.needsParentheses(expression, parent, top.getLocationInParent())) { + top= parent; + } else { + break; + } } - ASTNode toReplace= top; - if (top.getParent() instanceof ParenthesizedExpression && !NecessaryParenthesesChecker.needsParentheses(expression, top.getParent(), top.getLocationInParent())) { - toReplace= top.getParent(); - } - rewrite.replace(toReplace, move, group); + rewrite.replace(top, move, group); } } } -- cgit v1.2.3