diff options
| author | Srikanth Sankaran | 2013-10-04 08:57:35 +0000 |
|---|---|---|
| committer | M N Palat | 2013-10-04 08:57:35 +0000 |
| commit | f5937020c6b957eed03745f57cfee671f23dd9b8 (patch) | |
| tree | 3e7011610ad9b99a2b89eaab92f61ad23898d3d5 | |
| parent | 9485b94fdcfe614c14bea8b532c58213d01bbc20 (diff) | |
| download | eclipse.jdt.core-f5937020c6b957eed03745f57cfee671f23dd9b8.tar.gz eclipse.jdt.core-f5937020c6b957eed03745f57cfee671f23dd9b8.tar.xz eclipse.jdt.core-f5937020c6b957eed03745f57cfee671f23dd9b8.zip | |
Fix for Bug 417017 - [1.8] Incorrect parameters in resolved method
binding for LambdaExpression
5 files changed, 223 insertions, 6 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java index 807876636a..73afc7cec7 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java @@ -2645,6 +2645,200 @@ public class ASTConverter18Test extends ConverterTestSetup { typeBinding = type.resolveBinding(); assertFalse("A Functional interface", typeBinding.isFunctionalInterface()); } + /** + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=417017 + * + * @throws JavaModelException + */ + public void test417017a() throws JavaModelException { + this.workingCopy = getWorkingCopy("/Converter18/src/test417017/X.java", + true/* resolve */); + String contents = "package test417017;" + + "interface I {\n" + + " int foo(int x);\n" + + "}\n" + + "public class X {\n" + + " void fun(int a) {\n" + +" I i1 = x1-> x1;\n" + +" I i2 = xxx-> {\n" + +" i1.foo(a);\n" + +" return xxx;\n" + +" };\n" + +" }\n" + +"}\n"; + CompilationUnit cu = (CompilationUnit) buildAST(contents, this.workingCopy); + TypeDeclaration typedeclaration = (TypeDeclaration) getASTNode(cu, 1); + MethodDeclaration methodDeclaration = typedeclaration.getMethods()[0]; + VariableDeclarationFragment vdf= (VariableDeclarationFragment) ((VariableDeclarationStatement) methodDeclaration.getBody().statements().get(1)).fragments().get(0); + LambdaExpression lambda= (LambdaExpression) vdf.getInitializer(); + List parameters = lambda.parameters(); + assertTrue("Incorrect Number of parameters", parameters.size() == 1); + ITypeBinding[] parameterTypes= lambda.resolveMethodBinding().getParameterTypes(); + assertTrue("Incorrect Number of parameter type", parameterTypes.length == 1); + assertEquals("Incorrect parameter type", "int", parameterTypes[0].toString()); + } + /** + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=417017 + * + * @throws JavaModelException + */ + public void test417017b() throws JavaModelException { + this.workingCopy = getWorkingCopy("/Converter18/src/test417017/X.java", + true/* resolve */); + String contents = "package test417017;" + + "interface I1 {\n" + + " int foo(int a);\n" + + "}\n" + + "\n" + + "interface I2 {\n" + + " public default int foo() {\n" + + " I1 i1 = (a) -> {\n" + + " return a;\n" + + " };\n" + + " //return 0;\n" + // Error on purpose + " }\n" + + "}\n" ; + CompilationUnit cu = (CompilationUnit) buildAST(contents, this.workingCopy, false); + TypeDeclaration typedeclaration = (TypeDeclaration) getASTNode(cu, 1); + MethodDeclaration methodDeclaration = typedeclaration.getMethods()[0]; + VariableDeclarationFragment vdf= (VariableDeclarationFragment) ((VariableDeclarationStatement) methodDeclaration.getBody().statements().get(0)).fragments().get(0); + LambdaExpression lambda= (LambdaExpression) vdf.getInitializer(); + List parameters = lambda.parameters(); + assertTrue("Incorrect Number of parameters", parameters.size() == 1); + ITypeBinding[] parameterTypes= lambda.resolveMethodBinding().getParameterTypes(); + assertTrue("Incorrect Number of parameter type", parameterTypes.length == 1); + assertEquals("Incorrect parameter type", "int", parameterTypes[0].toString()); + } + /** + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=417017 + * + * @throws JavaModelException + */ + public void test417017c() throws JavaModelException { + this.workingCopy = getWorkingCopy("/Converter18/src/test417017/X.java", + true/* resolve */); + String contents = "package test417017;" + + "interface I1 {\n" + + " int foo(int a);\n" + + "}\n" + + "\n" + + "interface I2 {\n" + + " public default int foo() {\n" + + " I1 i1 = (float a) -> {\n" + + " return a;\n" + + " };\n" + + " //return 0;\n" + // Error on purpose + " }\n" + + "}\n" ; + CompilationUnit cu = (CompilationUnit) buildAST(contents, this.workingCopy, false); + TypeDeclaration typedeclaration = (TypeDeclaration) getASTNode(cu, 1); + MethodDeclaration methodDeclaration = typedeclaration.getMethods()[0]; + VariableDeclarationFragment vdf= (VariableDeclarationFragment) ((VariableDeclarationStatement) methodDeclaration.getBody().statements().get(0)).fragments().get(0); + LambdaExpression lambda= (LambdaExpression) vdf.getInitializer(); + List parameters = lambda.parameters(); + assertTrue("Incorrect Number of parameters", parameters.size() == 1); + ITypeBinding[] parameterTypes= lambda.resolveMethodBinding().getParameterTypes(); + assertTrue("Incorrect Number of parameter type", parameterTypes.length == 1); + assertEquals("Incorrect parameter type", "float", parameterTypes[0].toString()); + } + /** + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=417017 + * + * @throws JavaModelException + */ + public void test417017d() throws JavaModelException { + this.workingCopy = getWorkingCopy("/Converter18/src/test399794/X.java", + true/* resolve */); + String contents = "package test399794;" + + "interface I {\n" + + " void foo(X x);\n" + + "}\n" + + "public class X {\n" + + " void foo(X x) {\n" + + " }\n" + + " I i = this::foo;\n" + + "}\n"; + + CompilationUnit cu = (CompilationUnit) buildAST(contents, this.workingCopy); + TypeDeclaration typeDeclaration = (TypeDeclaration) getASTNode(cu, 1); + FieldDeclaration field = typeDeclaration.getFields()[0]; + + VariableDeclarationFragment fragment = (VariableDeclarationFragment) field.fragments().get(0); + Expression expression = fragment.getInitializer(); + ExpressionMethodReference methodReference = (ExpressionMethodReference) expression; + IMethodBinding methodBinding = methodReference.resolveMethodBinding(); + assertNotNull(methodBinding); + ITypeBinding [] parameterTypes = methodBinding.getParameterTypes(); + assertTrue("Incorrect Number of parameter type", parameterTypes.length == 1); + assertEquals("Incorrect parameter type", "X", parameterTypes[0].getName()); + } + + /** + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=417017 + * + * @throws JavaModelException + */ + public void test417017e() throws JavaModelException { + this.workingCopy = getWorkingCopy("/Converter18/src/test399794/X.java", + true/* resolve */); + String contents = "package test399794;" + + "interface I {\n" + + " int [] foo(int x);\n" + + "}\n" + + "public class X {\n" + + " I i = int []::new;\n" + + "}\n"; + + CompilationUnit cu = (CompilationUnit) buildAST(contents, this.workingCopy); + TypeDeclaration typeDeclaration = (TypeDeclaration) getASTNode(cu, 1); + FieldDeclaration field = typeDeclaration.getFields()[0]; + + VariableDeclarationFragment fragment = (VariableDeclarationFragment) field.fragments().get(0); + Expression expression = fragment.getInitializer(); + CreationReference creationReference = (CreationReference) expression; + IMethodBinding methodBinding = creationReference.resolveMethodBinding(); + assertNotNull(methodBinding); + assertEquals("Wrong name", "lambda$0", methodBinding.getName()); + ITypeBinding [] parameterTypes = methodBinding.getParameterTypes(); + assertTrue("Incorrect Number of parameter type", parameterTypes.length == 1); + assertEquals("Incorrect parameter type", "int", parameterTypes[0].getName()); + } + + /** + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=417017 + * + * @throws JavaModelException + */ + public void test417017f() throws JavaModelException { + this.workingCopy = getWorkingCopy("/Converter18/src/test399794/X.java", + true/* resolve */); + String contents = "package test399794;" + + "interface I {\n" + + " void foo(X x);\n" + + "}\n" + + "public class X {\n" + + " private void foo(X x) {\n" + + " }\n" + + " class Y {\n" + + " I i = X.this::foo;\n" + + " }\n" + + "}\n"; + + CompilationUnit cu = (CompilationUnit) buildAST(contents, this.workingCopy); + TypeDeclaration typeDeclaration = (TypeDeclaration) getASTNode(cu, 1); + typeDeclaration = typeDeclaration.getTypes()[0]; + FieldDeclaration field = typeDeclaration.getFields()[0]; + + VariableDeclarationFragment fragment = (VariableDeclarationFragment) field.fragments().get(0); + Expression expression = fragment.getInitializer(); + ExpressionMethodReference reference = (ExpressionMethodReference) expression; + IMethodBinding methodBinding = reference.resolveMethodBinding(); + assertNotNull(methodBinding); + assertEquals("Wrong name", "foo", methodBinding.getName()); + ITypeBinding [] parameterTypes = methodBinding.getParameterTypes(); + assertTrue("Incorrect Number of parameter type", parameterTypes.length == 1); + assertEquals("Incorrect parameter type", "X", parameterTypes[0].getName()); + } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=413942 // also refer https://bugs.eclipse.org/bugs/show_bug.cgi?id=413569 public void testBug413942() throws JavaModelException { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java index 4e6475292b..b2e589d566 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java @@ -38,7 +38,8 @@ public abstract class FunctionalExpression extends Expression { TypeBinding expectedType; public MethodBinding descriptor; - public MethodBinding binding; + public MethodBinding binding; // Code generation binding. May include synthetics. See getMethodBinding() + protected MethodBinding actualMethodBinding; // void of synthetics. boolean ignoreFurtherInvestigation; protected ExpressionContext expressionContext = VANILLA_CONTEXT; protected SimpleLookupTable resultExpressions; @@ -51,7 +52,10 @@ public abstract class FunctionalExpression extends Expression { public FunctionalExpression(CompilationResult compilationResult) { this.compilationResult = compilationResult; } - + // Return the actual (non-code generation) method binding that is void of synthetics. + public MethodBinding getMethodBinding() { + return null; + } public void setExpectedType(TypeBinding expectedType) { this.expectedType = this.ellipsisArgument ? ((ArrayBinding) expectedType).elementsType() : expectedType; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java index fcbd1d0bce..ffe9add2a6 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java @@ -49,6 +49,7 @@ import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding; +import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; @@ -783,6 +784,17 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC return this.outerLocalVariables[i]; return null; } + + // Return the actual method binding devoid of synthetics. + public MethodBinding getMethodBinding() { + if (this.actualMethodBinding == null) { + this.actualMethodBinding = new MethodBinding(this.binding.modifiers, this.binding.selector, this.binding.returnType, + this.binding instanceof SyntheticMethodBinding ? this.descriptor.parameters : this.binding.parameters, // retain any faults in parameter list. + this.binding.thrownExceptions, this.binding.declaringClass); + this.actualMethodBinding.tagBits = this.binding.tagBits; + } + return this.actualMethodBinding; + } } class IncongruentLambdaException extends RuntimeException { private static final long serialVersionUID = 4145723509219836114L; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java index 6dc9e6be58..b80d1b8bc5 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java @@ -81,6 +81,7 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat } public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { + this.actualMethodBinding = this.binding; // grab before synthetics come into play. SourceTypeBinding sourceType = currentScope.enclosingSourceType(); if (this.receiverType.isArrayType()) { if (isConstructorReference()) { @@ -637,4 +638,10 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat tSam = t.getSingleAbstractMethod(this.enclosingScope); return resultExpression.tIsMoreSpecific(tSam.returnType, sSam.returnType); } + + public org.eclipse.jdt.internal.compiler.lookup.MethodBinding getMethodBinding() { + if (this.actualMethodBinding == null) // array new/clone, no real binding. + this.actualMethodBinding = this.binding; + return this.actualMethodBinding; + } } diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java index e1e37e880e..062758cd3e 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java @@ -883,7 +883,7 @@ class DefaultBindingResolver extends BindingResolver { Object oldNode = this.newAstToOldAst.get(lambda); if (oldNode instanceof org.eclipse.jdt.internal.compiler.ast.LambdaExpression) { org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambdaExpression = (org.eclipse.jdt.internal.compiler.ast.LambdaExpression) oldNode; - IMethodBinding methodBinding = getMethodBinding(lambdaExpression.binding); + IMethodBinding methodBinding = getMethodBinding(lambdaExpression.getMethodBinding()); if (methodBinding == null) { return null; } @@ -934,7 +934,7 @@ class DefaultBindingResolver extends BindingResolver { Object oldNode = this.newAstToOldAst.get(methodReference); if (oldNode instanceof org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) { org.eclipse.jdt.internal.compiler.ast.ReferenceExpression referenceExpression = (org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) oldNode; - IMethodBinding methodBinding = getMethodBinding(referenceExpression.binding); + IMethodBinding methodBinding = getMethodBinding(referenceExpression.getMethodBinding()); if (methodBinding == null) { return null; } @@ -1166,7 +1166,7 @@ class DefaultBindingResolver extends BindingResolver { return method.getReturnType(); } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) { org.eclipse.jdt.internal.compiler.ast.ReferenceExpression referenceExpression = (org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) node; - IMethodBinding method = getMethodBinding(referenceExpression.binding); + IMethodBinding method = getMethodBinding(referenceExpression.getMethodBinding()); if (method == null) return null; return method.getReturnType(); } @@ -1431,7 +1431,7 @@ class DefaultBindingResolver extends BindingResolver { return getMethodBinding(memberValuePair.binding); } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) { org.eclipse.jdt.internal.compiler.ast.ReferenceExpression referenceExpression = (org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) node; - return getMethodBinding(referenceExpression.binding); + return getMethodBinding(referenceExpression.getMethodBinding()); } return null; } |
