diff options
author | Jayaprakash Arthanareeswaran | 2013-03-25 08:29:04 +0000 |
---|---|---|
committer | Jayaprakash Arthanareeswaran | 2013-04-02 08:13:39 +0000 |
commit | 29530aea390a72e4225d01267051bcdef2bb5cd8 (patch) | |
tree | f7b86d45fcd6ab0079c66437a25e0a6a27632d1a | |
parent | f28c28de6ed3d2e9e475bca36caf25c219a92533 (diff) | |
download | eclipse.jdt.core-29530aea390a72e4225d01267051bcdef2bb5cd8.tar.gz eclipse.jdt.core-29530aea390a72e4225d01267051bcdef2bb5cd8.tar.xz eclipse.jdt.core-29530aea390a72e4225d01267051bcdef2bb5cd8.zip |
Fix for bug 399791 - [1.8][dom ast] AST APIs should support code carrying
interfaces (static & default methods)
7 files changed, 163 insertions, 17 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter17Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter17Test.java index f10ba2479a..fdd9dbd6ea 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter17Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter17Test.java @@ -941,4 +941,26 @@ public class ASTConverter17Test extends ConverterTestSetup { binding = expression.resolveTypeBinding(); assertNull(binding); } + /* + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=399791 + */ + public void test0021() throws JavaModelException { + String contents = + "public interface X {\n" + + " static void foo(){}\n" + + " default void foo(int i){}\n" + + "}\n"; + this.workingCopy = getWorkingCopy("/Converter17/src/X.java", false); + ASTNode node = buildAST(contents, this.workingCopy, false); + assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType()); + CompilationUnit unit = (CompilationUnit) node; + TypeDeclaration type = (TypeDeclaration) unit.types().get(0); + node = (ASTNode) type.bodyDeclarations().get(0); + assertEquals("Not a method Declaration", ASTNode.METHOD_DECLARATION, node.getNodeType()); + MethodDeclaration method = (MethodDeclaration) node; + assertEquals("Method should be malformed", ASTNode.MALFORMED, (method.getFlags() & ASTNode.MALFORMED)); + + method = (MethodDeclaration) type.bodyDeclarations().get(1); + assertEquals("Method should be malformed", ASTNode.MALFORMED, (method.getFlags() & ASTNode.MALFORMED)); + } } 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 f31b3ef33e..140b56bd57 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 @@ -1896,5 +1896,43 @@ public class ASTConverter18Test extends ConverterTestSetup { assertNotNull(binding); assertEquals("ReduceInt", binding.getName()); } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=399791 + public void testBug399791() throws JavaModelException { + String contents = + "public interface X {\n" + + " static void foo(){}\n" + + " public default void foo(int i){}\n" + + " native void foo(float f){}\n" + + " abstract void foo(long l){}\n" + + "}\n"; + this.workingCopy = getWorkingCopy("/Converter18/src/X.java", false); + ASTNode node = buildAST(contents, this.workingCopy, false); + assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType()); + CompilationUnit unit = (CompilationUnit) node; + TypeDeclaration type = (TypeDeclaration) unit.types().get(0); + node = (ASTNode) type.bodyDeclarations().get(0); + assertEquals("Not a method Declaration", ASTNode.METHOD_DECLARATION, node.getNodeType()); + MethodDeclaration method = (MethodDeclaration) node; + assertEquals("Method should not be malformed", 0, (method.getFlags() & ASTNode.MALFORMED)); + List modifiers = method.modifiers(); + assertEquals("Incorrect no of modfiers", 1, modifiers.size()); + Modifier modifier = (Modifier) modifiers.get(0); + assertSame("Incorrect modifier keyword", Modifier.ModifierKeyword.STATIC_KEYWORD, modifier.getKeyword()); + + method = (MethodDeclaration) type.bodyDeclarations().get(1); + assertEquals("Method should not be malformed", 0, (method.getFlags() & ASTNode.MALFORMED)); + modifiers = method.modifiers(); + assertEquals("Incorrect no of modfiers", 2, modifiers.size()); + modifier = (Modifier) modifiers.get(1); + assertSame("Incorrect modifier keyword", Modifier.ModifierKeyword.DEFAULT_KEYWORD, modifier.getKeyword()); + assertTrue("Incorrect modifier", modifier.isDefaultMethod()); + assertEquals("Incorrect AST", "public default void foo(int i){\n}\n", method.toString()); + + method = (MethodDeclaration) type.bodyDeclarations().get(2); + assertEquals("Method should be malformed", ASTNode.MALFORMED, (method.getFlags() & ASTNode.MALFORMED)); + + method = (MethodDeclaration) type.bodyDeclarations().get(3); + assertEquals("Method should be malformed", ASTNode.MALFORMED, (method.getFlags() & ASTNode.MALFORMED)); + } } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java index 2f353d40cc..1c3407ebbe 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java @@ -5601,7 +5601,8 @@ public class ASTTest extends org.eclipse.jdt.core.tests.junit.extension.TestCase this.ast.newModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD), this.ast.newModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD), this.ast.newModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD), - this.ast.newModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD) + this.ast.newModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD), + this.ast.newModifier(Modifier.ModifierKeyword.DEFAULT_KEYWORD) }; return allMods; } @@ -8517,6 +8518,7 @@ public class ASTTest extends org.eclipse.jdt.core.tests.junit.extension.TestCase assertTrue(Modifier.ModifierKeyword.TRANSIENT_KEYWORD.toString().equals("transient")); //$NON-NLS-1$ assertTrue(Modifier.ModifierKeyword.VOLATILE_KEYWORD.toString().equals("volatile")); //$NON-NLS-1$ assertTrue(Modifier.ModifierKeyword.STRICTFP_KEYWORD.toString().equals("strictfp")); //$NON-NLS-1$ + assertTrue(Modifier.ModifierKeyword.DEFAULT_KEYWORD.toString().equals("default")); //$NON-NLS-1$ final Modifier.ModifierKeyword[] known = { Modifier.ModifierKeyword.PUBLIC_KEYWORD, @@ -8530,6 +8532,7 @@ public class ASTTest extends org.eclipse.jdt.core.tests.junit.extension.TestCase Modifier.ModifierKeyword.TRANSIENT_KEYWORD, Modifier.ModifierKeyword.VOLATILE_KEYWORD, Modifier.ModifierKeyword.STRICTFP_KEYWORD, + Modifier.ModifierKeyword.DEFAULT_KEYWORD }; // check all modifiers are distinct diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java index f3a96929a6..87bf4e52be 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java @@ -1759,7 +1759,7 @@ public final class AST { * for the given modifier flags. When multiple modifiers are * requested the modifiers nodes will appear in the following order: * public, protected, private, abstract, static, final, synchronized, - * native, strictfp, transient, volatile. This order is consistent + * native, strictfp, transient, volatile, default. This order is consistent * with the recommendations in JLS2 8.1.1, 8.3.1, and 8.4.3. * * @param flags bitwise or of modifier flags declared on {@link Modifier} @@ -1807,6 +1807,9 @@ public final class AST { if (Modifier.isVolatile(flags)) { result.add(newModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD)); } + if (Modifier.isDefaultMethod(flags)) { + result.add(newModifier(Modifier.ModifierKeyword.DEFAULT_KEYWORD)); + } return result; } diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java index 7db0343d89..df439873ab 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java @@ -611,11 +611,12 @@ class ASTConverter { } } } - if (block != null - && (Modifier.isAbstract(methodDecl.getModifiers()) - || Modifier.isNative(methodDecl.getModifiers()) - || isInterface)) { - methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED); + if (block != null) { + if ((methodDeclaration.modifiers & (ClassFileConstants.AccAbstract | ClassFileConstants.AccNative)) != 0 + || (isInterface && (this.ast.apiLevel < AST.JLS8 || + (methodDeclaration.modifiers & (ClassFileConstants.AccStatic | ExtraCompilerModifiers.AccDefaultMethod)) == 0))) { + methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED); + } } } else { // syntax error in this method declaration @@ -4843,6 +4844,9 @@ class ASTConverter { case TerminalTokens.TokenNamestrictfp: modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD); break; + case TerminalTokens.TokenNamedefault: + modifier = createModifier(Modifier.ModifierKeyword.DEFAULT_KEYWORD); + break; case TerminalTokens.TokenNameAT : // we have an annotation if (annotations != null && indexInAnnotations < annotations.length) { diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java index 63fbeb0a8d..4ddcab27a4 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java @@ -1,10 +1,14 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * 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 * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -31,12 +35,14 @@ import java.util.Map; * <b>transient</b> * <b>volatile</b> * <b>strictfp</b> + * <b>default</b> * </pre> * <p> * The numeric values of these flags match the ones for class - * files as described in the Java Virtual Machine Specification. - * Note that Java model class {@link org.eclipse.jdt.core.Flags} also - * provides the same constants as this class. + * files as described in the Java Virtual Machine Specification + * (except for {@link #DEFAULT}). Note that Java model class + * {@link org.eclipse.jdt.core.Flags} also provides the same + * constants as this class. * </p> * * @since 2.0 @@ -88,6 +94,14 @@ public final class Modifier extends ASTNode implements IExtendedModifier { /** "volatile" modifier with flag value {@link Modifier#VOLATILE}. */ public static final ModifierKeyword VOLATILE_KEYWORD = new ModifierKeyword("volatile", VOLATILE);//$NON-NLS-1$ + + /** + * "default" modifier with flag value {@link Modifier#DEFAULT}. Note that the value of the modifier is + * internal and is not specified in the Java Virtual Machine Specification. + * @since 3.9 + */ + public static final ModifierKeyword DEFAULT_KEYWORD = new ModifierKeyword("default", DEFAULT);//$NON-NLS-1$ + static { KEYWORDS = new HashMap(20); ModifierKeyword[] ops = { @@ -101,7 +115,8 @@ public final class Modifier extends ASTNode implements IExtendedModifier { SYNCHRONIZED_KEYWORD, TRANSIENT_KEYWORD, VOLATILE_KEYWORD, - STRICTFP_KEYWORD + STRICTFP_KEYWORD, + DEFAULT_KEYWORD }; for (int i = 0; i < ops.length; i++) { KEYWORDS.put(ops[i].toString(), ops[i]); @@ -292,6 +307,16 @@ public final class Modifier extends ASTNode implements IExtendedModifier { */ public static final int VOLATILE = 0x0040; + /** + * "default" modifier constant (bit mask). + * Applicable only to methods. + * + * Note that the value of the flag is internal and is not + * specified in the Java Virtual Machine Specification. + * @since 3.9 + */ + public static final int DEFAULT = 0x10000; + static { List properyList = new ArrayList(2); createPropertyList(Modifier.class, properyList); @@ -443,6 +468,19 @@ public final class Modifier extends ASTNode implements IExtendedModifier { } /** + * Returns whether the given flags includes the "default" modifier. + * Applicable only to methods. + * + * @param flags the modifier flags + * @return <code>true</code> if the <code>DEFAULT</code> bit is set + * and <code>false</code> otherwise + * @since 3.9 + */ + public static boolean isDefaultMethod(int flags) { + return (flags & DEFAULT) != 0; + } + + /** * Returns a list of structural property descriptors for this node type. * Clients must not modify the result. * @@ -663,6 +701,15 @@ public final class Modifier extends ASTNode implements IExtendedModifier { return this.modifierKeyword == ModifierKeyword.VOLATILE_KEYWORD; } + /** + * Answer true if the receiver is the default modifier, false otherwise. + * @return true if the receiver is the default modifier, false otherwise + * @since 3.9 + */ + public boolean isDefaultMethod() { + return this.modifierKeyword == ModifierKeyword.DEFAULT_KEYWORD; + } + /* (omit javadoc for this method) * Method declared on ASTNode. * @since 3.0 diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java index 16a7e86482..0992bd779c 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java @@ -1,10 +1,14 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * 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 * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * IBM Corporation - initial API and implementation * IBM Corporation - added constant AccDefault @@ -13,6 +17,7 @@ package org.eclipse.jdt.core; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; /** * Utility class for decoding modifier flags in Java elements. @@ -21,9 +26,10 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; * </p> * <p> * Note that the numeric values of these flags match the ones for class files - * as described in the Java Virtual Machine Specification. The AST class - * <code>Modifier</code> provides the same functionality as this class, only in - * the <code>org.eclipse.jdt.core.dom</code> package. + * as described in the Java Virtual Machine Specification (except for + * {@link #AccDefaultFlag}). The AST class <code>Modifier</code> provides + * the same functionality as this class, only in the + * <code>org.eclipse.jdt.core.dom</code> package. * </p> * * @see IMember#getFlags() @@ -143,6 +149,14 @@ public final class Flags { public static final int AccAnnotation = ClassFileConstants.AccAnnotation; /** + * Default property flag (added in J2SE 1.8). + * Note that the flag's value is internal and is not defined in the + * Virtual Machine specification. + * @since 3.9 + */ + public static final int AccDefaultFlag = ExtraCompilerModifiers.AccDefaultMethod; + + /** * Not instantiable. */ private Flags() { @@ -352,6 +366,19 @@ public final class Flags { } /** + * Returns whether the given integer has the <code>AccDefaultFlag</code> + * bit set. Note that this flag represents the usage of the 'default' keyword + * on a method and should not be confused with the default access visibility. + * + * @return <code>true</code> if the <code>AccDefaultFlag</code> flag is included + * @see #AccDefaultFlag + * @since 3.9 + */ + public static boolean isDefaultMethod(int flags) { + return (flags & AccDefaultFlag) != 0; + } + + /** * Returns a standard string describing the given modifier flags. * Only modifier flags are included in the output; deprecated, * synthetic, bridge, etc. flags are ignored. @@ -361,6 +388,7 @@ public final class Flags { * <code>public</code> <code>protected</code> <code>private</code> * <code>static</code> * <code>abstract</code> <code>final</code> <code>native</code> <code>synchronized</code> <code>transient</code> <code>volatile</code> <code>strictfp</code> + * <code>default</code> * </pre> * This is a compromise between the orders specified in sections 8.1.1, * 8.3.1, 8.4.3, 8.8.3, 9.1.1, and 9.3 of <em>The Java Language @@ -412,7 +440,8 @@ public final class Flags { sb.append("volatile "); //$NON-NLS-1$ if (isStrictfp(flags)) sb.append("strictfp "); //$NON-NLS-1$ - + if (isDefaultMethod(flags)) + sb.append("default "); //$NON-NLS-1$ int len = sb.length(); if (len == 0) return ""; //$NON-NLS-1$ |