diff options
author | Stephan Herrmann | 2016-06-04 20:41:32 +0000 |
---|---|---|
committer | Stephan Herrmann | 2016-06-05 00:04:33 +0000 |
commit | ca85fc25b968cc407c8b7e2ebf75044c0a42107d (patch) | |
tree | 5cf0ee4a18640207062c11859d2e9fadc96cc99c | |
parent | c45a87ae53eb97cc7def646c521a55cacc3dae49 (diff) | |
download | org.eclipse.objectteams-ca85fc25b968cc407c8b7e2ebf75044c0a42107d.tar.gz org.eclipse.objectteams-ca85fc25b968cc407c8b7e2ebf75044c0a42107d.tar.xz org.eclipse.objectteams-ca85fc25b968cc407c8b7e2ebf75044c0a42107d.zip |
Bug 444231: Copyinheritance of method with parameter annotations causes
AIOOBE
- fix NPE when reporting ambiguous role ctor
- copy null annotations to copied methods (copyInh. & creationMethods)
7 files changed, 111 insertions, 14 deletions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java index 6882cdbc7..3a8231a07 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java @@ -3267,12 +3267,23 @@ public MethodBinding resolveGeneratedMethod(MethodBinding mb) { * Create and link binding for a generated method. * @param methodDeclaration * @param wasSynthetic - * @param copyInheritanceSrc + * @param original copyInheritanceSource or original ctor + * @param isCopyInheritance whether or not original is copyInheritanceSource */ -public void resolveGeneratedMethod(AbstractMethodDeclaration methodDeclaration, boolean wasSynthetic, MethodBinding copyInheritanceSrc) { +public void resolveGeneratedMethod(AbstractMethodDeclaration methodDeclaration, boolean wasSynthetic, MethodBinding original, boolean isCopyInheritance) { if (this.scope != null) { MethodBinding binding = this.scope.createMethod(methodDeclaration); - binding.setCopyInheritanceSrc(copyInheritanceSrc); + if (isCopyInheritance) + binding.setCopyInheritanceSrc(original); + if (original != null && original.parameterNonNullness != null && methodDeclaration.arguments != null) { + int len = Math.min(methodDeclaration.arguments.length, original.parameterNonNullness.length); + AstGenerator gen = new AstGenerator(methodDeclaration); + for (int i=0; i<len; i++) { + Boolean nonNull = original.parameterNonNullness[i]; + if (nonNull != null) + gen.addNullAnnotation(methodDeclaration.arguments[i], this.scope.environment(), nonNull); + } + } } else { // in STATE_FINAL we can only fake this method: // (this way, dependent classes can already be fully translated). @@ -3284,7 +3295,7 @@ public void resolveGeneratedMethod(AbstractMethodDeclaration methodDeclaration, methodDeclaration.selector, null, null, null, this); - binding.setCopyInheritanceSrc(copyInheritanceSrc); + binding.setCopyInheritanceSrc(original); methodDeclaration.binding = binding; resolveTypesFor(binding); return; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java index 3dc613f23..fb72c1b15 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java @@ -4476,6 +4476,7 @@ public void invalidMethod(MessageSend messageSend, MethodBinding method, Scope s } else { ProblemMethodBinding problemMethod = new ProblemMethodBinding( constructor, selector, constructor.parameters, method.problemId()); + problemMethod.declaringClass = declaringClass; invalidConstructor(messageSend, problemMethod); } return; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java index 99db29058..f07347c51 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java @@ -1086,7 +1086,7 @@ public class CallinImplementorDyn extends MethodMappingImplementor { decl.hasParsedStatements = true; if (teamMethods != null && idxOfExisting > -1) { teamMethods[idxOfExisting] = decl; // directly replace - teamDecl.binding.resolveGeneratedMethod(decl, false, null); + teamDecl.binding.resolveGeneratedMethod(decl, false, null, false); } else { AstEdit.addMethod(teamDecl, decl); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java index 5475a1278..f5636e8d8 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java @@ -1006,7 +1006,7 @@ public class CopyInheritance implements IOTConstants, ClassFileConstants, ExtraC // it would invoke the wrong super(). ConstructorDeclaration ctor = targetRoleDecl.createDefaultConstructor(true, true); - targetRoleDecl.binding.resolveGeneratedMethod(ctor, false, origin); + targetRoleDecl.binding.resolveGeneratedMethod(ctor, false, origin, true); return; } else if (targetRoleDecl.getRoleModel()._refinesExtends) @@ -1119,7 +1119,7 @@ public class CopyInheritance implements IOTConstants, ClassFileConstants, ExtraC } } - AstEdit.addMethod(targetRoleDecl, newMethodDecl, wasSynthetic, false/*addToFront*/, origin); + AstEdit.addMethod(targetRoleDecl, newMethodDecl, wasSynthetic, false/*addToFront*/, origin, true); } if (method.isPrivate()) { newMethodDecl.binding.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; // don't warn unused copied method @@ -1507,6 +1507,7 @@ public class CopyInheritance implements IOTConstants, ClassFileConstants, ExtraC MethodDeclaration newMethod = internalCreateCreationMethod( teamDeclaration, roleModel, + constructorBinding, modifiers, newArguments, exceptions, @@ -1546,6 +1547,7 @@ public class CopyInheritance implements IOTConstants, ClassFileConstants, ExtraC private static MethodDeclaration internalCreateCreationMethod( TypeDeclaration teamDeclaration, RoleModel roleModel, + MethodBinding constructor, int ctorModifiers, Argument[] newArguments, TypeReference[] thrownExceptions, @@ -1623,7 +1625,7 @@ public class CopyInheritance implements IOTConstants, ClassFileConstants, ExtraC } newMethod.isGenerated = true; - AstEdit.addMethod(teamDeclaration, newMethod); + AstEdit.addMethod(teamDeclaration, newMethod, false, false, constructor, false); return newMethod; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstEdit.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstEdit.java index b75b50cde..7f7bf7987 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstEdit.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstEdit.java @@ -10,7 +10,6 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * $Id: AstEdit.java 23416 2010-02-03 19:59:31Z stephan $ * * Please visit http://www.eclipse.org/objectteams for updates and contact. * @@ -175,6 +174,15 @@ public class AstEdit { } addMethod(classTypeDeclaration, methodDeclaration); } + public static void addMethod( + TypeDeclaration classTypeDeclaration, + AbstractMethodDeclaration methodDeclaration, + boolean wasSynthetic, + boolean addToFront, + MethodBinding copyInheritanceSrc) + { + addMethod(classTypeDeclaration, methodDeclaration, wasSynthetic, addToFront, copyInheritanceSrc, true); + } /** * Adds a new Method to TypeDeclaration and resolve its types. * @@ -182,18 +190,20 @@ public class AstEdit { * @param methodDeclaration * @param wasSynthetic was the method copied from a synthetic method? * @param addToFront should the method be added to the front of 'methods'? - * @param copyInheritanceSrc tsuper method from which this method is copied + * @param original tsuper method or original ctor from which this method is copied + * @param isCopyInheritance */ public static void addMethod( TypeDeclaration classTypeDeclaration, AbstractMethodDeclaration methodDeclaration, boolean wasSynthetic, boolean addToFront, - MethodBinding copyInheritanceSrc) + MethodBinding original, + boolean isCopyInheritance) { boolean modifiersAdjusted = addMethodDeclOnly(classTypeDeclaration, methodDeclaration, addToFront); if (classTypeDeclaration.binding != null) { - classTypeDeclaration.binding.resolveGeneratedMethod(methodDeclaration, wasSynthetic, copyInheritanceSrc); + classTypeDeclaration.binding.resolveGeneratedMethod(methodDeclaration, wasSynthetic, original, isCopyInheritance); if (modifiersAdjusted) methodDeclaration.binding.tagBits |= TagBits.ClearPrivateModifier; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java index 791882a30..418ea1f15 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java @@ -1492,14 +1492,19 @@ public class AstGenerator extends AstFactory { } public void addNonNullAnnotation(Argument argument, LookupEnvironment environment) { + addNullAnnotation(argument, environment, true); + } + + public void addNullAnnotation(Argument argument, LookupEnvironment environment, boolean nonNull) { CompilerOptions compilerOptions = environment.globalOptions; if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) { + char[][] annotationName = nonNull ? environment.getNonNullAnnotationName() : environment.getNullableAnnotationName(); if (compilerOptions.sourceLevel < ClassFileConstants.JDK1_8) { - argument.annotations = new Annotation[]{ markerAnnotation(environment.getNonNullAnnotationName()) }; + argument.annotations = new Annotation[]{ markerAnnotation(annotationName) }; } else { int levels = argument.type.getAnnotatableLevels(); argument.type.annotations = new Annotation[levels][]; - argument.type.annotations[levels-1] = new Annotation[] { markerAnnotation(environment.getNonNullAnnotationName()) }; + argument.type.annotations[levels-1] = new Annotation[] { markerAnnotation(annotationName) }; } } } diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/OTNullAnnotationTest.java b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/OTNullAnnotationTest.java index eed4b20aa..8430dcb1b 100644 --- a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/OTNullAnnotationTest.java +++ b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/OTNullAnnotationTest.java @@ -17,6 +17,7 @@ package org.eclipse.objectteams.otdt.tests.otjld.other; import junit.framework.Test; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.objectteams.otdt.tests.otjld.AbstractOTJLDNullAnnotationTest; public class OTNullAnnotationTest extends AbstractOTJLDNullAnnotationTest { @@ -68,4 +69,71 @@ public class OTNullAnnotationTest extends AbstractOTJLDNullAnnotationTest { "Null type mismatch: required \'@NonNull MyBase\' but the provided value is null\n" + "----------\n"); } + + public void testBug444231() { + if (this.complianceLevel >= ClassFileConstants.JDK1_8) return; // not ready for type annotations, yet + runNegativeTestWithLibs( + new String[] { + "b/Base444231.java", + "package b;\n" + + "public class Base444231 {}\n", + "p/Team444231Super.java", + "package p;\n" + + "import org.eclipse.jdt.annotation.*;\n" + + "import base b.Base444231;\n" + + "public team class Team444231Super {\n" + + " protected class R playedBy Base444231 {\n" + + " protected R(@NonNull String s) { base(); }\n" + + " }\n" + + "}\n", + "p/Team444231Sub.java", + "package p;\n" + + "public team class Team444231Sub extends Team444231Super {\n" + + " void test() {\n" + + " String val = null;\n" + + " new R(val);\n" + + " }\n" + + "}\n" + }, + getCompilerOptions(), + "----------\n" + + "1. ERROR in p\\Team444231SubSub.java (at line 6)\n" + + " new R(val);\n" + + " ^^^\n" + + "Null type mismatch: required '@NonNull String' but the provided value is null\n" + + "----------\n"); + } + + public void testBug444231_ambiguous() { + if (this.complianceLevel >= ClassFileConstants.JDK1_8) return; // not ready for type annotations, yet + runNegativeTestWithLibs( + new String[] { + "b/Base444231.java", + "package b;\n" + + "public class Base444231 {}\n", + "p/Team444231Super.java", + "package p;\n" + + "import org.eclipse.jdt.annotation.*;\n" + + "import base b.Base444231;\n" + + "public team class Team444231Super {\n" + + " protected class R playedBy Base444231 {\n" + + " protected R(@NonNull String s) { base(); }\n" + + " }\n" + + "}\n", + "p/Team444231Sub.java", + "package p;\n" + + "public team class Team444231Sub extends Team444231Super {\n" + + " void test() {\n" + + " new R(null);\n" + + " }\n" + + "}\n" + }, + getCompilerOptions(), + "----------\n" + + "1. ERROR in p\\Team444231Sub.java (at line 4)\n" + + " new R(null);\n" + + " ^^^^^^^^^^^\n" + + "The constructor Team444231Sub.R(null) is ambiguous\n" + + "----------\n"); + } } |