Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 258072 - [quick fix] Dead code detection quick fix leaves behind the curly braces
Summary: [quick fix] Dead code detection quick fix leaves behind the curly braces
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.5   Edit
Hardware: All All
: P3 minor (vote)
Target Milestone: 3.7 M4   Edit
Assignee: Raksha Vasisht CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 302600 (view as bug list)
Depends on:
Blocks:
 
Reported: 2008-12-09 08:57 EST by Raksha Vasisht CLA
Modified: 2010-12-07 11:31 EST (History)
4 users (show)

See Also:


Attachments
Patch (1.52 KB, patch)
2010-07-12 14:34 EDT, Raksha Vasisht CLA
no flags Details | Diff
Patch_2 (1.60 KB, patch)
2010-11-23 03:25 EST, Raksha Vasisht CLA
no flags Details | Diff
patch 3 (1.91 KB, patch)
2010-12-01 15:11 EST, Markus Keller CLA
no flags Details | Diff
Patch + tests (17.10 KB, patch)
2010-12-02 09:22 EST, Raksha Vasisht CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Raksha Vasisht CLA 2008-12-09 08:57:57 EST
The quick fix for the dead code detection removes the code as well as the condition, which works in case of only 'if' block but if an 'if-else ' block is used it leaves behind the curly braces with the valid code.

Try this simple test case:

                if (false){
			 x= 1;
		}else {
			 x= 0;
		}
then click on remove in the quick fix. It leaves this :
                {
			 x= 0;
		}
Comment 1 Dani Megert CLA 2008-12-09 09:00:09 EST
Build: I20081209-0100.
Comment 2 Dani Megert CLA 2010-04-14 03:07:15 EDT
*** Bug 302600 has been marked as a duplicate of this bug. ***
Comment 3 Dani Megert CLA 2010-04-14 03:09:47 EDT
Test Case for pasting into Package Explorer:
	void test() {
		Object o = new Object();
		if (o != null) {
			if (o == null) {
				System.out.println("hello");
			} else {
				System.out.println("bye");
			}
		}
	}
Comment 4 Raksha Vasisht CLA 2010-07-12 14:34:56 EDT
Created attachment 174084 [details]
Patch

Removes the curly braces when there are single or multiple statements in the if or else unreachable block.

Ex: 
void test2() {
		Object o= new Object();
		if (o != null) {
			if (o == null) {
				System.out.println("hello");
			} else {
				System.out.println("bye");
				System.out.println("bye-bye");
			}
		}
	}
Comment 5 Markus Keller CLA 2010-07-30 15:09:34 EDT
It's not that easy, that's why I didn't do it in the first place ;-)

package snippet;
public class Snippet {
	public static void main(String[] args) {
		test(true);
		test(false);
	}

	static void test(boolean b) {
		Object o = new Object();
		if (o != null) {
	    	if (b)
		        if (o == null) {
		            System.out.println("hello");
		        } else {
		            System.out.println("bye " + b);
		            System.out.println("bye " + b);
		        }
		}
	}
}

You have to think about all constructs in the AST where a block could be unused and rule out all possible side effects when removing the block.

Code pointers that could help:
- ControlStatementsFix#createRemoveBlockFix(CompilationUnit, ASTNode)
- ASTNodes#isControlStatementBody(StructuralPropertyDescriptor)
We already have a helper method ASTNodes#substituteMustBeParenthesized(..) for parentheses. Maybe we need something similar for Blocks?

We should also have a tests for this in LocalCorrectionsQuickFixTest.
Comment 6 Raksha Vasisht CLA 2010-11-23 03:25:16 EST
Created attachment 183641 [details]
Patch_2

(In reply to comment #5)
> It's not that easy, that's why I didn't do it in the first place ;-)
> 
> package snippet;
> public class Snippet {
>     public static void main(String[] args) {
>         test(true);
>         test(false);
>     }
> 
>     static void test(boolean b) {
>         Object o = new Object();
>         if (o != null) {
>             if (b)
>                 if (o == null) {
>                     System.out.println("hello");
>                 } else {
>                     System.out.println("bye " + b);
>                     System.out.println("bye " + b);
>                 }
>         }
>     }
> }
> 
> You have to think about all constructs in the AST where a block could be unused
> and rule out all possible side effects when removing the block.
> 
> Code pointers that could help:
> - ControlStatementsFix#createRemoveBlockFix(CompilationUnit, ASTNode)
> - ASTNodes#isControlStatementBody(StructuralPropertyDescriptor)
> We already have a helper method ASTNodes#substituteMustBeParenthesized(..) for
> parentheses. Maybe we need something similar for Blocks?
> 
> We should also have a tests for this in LocalCorrectionsQuickFixTest.

I looked at all the code mentioned but I think we could solve this by checking if the parent node is a Block or not and only if it is then copy the statements in the block and replace the removed node without adding the extra parenthesis. The existing behavior is to add the parenthesis around the node that would replace the removed node by default, so we dont need to add extra code like ASTNodes#substituteMustBeParenthesized(..), ASTNodes#isControlStatementBody(StructuralPropertyDescriptor) to check, instead we could just check first whether the node itself is a Block, if it is then if the parent node is also a Block then remove the parenthesis , else keep the parenthesis. 

Here's another example :

static void test3() {
		Object o = new Object();
		if (o != null)
			if (true)
				if (true)
					if (o != null) {
						System.out.println("hello");
						System.out.println("hi");
					} else {
						System.out.println("bye");
						System.out.println("bye-bye");
					}
				else
					System.out.println("out");
			else
				System.out.println("outermost");
	}
Comment 7 Markus Keller CLA 2010-12-01 15:11:22 EST
Created attachment 184298 [details]
patch 3

(In reply to comment #6)
> Created an attachment (id=183641) [details] [diff]
> Patch_2

Looks good, but the parent of the removed block could also be a SwitchStatement. I've added this to the patch.

I've tested a bit more and found another bug with this snippet:

	static void test(boolean b) {
		Object o = new Object();
		if (o != null)
			if (b)
				if (o == null)
					System.out.println("x " + b);
		System.out.println("y " + b);
	}

This was already wrong before, but this is the place where the tips from comment 5 apply. I've also fixed that problem in this patch.

Raksha, please release if you agree with my changes and add regression tests for the problematic cases to LocalCorrectionsQuickFixTest (fix existing tests).
Comment 8 Raksha Vasisht CLA 2010-12-02 09:18:19 EST
(In reply to comment #7)
> Created an attachment (id=184298) [details] [diff]
> patch 3
> 
> I've tested a bit more and found another bug with this snippet:
> 
>     static void test(boolean b) {
>         Object o = new Object();
>         if (o != null)
>             if (b)
>                 if (o == null)
>                     System.out.println("x " + b);
>         System.out.println("y " + b);
>     }
> 
> This was already wrong before, but this is the place where the tips from
> comment 5 apply. I've also fixed that problem in this patch.

Ah yes. Good catch! 
> 
> Raksha, please release if you agree with my changes and add regression tests
> for the problematic cases to LocalCorrectionsQuickFixTest (fix existing tests).

Yes. Added the tests and committed the above patch to HEAD.
Comment 9 Raksha Vasisht CLA 2010-12-02 09:22:53 EST
Created attachment 184353 [details]
Patch + tests

..and here's the patch.
Comment 10 Rajesh CLA 2010-12-07 11:31:46 EST
Verified in I20101206-1800.