| Summary: | [1.7][content assist]Getting NegativeArraySizeException while trying content assist after diamond | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Satyam Kandula <satyam.kandula> | ||||||||
| Component: | Core | Assignee: | Ayushman Jain <amj87.iitr> | ||||||||
| Status: | VERIFIED FIXED | QA Contact: | |||||||||
| Severity: | normal | ||||||||||
| Priority: | P3 | CC: | amj87.iitr, Olivier_Thomann, srikanth_sankaran | ||||||||
| Version: | 3.7 | Flags: | satyam.kandula:
review+
|
||||||||
| Target Milestone: | 3.7.1 | ||||||||||
| Hardware: | PC | ||||||||||
| OS: | Windows XP | ||||||||||
| Whiteboard: | |||||||||||
| Attachments: |
|
||||||||||
Note also that currenly we don't give any proposals after Test<String> t = new Test<String>[CTRL-SPC] even on HEAD. Maybe we can propose a constructor here. Note that CompletionOnQualifiedAllocationExpression.resolveType() doesn't call super.resolveType() but does some other things and hence special processing for diamond cases may not be happening. Watch out for these and other parser related changes that should probably happen. Look at the patch for bug 343693 for probable changes required. I don't see the NegativeSizeArrayEx anymore. It got fixed with bug 343637. Although, we may want to look at what we want to propose when content assist is invoked after new Test<String> or after new Test<> for both HEAD and BETA_JAVA7. On more testing, however, it turns out the exception now appears on the following test case (note the dot after <>)
public class Test <T>{
static class T2<Z>{
}
public void foo() {
Test<String> x = new Test<>.
}
}
This happens because currently Parser.genericsLengthStack not being zero can only imply Parameterized type. But now with diamond case, Parser.genericsLengthStack being -1 can also imply a parameterized type using <>. All places need to be checked for this. Created attachment 197027 [details] proposed fix The patch fixes a few issues with content assist used after <> 1) The first issue is the one reported in comment 4 and has been fixed in AssistParser 2) CompletionParser.consumeGenericTypeWithDiamond() has been added to make sure that the K_BINARY_OPERATOR type corresponding to < and > is popped off the stack when the generic type is consumed. In non <> cases, this gets taken care of by consumeReferenceType(), and other methods that consume the type parameters. 3) I observed that in cases where we request completion after something like Test<>| , we encounter the assist node before we have fully parsed the class instance creation expression and start the completion engine. So Parser.classInstanceCreation() is not called and even though Test<> is a diamond case, the ASTNode.IsDiamond flag remains unset. So, checkForDiamond has been added to CompletionParser.getTypeReferenceForGenericType() instead. Without changes in 2) and 3) the cases in comment 0 and comment 4 no longer throw the NASException but give completion results that differ from when we have Test<String> 4) CompletionOnQualifiedAllocationExpression.resolve() has been modified to handle the diamond case. It has also been made more resilient so that CompletionEngine can still propose something even if type inference fails or the type cannot be resolved. A part of this resilience can also be seen in the changes to CompletionEngine, where if we couldn't infer the type and happen to reach findConstructors(..) with type as Test<>, the type.availableMethods() call with throw an exception and completion engine will silently bail out. This is because in the followig case class Test<T> { public Test(T t) { } } the availableMethods will try and substitute the inferred type for T, but on fiding <> instead of type arguments, it will bail out. So in findConstructors(..), I added some code to make sure we atleast return Test(T t) without substitution when the type inference failed. This will help the following case: new Test<>(<CTRL-SPACE>) Satyam, please review. Thanks! Created attachment 197215 [details]
proposed fix v1.1 + regression tests
There was a small mistake in the prev. patch.
Changes look good to me. Minor comments: 1. Your patch missed the changes to CompletionTests. Your earlier patch has those tests. 2. As the IsDiamond tag is being used for also allocation expressions, you would want to add the particular comment for this tag in ASTNode.java. Created attachment 197247 [details]
released patch
Thanks Satyam
Released in BETA_JAVA7. Verified using "Eclipse Java Development Tools Patch for Java 7 Support (BETA) 1.0.0.v20110623-0900 org.eclipse.jdt.patch.feature.group Eclipse.org" |
####### public class Test <T>{ public void foo() { Test<String> x = new Test<> } } ##### In the above testcase, press CTRL-SPACE after <>, then the following exception comes up. java.lang.NegativeArraySizeException at org.eclipse.jdt.internal.codeassist.impl.AssistParser.getAssistTypeReferenceForGenericType(AssistParser.java:957) at org.eclipse.jdt.internal.codeassist.complete.CompletionParser.checkParemeterizedType(CompletionParser.java:1762) at org.eclipse.jdt.internal.codeassist.complete.CompletionParser.completionIdentifierCheck(CompletionParser.java:1990) at org.eclipse.jdt.internal.codeassist.complete.CompletionParser.updateRecoveryState(CompletionParser.java:4875) at org.eclipse.jdt.internal.compiler.parser.Parser.resumeOnSyntaxError(Parser.java:10860) at org.eclipse.jdt.internal.compiler.parser.Parser.parse(Parser.java:9575) at org.eclipse.jdt.internal.codeassist.impl.AssistParser.parseBlockStatements(AssistParser.java:1425) at org.eclipse.jdt.internal.codeassist.impl.AssistParser.parseBlockStatements(AssistParser.java:1264) at org.eclipse.jdt.internal.codeassist.impl.Engine.parseBlockStatements(Engine.java:307) at org.eclipse.jdt.internal.codeassist.impl.Engine.parseBlockStatements(Engine.java:270) at org.eclipse.jdt.internal.codeassist.CompletionEngine.complete(CompletionEngine.java:1854) at org.eclipse.jdt.internal.core.Openable.codeComplete(Openable.java:130) at org.eclipse.jdt.internal.core.CompilationUnit.codeComplete(CompilationUnit.java:357) at org.eclipse.jdt.internal.core.CompilationUnit.codeComplete(CompilationUnit.java:345)