Extension methods aren't abstract

This commit is contained in:
Roman Shevchenko
2012-05-24 21:43:35 +04:00
parent 5a7dd97108
commit 3f4aca11bd
10 changed files with 112 additions and 112 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@ package com.intellij.psi.impl.cache;
* @author max
*/
public interface ModifierFlags {
// ---- The group equal to corresponding in ClsUtil.ACC_*
int PUBLIC_MASK = 0x0001;
int PRIVATE_MASK = 0x0002;
int PROTECTED_MASK = 0x0004;
@@ -31,9 +30,8 @@ public interface ModifierFlags {
int TRANSIENT_MASK = 0x0080;
int NATIVE_MASK = 0x0100;
int INTERFACE_MASK = 0x0200;
int DEFENDER_MASK = 0x0200;
int ABSTRACT_MASK = 0x0400;
// ---- End of the group equal to corresponding in ClsUtil.ACC_*
int STRICTFP_MASK = 0x0800;
int PACKAGE_LOCAL_MASK = 0x1000;
int DEPRECATED_MASK = 0x2000;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,12 +30,8 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.util.CharTable;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* @author max
@@ -123,7 +119,7 @@ public class RecordUtil {
else if (parent instanceof PsiMethodStub) {
if (grandParent instanceof PsiClassStub && ((PsiClassStub)grandParent).isInterface()) {
alreadyPublic = true;
alreadyAbstract = true;
alreadyAbstract = !((PsiMethodStub)parent).isDefender();
}
}
else if (parent instanceof PsiFieldStub) {
@@ -143,27 +139,37 @@ public class RecordUtil {
for (final LighterASTNode child : tree.getChildren(modList)) {
final IElementType type = child.getTokenType();
if(type == JavaTokenType.PUBLIC_KEYWORD) {
if (type == JavaTokenType.PUBLIC_KEYWORD) {
alreadyPublic = true;
} else if(type == JavaTokenType.PRIVATE_KEYWORD) {
}
else if (type == JavaTokenType.PRIVATE_KEYWORD) {
packed |= ModifierFlags.PRIVATE_MASK;
} else if(type == JavaTokenType.PROTECTED_KEYWORD) {
}
else if (type == JavaTokenType.PROTECTED_KEYWORD) {
packed |= ModifierFlags.PROTECTED_MASK;
} else if(type == JavaTokenType.ABSTRACT_KEYWORD) {
alreadyAbstract =true;
} else if (type == JavaTokenType.FINAL_KEYWORD) {
}
else if (type == JavaTokenType.ABSTRACT_KEYWORD) {
alreadyAbstract = true;
}
else if (type == JavaTokenType.FINAL_KEYWORD) {
alreadyFinal = true;
} else if (type == JavaTokenType.STATIC_KEYWORD) {
}
else if (type == JavaTokenType.STATIC_KEYWORD) {
alreadyStatic = true;
} else if(type == JavaTokenType.NATIVE_KEYWORD) {
}
else if (type == JavaTokenType.NATIVE_KEYWORD) {
packed |= ModifierFlags.NATIVE_MASK;
} else if (type == JavaTokenType.SYNCHRONIZED_KEYWORD) {
}
else if (type == JavaTokenType.SYNCHRONIZED_KEYWORD) {
packed |= ModifierFlags.SYNCHRONIZED_MASK;
} else if (type == JavaTokenType.TRANSIENT_KEYWORD) {
}
else if (type == JavaTokenType.TRANSIENT_KEYWORD) {
packed |= ModifierFlags.TRANSIENT_MASK;
} else if (type == JavaTokenType.VOLATILE_KEYWORD) {
}
else if (type == JavaTokenType.VOLATILE_KEYWORD) {
packed |= ModifierFlags.VOLATILE_MASK;
} else if (type == JavaTokenType.STRICTFP_KEYWORD) {
}
else if (type == JavaTokenType.STRICTFP_KEYWORD) {
packed |= ModifierFlags.STRICTFP_MASK;
}
}
@@ -175,8 +181,7 @@ public class RecordUtil {
if ((packed & ModifierFlags.PRIVATE_MASK) == 0 &&
(packed & ModifierFlags.PROTECTED_MASK) == 0 &&
(packed & ModifierFlags.PUBLIC_MASK) == 0
) {
(packed & ModifierFlags.PUBLIC_MASK) == 0) {
packed |= ModifierFlags.PACKAGE_LOCAL_MASK;
}
@@ -217,62 +222,6 @@ public class RecordUtil {
return (ourModifierNameToFlagMap.get(psiModifier) & packed) != 0;
}
@SuppressWarnings({"unchecked"})
private static final Set<String>[] SET_INSTANCES = new Set[8 * 4];
private static final String[] VISIBILITY_MODIFIERS = {null, PsiModifier.PUBLIC, PsiModifier.PRIVATE, PsiModifier.PROTECTED};
private static final int[] MODIFIER_MAP = {0, 1, 2, -1, 3, -1, -1, -1, -1};
static {
SET_INSTANCES[0] = Collections.emptySet();
for (int i = 1; i < 4; i++) {
SET_INSTANCES[i << 3] = Collections.singleton(VISIBILITY_MODIFIERS[i]);
}
for (int i = 1; i < 8; i++) {
int attr = i << 3;
Set<String> set = new LinkedHashSet<String>();
if ((attr & ModifierFlags.STATIC_MASK) != 0) set.add(PsiModifier.STATIC);
if ((attr & ModifierFlags.FINAL_MASK) != 0) set.add(PsiModifier.FINAL);
if ((attr & (4 << 3)) != 0) set.add(PsiModifier.ABSTRACT);
if (set.size() == 1) set = Collections.singleton(set.iterator().next());
SET_INSTANCES[i] = set;
for (int k = 1; k < 4; k++) {
Set<String> setWithModifier = new LinkedHashSet<String>();
setWithModifier.add(VISIBILITY_MODIFIERS[k]);
setWithModifier.addAll(set);
assert setWithModifier.size() > 1;
SET_INSTANCES[(k << 3) + i] = setWithModifier;
}
}
}
public static Set<String> getModifierSet(int modifiers) {
assert (modifiers & ~(ModifierFlags.PUBLIC_MASK | ModifierFlags.PRIVATE_MASK | ModifierFlags.PROTECTED_MASK |
ModifierFlags.FINAL_MASK | ModifierFlags.ABSTRACT_MASK | ModifierFlags.STATIC_MASK)) == 0;
int visibilityModifierIndex = MODIFIER_MAP[modifiers & 7];
int index = ((modifiers >>> 3) & 3) + ((modifiers & ModifierFlags.ABSTRACT_MASK) >>> 8);
if (visibilityModifierIndex != -1) {
return SET_INSTANCES[index + (visibilityModifierIndex << 3)];
}
Set<String> res = new LinkedHashSet<String>();
if ((modifiers & ModifierFlags.PUBLIC_MASK) != 0) res.add(PsiModifier.PUBLIC);
if ((modifiers & ModifierFlags.PRIVATE_MASK) != 0) res.add(PsiModifier.PRIVATE);
if ((modifiers & ModifierFlags.PROTECTED_MASK) != 0) res.add(PsiModifier.PROTECTED);
res.addAll(SET_INSTANCES[index]);
return res;
}
public static String intern(final CharTable table, final LighterASTNode node) {
assert node instanceof LighterASTTokenNode;
return table.intern(((LighterASTTokenNode)node).getText()).toString();
@@ -58,6 +58,10 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
public static final String FLOAT_NEGATIVE_INF = "-1.0f / 0.0";
public static final String FLOAT_NAN = "0.0f / 0.0";
@NonNls private static final String SYNTHETIC_CLASS_INIT_METHOD = "<clinit>";
@NonNls private static final String SYNTHETIC_INIT_METHOD = "<init>";
private static final int ACC_DEFENDER = Opcodes.ACC_INTERFACE; // todo[r.sh] use right constant once ASM gets Java 8 support
private final InnerClassSourceStrategy<T> myInnersStrategy;
private final StubElement myParent;
@@ -65,8 +69,6 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
private final T mySource;
private PsiModifierListStub myModList;
private PsiClassStub myResult;
@NonNls private static final String SYNTHETIC_CLINIT_METHOD = "<clinit>";
@NonNls private static final String SYNTHETIC_INIT_METHOD = "<init>";
private JavaLexer myLexer;
public StubBuildingVisitor(final T classSource, InnerClassSourceStrategy<T> innersStrategy, final StubElement parent, final int access) {
@@ -174,20 +176,25 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
return convertedSuper;
}
// for lexer, so need not to be precise
private static LanguageLevel convertFromVersion(final int version) {
if (version == Opcodes.V1_1 || version == Opcodes.V1_2 || version == Opcodes.V1_3) {
return LanguageLevel.JDK_1_3;
}
switch (version) {
case Opcodes.V1_1:
case Opcodes.V1_2:
case Opcodes.V1_3:
return LanguageLevel.JDK_1_3;
if (version == Opcodes.V1_4) {
return LanguageLevel.JDK_1_4;
}
case Opcodes.V1_4:
return LanguageLevel.JDK_1_4;
if (version == Opcodes.V1_5 || version == Opcodes.V1_6) {
return LanguageLevel.JDK_1_5;
}
case Opcodes.V1_5:
case Opcodes.V1_6:
case Opcodes.V1_7:
return LanguageLevel.JDK_1_5;
return LanguageLevel.HIGHEST;
default:
return LanguageLevel.HIGHEST;
}
}
private static int packCommonFlags(final int access) {
@@ -357,16 +364,17 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
// However Scala compiler erroneously generates ACC_BRIDGE instead of ACC_SYNTHETIC flag for in-trait implementation delegation. See IDEA-78649
if (isSynthetic) return null;
if (SYNTHETIC_CLINIT_METHOD.equals(name)) return null;
if (SYNTHETIC_CLASS_INIT_METHOD.equals(name)) return null;
boolean isDeprecated = (access & Opcodes.ACC_DEPRECATED) != 0;
boolean isConstructor = SYNTHETIC_INIT_METHOD.equals(name);
boolean isVarargs = (access & Opcodes.ACC_VARARGS) != 0;
boolean isAnnotationMethod = myResult.isAnnotationType();
boolean isDefender = (access & ACC_DEFENDER) != 0;
if (!isConstructor && !isCorrectName(name)) return null;
final byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnnotationMethod, isVarargs, isDeprecated, false);
final byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnnotationMethod, isVarargs, isDeprecated, false, isDefender);
String canonicalMethodName = isConstructor ? myResult.getName() : name;
final List<String> args = new ArrayList<String>();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -73,6 +73,7 @@ public abstract class JavaMethodElementType extends JavaStubElementType<PsiMetho
boolean isVarArgs = false;
boolean isDeprecatedByComment = false;
boolean hasDeprecatedAnnotation = false;
boolean isDefender = false;
String defValueText = null;
boolean expectingDef = false;
@@ -102,16 +103,20 @@ public abstract class JavaMethodElementType extends JavaStubElementType<PsiMetho
else if (type == JavaTokenType.DEFAULT_KEYWORD) {
expectingDef = true;
}
else if (expectingDef && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type) &&
type != JavaTokenType.SEMICOLON && type != JavaElementType.CODE_BLOCK) {
defValueText = LightTreeUtil.toFilteredString(tree, child, null);
else if (expectingDef && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type) && type != JavaTokenType.SEMICOLON) {
if (type != JavaElementType.CODE_BLOCK) {
defValueText = LightTreeUtil.toFilteredString(tree, child, null);
}
else {
isDefender = true;
}
break;
}
}
final TypeInfo typeInfo = isConstructor ? TypeInfo.createConstructorType() : TypeInfo.create(tree, node, parentStub);
final boolean isAnno = (node.getTokenType() == JavaElementType.ANNOTATION_METHOD);
final byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnno, isVarArgs, isDeprecatedByComment, hasDeprecatedAnnotation);
final byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnno, isVarArgs, isDeprecatedByComment, hasDeprecatedAnnotation, isDefender);
return new PsiMethodStubImpl(parentStub, StringRef.fromString(name), typeInfo, flags, StringRef.fromString(defValueText));
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@ public interface PsiMethodStub extends NamedStub<PsiMethod> {
boolean isConstructor();
boolean isVarArgs();
boolean isAnnotationMethod();
boolean isDefender();
@Nullable String getDefaultValueText();
@NotNull TypeInfo getReturnTypeText(boolean doResolve);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS
private static final int ANNOTATION = 0x04;
private static final int DEPRECATED = 0x08;
private static final int DEPRECATED_ANNOTATION = 0x10;
private static final int DEFENDER = 0x20;
public PsiMethodStubImpl(final StubElement parent,
@@ -88,6 +89,11 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS
return isAnnotationMethod(myFlags);
}
@Override
public boolean isDefender() {
return (myFlags & DEFENDER) != 0;
}
public static boolean isAnnotationMethod(final byte flags) {
return (flags & ANNOTATION) != 0;
}
@@ -145,13 +151,19 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS
myDefaultValueText = StringRef.fromString(defaultValueText);
}
public static byte packFlags(boolean isConstructor, boolean isAnnotationMethod, boolean isVarargs, boolean isDeprecated, boolean hasDeprecatedAnnotation) {
public static byte packFlags(boolean isConstructor,
boolean isAnnotationMethod,
boolean isVarargs,
boolean isDeprecated,
boolean hasDeprecatedAnnotation,
boolean isDefender) {
byte flags = 0;
if (isConstructor) flags |= CONSTRUCTOR;
if (isAnnotationMethod) flags |= ANNOTATION;
if (isVarargs) flags |= VARARGS;
if (isDeprecated) flags |= DEPRECATED;
if (hasDeprecatedAnnotation) flags |= DEPRECATED_ANNOTATION;
if (isDefender) flags |= DEFENDER;
return flags;
}
@@ -179,6 +191,10 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS
builder.append(" default=").append(defaultValue);
}
if (isDefender()) {
builder.append(" default {}");
}
builder.append("]");
return builder.toString();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ import java.io.IOException;
* @author max
*/
public class JavaFileElementType extends ILightStubFileElementType<PsiJavaFileStub> {
public static final int STUB_VERSION = 9;
public static final int STUB_VERSION = 10;
public JavaFileElementType() {
super("java.FILE", JavaLanguage.INSTANCE);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
@@ -151,7 +152,7 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
return false;
}
if (type == JavaTokenType.ABSTRACT_KEYWORD) {
return true;
return !PsiUtil.isExtensionMethod((PsiMethod)parent);
}
}
}
@@ -13,9 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class C {
interface I {
<error descr="Interface methods cannot have body">void m1()</error> { }
void m2() default { }
void m() default { }
}
void test() {
new I(){}.m();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,7 +32,6 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.security.SecureRandom;
public class JavaStubBuilderTest extends LightIdeaTestCase {
private static final StubBuilder NEW_BUILDER = new JavaLightStubBuilder();
@@ -40,7 +39,7 @@ public class JavaStubBuilderTest extends LightIdeaTestCase {
public void setUp() throws Exception {
super.setUp();
doTest("@interface A { int i() default 42; }\n class C { void m(int p) throws E { } }", null); // warm up
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7);
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.HIGHEST);
}
public void testEmpty() {
@@ -112,6 +111,10 @@ public class JavaStubBuilderTest extends LightIdeaTestCase {
" public C() throws Exception { }\n" +
" public abstract void m(final int i, int[] a1, int a2[], int[] a3[]);\n" +
" private static int v2a(int... v) [] { return v; }\n" +
"}\n" +
"interface I {\n" +
" void m1();\n" +
" void m2() default { }\n" +
"}",
"PsiJavaFileStub []\n" +
@@ -160,6 +163,21 @@ public class JavaStubBuilderTest extends LightIdeaTestCase {
" PARAMETER_LIST:PsiParameterListStub\n" +
" PARAMETER:PsiParameterStub[v:int...]\n" +
" MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" +
" THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n" +
" CLASS:PsiClassStub[interface name=I fqn=I]\n" +
" MODIFIER_LIST:PsiModifierListStub[mask=5120]\n" +
" TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" +
" EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" +
" IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" +
" METHOD:PsiMethodStub[m1:void]\n" +
" MODIFIER_LIST:PsiModifierListStub[mask=1025]\n" +
" TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" +
" PARAMETER_LIST:PsiParameterListStub\n" +
" THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n" +
" METHOD:PsiMethodStub[m2:void default {}]\n" +
" MODIFIER_LIST:PsiModifierListStub[mask=1]\n" +
" TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" +
" PARAMETER_LIST:PsiParameterListStub\n" +
" THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n");
}
@@ -393,7 +411,7 @@ public class JavaStubBuilderTest extends LightIdeaTestCase {
final String lightStr2 = DebugUtil.stubTreeToString(lighterTree2);
if (tree != null) {
System.out.println("light=" + t1 + "mks, heavy=" + t2 + "mks");
if (!"".equals(tree)) {
if (!tree.isEmpty()) {
assertEquals("light tree differs", tree, lightStr);
assertEquals("light tree (2nd) differs", tree, lightStr2);
}