Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 349517 - [1.7][introduce parameter] must expand diamond type argument
Summary: [1.7][introduce parameter] must expand diamond type argument
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.7   Edit
Hardware: PC Windows XP
: P2 normal (vote)
Target Milestone: 3.8 M5   Edit
Assignee: Raksha Vasisht CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-06-15 22:41 EDT by Deepak Azad CLA
Modified: 2012-01-05 10:32 EST (History)
3 users (show)

See Also:
markus.kell.r: review-


Attachments
Patch + tests (7.99 KB, patch)
2011-07-05 04:45 EDT, Raksha Vasisht CLA
no flags Details | Diff
Patch + tests (13.43 KB, patch)
2011-07-28 04:49 EDT, 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 Deepak Azad CLA 2011-06-15 22:41:13 EDT
--------------------------------------------------------
class Diamond {
	void foo() {
		Map<String, String> m = new HashMap<>();
	}

	public static void main(String[] args) {
		new Diamond().foo();
	}
}
--------------------------------------------------------

- Select "new HashMap<>()"
- Refactor > Introduce Parameter 

=>
-------------------------------------------------------
class Diamond {
	void foo(HashMap<String, String> hashMap) {
		Map<String, String> m = hashMap;
	}

	public static void main(String[] args) {
		new Diamond().foo(new HashMap<>()); //error here
	}
}
-------------------------------------------------------
Comment 1 Raksha Vasisht CLA 2011-06-21 07:15:37 EDT
Ill have a look.
Comment 2 Raksha Vasisht CLA 2011-07-05 04:45:57 EDT
Created attachment 199099 [details]
Patch + tests

The error was because the ParameterInfo for the diamond was set from the expression as it is without inferring the parameters. I have fixed it in the UI code although there can be APIs from core on Expression to determine if it has a diamond and whether the type parameters can be inferred. Markus, could you pls have a look at the fix?
Comment 3 Markus Keller CLA 2011-07-05 09:25:48 EDT
- You need to use the import rewrite to create the type references. Never create the type nodes yourself from a binding.

Example that fails (introduce parameter for "new java.util.HashMap<>()"):

import java.util.Map;
public class Diamond {
	class HashMap {}
	
    void foo() {
        Map<String, ? extends Number> m = new java.util.HashMap<>();
    }

    public static void main(String[] args) {
        new Diamond().foo();
    }
}

Don't create objects/variables unless you're sure you use them later ('ast' and 'simpleName' go inside the "if (parameters.length > 0)" block).

- classInstanceCreation.toString():
Javadoc says this is only for debugging purposes. Use ASTNodes#asFormattedString(..) for now. Eventually, this refactoring should use ChangeSignatureProcessor#setDefaultValueAdvisor(..), but that would be too much for now. We have other open bugs for the missing rewriting of values.
Comment 4 Markus Keller CLA 2011-07-05 09:32:08 EDT
To check whether we really deal with a diamond, use ClassInstanceCreation#getType(), test instanceof ParameterizedType and then check typeArguments() == 0.

See bug 349517 for the API request ClassInstanceCreation#isResolvedTypeInferredFromExpectedType(), but i don't think we need that here.
Comment 5 Deepak Azad CLA 2011-07-28 00:33:41 EDT
Ping!
Comment 6 Deepak Azad CLA 2011-07-28 00:37:11 EDT
(In reply to comment #4)
> See bug 349517 for the API request
> ClassInstanceCreation#isResolvedTypeInferredFromExpectedType(), but i don't
> think we need that here.
That is bug 350897 :)
Comment 7 Raksha Vasisht CLA 2011-07-28 04:49:45 EDT
Created attachment 200502 [details]
Patch + tests

Patch creates type using ImportRewriteContext so that the qualifier is not removed (replaced with an import) for cases shown in comment #3. Markus, could you pls review?
Comment 8 Markus Keller CLA 2012-01-04 12:41:58 EST
The "if (parameters.length > 0)" is a no-op (always true), since parameterized type bindings always have type arguments. See comment 4 for the right test. This can e.g. be seen when you have comments in the existing actual type arguments.

classInstanceCreation.setType(..) should not be called like this, since this modifies the original AST. However, this is the easiest solution and the whole thing is a hack anyway, so I left it in but restored the original AST node again.

The tests failed because the results were wrongly formatted.

Fixed with commit 2ffd9ab835396cfd7d6c2ece7e8e4297a15c25d5.
Comment 9 Markus Keller CLA 2012-01-05 10:25:11 EST
Tests were even more screwed than I initially saw:
- not formatted, whitespace garbage
- bad class names that lead to conflicting updates in unrelated test classes, depending on execution order

Furthermore, IntroduceParameterTests#testSimple_Capture() also failed, which apparently neither of us ever ran. Bug was that you used the result of typeBinding.getName() as type name, which is wrong (fails in this case and doesn't add imports).

Fixed everything with commit ab5a5917c6c3b36cd87f4bb10f197dd67d229257.
Comment 10 Markus Keller CLA 2012-01-05 10:32:42 EST
> Fixed everything with commit [..].
Got a push conflict, it's commit 317dc3d4384797a7c39d20d5060c363099cf125d.