### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core.tests.model Index: src/org/eclipse/jdt/core/tests/model/SignatureTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SignatureTests.java,v retrieving revision 1.42 diff -u -r1.42 SignatureTests.java --- src/org/eclipse/jdt/core/tests/model/SignatureTests.java 17 Jul 2006 11:22:07 -0000 1.42 +++ src/org/eclipse/jdt/core/tests/model/SignatureTests.java 26 Oct 2006 14:26:49 -0000 @@ -505,6 +505,21 @@ } /** + * @bug 155003: [model] Missing exception types / wrong signature? + * @test Ensure that thrown exceptions are well decoded when added at the end of the signature + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=155003" + */ +public void testGetThrownExceptions_Bug155003() throws JavaModelException { + String methodSig = "()Ljava.lang.Object;^Ljava.lang.InstantiationException;^Ljava.lang.IllegalAccessException;"; + assertStringsEqual("Signature#Bug155003#1 is not correct", + "Ljava.lang.InstantiationException;\nLjava.lang.IllegalAccessException;\n", + Signature.getThrownExceptionTypes(methodSig)); + methodSig = "()V"; // no change when no thrown exceptions + assertStringsEqual("Signature#Bug155003#2 is not correct", + "", + Signature.getThrownExceptionTypes(methodSig)); +} +/** * @see Signature * @since 3.0 */ Index: src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java,v retrieving revision 1.216 diff -u -r1.216 ASTConverter15Test.java --- src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java 24 Oct 2006 03:10:39 -0000 1.216 +++ src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java 26 Oct 2006 14:26:48 -0000 @@ -7321,4 +7321,81 @@ assertTrue("Not assignement compatible", typeBinding.isAssignmentCompatible(typeBinding2)); assertTrue("Not assignement compatible", typeBinding.isAssignmentCompatible(collectionTypeBinding)); } + + /** + * @bug 155003: [model] Missing exception types / wrong signature? + * @test Ensure that thrown exceptions are added in method unique key (not in signature) + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=155003" + */ + public void testBug155003() throws CoreException { + workingCopies = new ICompilationUnit[1]; + workingCopies[0] = getWorkingCopy("/Converter15/src/Test.java", + "public class Test {\n" + + " public void foo() throws InstantiationException, IllegalAccessException {\n" + + " }\n" + + " void test() throws InstantiationException, IllegalAccessException {\n" + + " foo();\n" + + " }\n" + + "}", + true // compute problems => resolve bindings + ); + + // Get 'test' method statements + CompilationUnit unit = (CompilationUnit) buildAST(this.workingCopies[0]); + ASTNode method = getASTNode(unit, 0, 1); + assertEquals("Expecting method", method.getNodeType(), ASTNode.METHOD_DECLARATION); + MethodDeclaration bar = (MethodDeclaration) method; + Block body = bar.getBody(); + List statements = body.statements(); + + // Verify statement binding + ASTNode node = (ASTNode) statements.get(0); + assertEquals("Expecting expression statement", node.getNodeType(), ASTNode.EXPRESSION_STATEMENT); + assertBindingEquals( + "LTest;.foo()V^Ljava/lang/InstantiationException;^Ljava/lang/IllegalAccessException;", + resolveBinding(((ExpressionStatement)node).getExpression()) + ); + } + public void testBug155003_Generic() throws CoreException { + workingCopies = new ICompilationUnit[1]; + workingCopies[0] = getWorkingCopy("/Converter15/src/X.java", + "public class X {\n" + + " X foo(X x) throws RuntimeException, U {\n" + + " return null;\n" + + " }\n" + + " V bar(K key, V value) throws Exception {\n" + + " return value;\n" + + " }\n" + + " void test() throws Exception {\n" + + " foo(this);\n" + + " bar(\"\", \"\");\n" + + " }\n" + + "}\n", + true // compute problems => resolve bindings + ); + + // Get 'test' method statements + CompilationUnit unit = (CompilationUnit) buildAST(this.workingCopies[0]); + ASTNode method = getASTNode(unit, 0, 2); + assertEquals("Expecting method", method.getNodeType(), ASTNode.METHOD_DECLARATION); + MethodDeclaration bar = (MethodDeclaration) method; + Block body = bar.getBody(); + List statements = body.statements(); + + // Verify first statement binding + ASTNode node = (ASTNode) statements.get(0); + assertEquals("Expecting expression statement", node.getNodeType(), ASTNode.EXPRESSION_STATEMENT); + assertBindingEquals( + "LX;.foo(LX;)LX;^Ljava/lang/RuntimeException;^TU;%", + resolveBinding(((ExpressionStatement)node).getExpression()) + ); + + // Verify second statement binding + node = (ASTNode) statements.get(1); + assertEquals("Expecting expression statement", node.getNodeType(), ASTNode.EXPRESSION_STATEMENT); + assertBindingEquals( + "LX;.bar(TK;TV;)TV;^Ljava/lang/Exception;%", + resolveBinding(((ExpressionStatement)node).getExpression()) + ); + } } \ No newline at end of file #P org.eclipse.jdt.core Index: model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java,v retrieving revision 1.24 diff -u -r1.24 BindingKeyParser.java --- model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java 8 Dec 2005 11:45:12 -0000 1.24 +++ model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java 26 Oct 2006 14:26:51 -0000 @@ -53,6 +53,10 @@ && this.source[this.index] == '!'; } + boolean isAtEnd() { + return this.index >= this.source.length; + } + boolean isAtFieldOrMethodStart() { return this.index < this.source.length @@ -116,7 +120,7 @@ return this.index < this.source.length && "LIZVCDBFJS[!".indexOf(this.source[this.index]) != -1; //$NON-NLS-1$ } - boolean isAtFlagsStart() { + boolean isAtThrownStart() { return this.index < this.source.length && this.source[this.index] == '^'; @@ -325,6 +329,11 @@ } } + void skipThrownStart() { + while (this.index < this.source.length && this.source[this.index] == '^') + this.index++; + } + void skipParametersStart() { while (this.index < this.source.length && (this.source[this.index] == '<' || this.source[this.index] == '%')) this.index++; @@ -429,6 +438,10 @@ // default is to do nothing } + public void consumeException() { + // default is to do nothing + } + public void consumeField(char[] fieldName) { // default is to do nothing } @@ -579,7 +592,6 @@ consumeType(); this.scanner.skipTypeEnd(); - parseFlags(); if (this.scanner.isAtFieldOrMethodStart()) { switch (this.scanner.nextToken()) { @@ -704,7 +716,6 @@ parseLocalVariable(); } else { consumeLocalVar(varName); - parseFlags(); } } @@ -713,7 +724,7 @@ this.scanner.skipMethodSignature(); char[] signature = this.scanner.getTokenSource(); consumeMethod(selector, signature); - parseFlags(); + parseThrownExceptions(); if (this.scanner.isAtParametersStart()) parseParameterizedMethod(); } @@ -743,9 +754,14 @@ consumeField(fieldName); } - private void parseFlags() { - if (!this.scanner.isAtFlagsStart() || this.scanner.nextToken() != Scanner.FLAGS) return; - consumeModifiers(this.scanner.getTokenSource()); + private void parseThrownExceptions() { + while (this.scanner.isAtThrownStart()) { + this.scanner.skipThrownStart(); + consumeException(); + parseFullyQualifiedName(); + consumeType(); + this.scanner.skipTypeEnd(); + } } private void parseParameterizedType(char[] typeName, boolean isRaw) { @@ -758,7 +774,6 @@ this.scanner.skipParametersEnd(); consumeParameterizedType(typeName, isRaw); this.scanner.skipTypeEnd(); - parseFlags(); if (this.scanner.isAtMemberTypeStart() && this.scanner.nextToken() == Scanner.TYPE) { typeName = this.scanner.getTokenSource(); if (this.scanner.isAtParametersStart()) { @@ -773,7 +788,6 @@ this.scanner.skipParametersEnd(); consumeRawType(); this.scanner.skipTypeEnd(); - parseFlags(); if (this.scanner.isAtMemberTypeStart() && this.scanner.nextToken() == Scanner.TYPE) { char[] typeName = this.scanner.getTokenSource(); if (this.scanner.isAtParametersStart()) { Index: model/org/eclipse/jdt/internal/core/util/KeyToSignature.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/KeyToSignature.java,v retrieving revision 1.23 diff -u -r1.23 KeyToSignature.java --- model/org/eclipse/jdt/internal/core/util/KeyToSignature.java 7 Jul 2005 10:44:03 -0000 1.23 +++ model/org/eclipse/jdt/internal/core/util/KeyToSignature.java 26 Oct 2006 14:26:51 -0000 @@ -198,6 +198,10 @@ } } + public void consumeException() { + this.signature.append('^'); + } + public void consumeFullyQualifiedName(char[] fullyQualifiedName) { this.typeSigStart = this.signature.length(); this.signature.append('L'); Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java,v retrieving revision 1.83 diff -u -r1.83 MethodBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java 25 Jun 2006 21:33:33 -0000 1.83 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java 26 Oct 2006 14:26:51 -0000 @@ -320,10 +320,26 @@ // generic signature char[] sig = genericSignature(); - if (sig == null) sig = signature(); + boolean isGeneric = sig != null; + if (!isGeneric) sig = signature(); int signatureLength = sig.length; - char[] uniqueKey = new char[declaringLength + 1 + selectorLength + signatureLength]; + // thrown exceptions + int thrownExceptionsLength = this.thrownExceptions.length; + int thrownExceptionsSignatureLength = 0; + char[][] thrownExceptionsSignatures = null; + boolean addThrownExceptions = thrownExceptionsLength > 0 && (!isGeneric || CharOperation.lastIndexOf('^', sig) < 0); + if (addThrownExceptions) { + thrownExceptionsSignatures = new char[thrownExceptionsLength][]; + for (int i = 0; i < thrownExceptionsLength; i++) { + if (this.thrownExceptions[i] != null) { + thrownExceptionsSignatures[i] = this.thrownExceptions[i].signature(); + thrownExceptionsSignatureLength += thrownExceptionsSignatures[i].length + 1; // add one char for separator + } + } + } + + char[] uniqueKey = new char[declaringLength + 1 + selectorLength + signatureLength + thrownExceptionsSignatureLength]; int index = 0; System.arraycopy(declaringKey, 0, uniqueKey, index, declaringLength); index = declaringLength; @@ -331,7 +347,19 @@ System.arraycopy(this.selector, 0, uniqueKey, index, selectorLength); index += selectorLength; System.arraycopy(sig, 0, uniqueKey, index, signatureLength); - //index += signatureLength; + if (thrownExceptionsSignatureLength > 0) { + index += signatureLength; + for (int i = 0; i < thrownExceptionsLength; i++) { + char[] thrownExceptionSignature = thrownExceptionsSignatures[i]; + if (thrownExceptionSignature != null) { + uniqueKey[index++] = '^'; + int length = thrownExceptionSignature.length; + System.arraycopy(thrownExceptionSignature, 0, uniqueKey, index, length); + index += length; + } + } + } + return uniqueKey; } /*