Properly calculate short name for inner class with dollars

https://github.com/JetBrains/intellij-community/pull/108
This commit is contained in:
Roman Shevchenko
2013-10-22 11:29:18 +02:00
parent e27a3c18f5
commit 894d3b07d9
9 changed files with 70 additions and 27 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -40,9 +40,8 @@ public class DefaultClsStubBuilderFactory extends ClsStubBuilderFactory {
final PsiJavaFileStubImpl file = new PsiJavaFileStubImpl("do.not.know.yet", true);
try {
final ClassReader reader = new ClassReader(bytes);
final StubBuildingVisitor<VirtualFile> classVisitor =
new StubBuildingVisitor<VirtualFile>(vFile, VirtualFileInnerClassStrategy.INSTANCE, file, 0);
new StubBuildingVisitor<VirtualFile>(vFile, VirtualFileInnerClassStrategy.INSTANCE, file, 0, null);
try {
reader.accept(classVisitor, ClassReader.SKIP_FRAMES);
}
@@ -40,6 +40,8 @@ import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import static com.intellij.psi.CommonClassNames.*;
/**
* @author max
*/
@@ -57,19 +59,21 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
@NonNls private static final String SYNTHETIC_CLASS_INIT_METHOD = "<clinit>";
@NonNls private static final String SYNTHETIC_INIT_METHOD = "<init>";
private final T mySource;
private final InnerClassSourceStrategy<T> myInnersStrategy;
private final StubElement myParent;
private final int myAccess;
private final T mySource;
private PsiModifierListStub myModList;
private final String myShortName;
private PsiClassStub myResult;
private PsiModifierListStub myModList;
public StubBuildingVisitor(final T classSource, InnerClassSourceStrategy<T> innersStrategy, final StubElement parent, final int access) {
public StubBuildingVisitor(T classSource, InnerClassSourceStrategy<T> innersStrategy, StubElement parent, int access, String shortName) {
super(Opcodes.ASM4);
mySource = classSource;
myInnersStrategy = innersStrategy;
myParent = parent;
myAccess = access;
myShortName = shortName;
}
public PsiClassStub<?> getResult() {
@@ -77,25 +81,17 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
}
@Override
public void visit(final int version,
final int access,
final String name,
final String signature,
final String superName,
final String[] interfaces) {
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
String fqn = getClassName(name);
String shortName = myShortName != null ? myShortName : PsiNameHelper.getShortClassName(fqn);
final String shortName = PsiNameHelper.getShortClassName(fqn);
final int flags = myAccess == 0 ? access : myAccess;
int flags = myAccess == 0 ? access : myAccess;
boolean isDeprecated = (flags & Opcodes.ACC_DEPRECATED) != 0;
boolean isInterface = (flags & Opcodes.ACC_INTERFACE) != 0;
boolean isEnum = (flags & Opcodes.ACC_ENUM) != 0;
boolean isAnnotationType = (flags & Opcodes.ACC_ANNOTATION) != 0;
final byte stubFlags = PsiClassStubImpl.packFlags(isDeprecated, isInterface, isEnum, false, false, isAnnotationType, false, false);
byte stubFlags = PsiClassStubImpl.packFlags(isDeprecated, isInterface, isEnum, false, false, isAnnotationType, false, false);
myResult = new PsiClassStubImpl(JavaStubElementTypes.CLASS, myParent, fqn, shortName, null, stubFlags);
LanguageLevel languageLevel = convertFromVersion(version);
@@ -131,16 +127,15 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
if (isInterface) {
if (isAnnotationType) {
convertedInterfaces.remove(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION);
convertedInterfaces.remove(JAVA_LANG_ANNOTATION_ANNOTATION);
}
newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, ArrayUtil.toStringArray(convertedInterfaces));
newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, myResult);
}
else {
if (convertedSuper == null ||
CommonClassNames.JAVA_LANG_OBJECT.equals(convertedSuper) ||
isEnum && (CommonClassNames.JAVA_LANG_ENUM.equals(convertedSuper) ||
(CommonClassNames.JAVA_LANG_ENUM + "<" + fqn + ">").equals(convertedSuper))) {
JAVA_LANG_OBJECT.equals(convertedSuper) ||
isEnum && (JAVA_LANG_ENUM.equals(convertedSuper) || (JAVA_LANG_ENUM + "<" + fqn + ">").equals(convertedSuper))) {
newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult);
}
else {
@@ -303,12 +298,10 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
@Override
public void visitInnerClass(final String name, final String outerName, final String innerName, final int access) {
if ((access & Opcodes.ACC_SYNTHETIC) != 0) return;
if (!isCorrectName(innerName)) return;
if (!isCorrectName(innerName) || outerName == null) return;
if (innerName == null || outerName == null) return;
if ((getClassName(outerName) + "." + innerName).equals(myResult.getQualifiedName())) {
// Our result is inner class
// our result is inner class
if (myParent instanceof PsiFileStub) {
throw new OutOfOrderInnerClassException();
}
@@ -322,7 +315,7 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
final ClassReader reader = myInnersStrategy.readerForInnerClass(innerSource);
if (reader == null) return;
final StubBuildingVisitor<T> classVisitor = new StubBuildingVisitor<T>(innerSource, myInnersStrategy, myResult, access);
final StubBuildingVisitor<T> classVisitor = new StubBuildingVisitor<T>(innerSource, myInnersStrategy, myResult, access, innerName);
reader.accept(classVisitor, ClassReader.SKIP_FRAMES);
}
@@ -0,0 +1,27 @@
// IntelliJ API Decompiler stub source generated from a class file
// Implementation of methods is not available
package pkg;
public abstract class KotlinFunList <T> {
public static pkg.KotlinFunList.ClassObject$ $classobj;
public KotlinFunList() { /* compiled code */ }
public static final class ClassObject$ {
public ClassObject$() { /* compiled code */ }
public final class Standard <T> {
final pkg.KotlinFunList.ClassObject$ this$0;
public Standard() { /* compiled code */ }
}
public final class Empty <T> {
final pkg.KotlinFunList.ClassObject$ this$0;
public Empty() { /* compiled code */ }
}
}
}
@@ -0,0 +1,23 @@
package pkg;
public abstract class KotlinFunList<T> {
public static pkg.KotlinFunList.ClassObject$ $classobj;
public KotlinFunList() { }
public static final class ClassObject$ {
public ClassObject$() { }
public final class Empty<T> {
final ClassObject$ this$0;
public Empty() { this$0 = null; }
}
public final class Standard<T> {
final ClassObject$ this$0;
public Standard() { this$0 = null; }
}
}
}
@@ -43,6 +43,7 @@ public class ClsMirrorBuildingTest extends LightIdeaTestCase {
public void testPrimitives() { doTest(); }
public void testClassRefs() { doTest(); }
public void testEA46236() { doTest("ValuedEnum"); }
public void testKotlinFunList() { doTest(); }
private void doTest() {
doTest(getTestName(false));