Refactor CodegenBinding & PsiCodegenPredictor
Use ASM Type to store names of classes, use strings in PsiCodegenPredictor. Inline some methods, move closer to their usages
This commit is contained in:
@@ -53,7 +53,6 @@ import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
@@ -1327,10 +1326,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
assert constructorDescriptor != null;
|
||||
CallableMethod constructor = typeMapper.mapToCallableMethod(constructorDescriptor, closure);
|
||||
|
||||
JvmClassName name = bindingContext.get(FQN, constructorDescriptor.getContainingDeclaration());
|
||||
assert name != null;
|
||||
Type type = bindingContext.get(ASM_TYPE, constructorDescriptor.getContainingDeclaration());
|
||||
assert type != null;
|
||||
|
||||
Type type = name.getAsmType();
|
||||
v.anew(type);
|
||||
v.dup();
|
||||
Method cons = constructor.getSignature().getAsmMethod();
|
||||
@@ -1352,7 +1350,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
pushMethodArguments(resolvedCall, Arrays.asList(argumentTypes));
|
||||
}
|
||||
|
||||
v.invokespecial(name.getInternalName(), "<init>", cons.getDescriptor());
|
||||
v.invokespecial(type.getInternalName(), "<init>", cons.getDescriptor());
|
||||
return StackValue.onStack(type);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||
import org.jetbrains.jet.lang.psi.JetScript;
|
||||
import org.jetbrains.jet.lang.resolve.ScriptNameUtil;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -45,7 +44,7 @@ public class KotlinCodegenFacade {
|
||||
String name = ScriptNameUtil.classNameForScript(file);
|
||||
JetScript script = file.getScript();
|
||||
assert script != null;
|
||||
registerClassNameForScript(state.getBindingTrace(), script, JvmClassName.byInternalName(name));
|
||||
registerClassNameForScript(state.getBindingTrace(), script, Type.getObjectType(name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collections;
|
||||
@@ -69,18 +68,16 @@ public class ScriptCodegen extends MemberCodegen {
|
||||
ClassDescriptor classDescriptorForScript = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor);
|
||||
assert classDescriptorForScript != null;
|
||||
|
||||
ScriptContext context =
|
||||
(ScriptContext) CodegenContext.STATIC
|
||||
.intoScript(scriptDescriptor, classDescriptorForScript);
|
||||
ScriptContext context = (ScriptContext) CodegenContext.STATIC.intoScript(scriptDescriptor, classDescriptorForScript);
|
||||
|
||||
JvmClassName className = bindingContext.get(FQN, classDescriptorForScript);
|
||||
assert className != null;
|
||||
Type classType = bindingContext.get(ASM_TYPE, classDescriptorForScript);
|
||||
assert classType != null;
|
||||
|
||||
ClassBuilder classBuilder = classFileFactory.newVisitor(className.getAsmType(), scriptDeclaration.getContainingFile());
|
||||
ClassBuilder classBuilder = classFileFactory.newVisitor(classType, scriptDeclaration.getContainingFile());
|
||||
classBuilder.defineClass(scriptDeclaration,
|
||||
V1_6,
|
||||
ACC_PUBLIC,
|
||||
className.getInternalName(),
|
||||
classType.getInternalName(),
|
||||
null,
|
||||
"java/lang/Object",
|
||||
new String[0]);
|
||||
@@ -120,13 +117,13 @@ public class ScriptCodegen extends MemberCodegen {
|
||||
|
||||
InstructionAdapter instructionAdapter = new InstructionAdapter(mv);
|
||||
|
||||
JvmClassName className = bindingContext.get(FQN, classDescriptorForScript);
|
||||
assert className != null;
|
||||
Type classType = bindingContext.get(ASM_TYPE, classDescriptorForScript);
|
||||
assert classType != null;
|
||||
|
||||
instructionAdapter.load(0, className.getAsmType());
|
||||
instructionAdapter.load(0, classType);
|
||||
instructionAdapter.invokespecial("java/lang/Object", "<init>", "()V");
|
||||
|
||||
instructionAdapter.load(0, className.getAsmType());
|
||||
instructionAdapter.load(0, classType);
|
||||
|
||||
FrameMap frameMap = context.prepareFrame(typeMapper);
|
||||
|
||||
@@ -152,25 +149,25 @@ public class ScriptCodegen extends MemberCodegen {
|
||||
|
||||
for (ScriptDescriptor earlierScript : importedScripts) {
|
||||
Type earlierClassType = asmTypeForScriptDescriptor(bindingContext, earlierScript);
|
||||
instructionAdapter.load(0, className.getAsmType());
|
||||
instructionAdapter.load(0, classType);
|
||||
instructionAdapter.load(offset, earlierClassType);
|
||||
offset += earlierClassType.getSize();
|
||||
instructionAdapter.putfield(className.getInternalName(), getScriptFieldName(earlierScript), earlierClassType.getDescriptor());
|
||||
instructionAdapter.putfield(classType.getInternalName(), getScriptFieldName(earlierScript), earlierClassType.getDescriptor());
|
||||
}
|
||||
|
||||
for (ValueParameterDescriptor parameter : scriptDescriptor.getValueParameters()) {
|
||||
Type parameterType = typeMapper.mapType(parameter.getType());
|
||||
instructionAdapter.load(0, className.getAsmType());
|
||||
instructionAdapter.load(0, classType);
|
||||
instructionAdapter.load(offset, parameterType);
|
||||
offset += parameterType.getSize();
|
||||
instructionAdapter.putfield(className.getInternalName(), parameter.getName().getIdentifier(), parameterType.getDescriptor());
|
||||
instructionAdapter.putfield(classType.getInternalName(), parameter.getName().getIdentifier(), parameterType.getDescriptor());
|
||||
}
|
||||
|
||||
StackValue stackValue =
|
||||
new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state).gen(scriptDeclaration.getBlockExpression());
|
||||
if (stackValue.type != Type.VOID_TYPE) {
|
||||
stackValue.put(stackValue.type, instructionAdapter);
|
||||
instructionAdapter.putfield(className.getInternalName(), ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME,
|
||||
instructionAdapter.putfield(classType.getInternalName(), ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME,
|
||||
blockType.getDescriptor());
|
||||
}
|
||||
|
||||
@@ -204,8 +201,7 @@ public class ScriptCodegen extends MemberCodegen {
|
||||
ScriptDescriptor earlierDescriptor = t.first;
|
||||
Type earlierClassName = t.second;
|
||||
|
||||
registerClassNameForScript(state.getBindingTrace(), earlierDescriptor,
|
||||
JvmClassName.byInternalName(earlierClassName.getInternalName()));
|
||||
registerClassNameForScript(state.getBindingTrace(), earlierDescriptor, earlierClassName);
|
||||
}
|
||||
|
||||
List<ScriptDescriptor> earlierScriptDescriptors = Lists.newArrayList();
|
||||
@@ -243,7 +239,7 @@ public class ScriptCodegen extends MemberCodegen {
|
||||
@NotNull CompilationErrorHandler errorHandler
|
||||
) {
|
||||
registerEarlierScripts(earlierScripts);
|
||||
registerClassNameForScript(state.getBindingTrace(), script, JvmClassName.byInternalName(classType.getInternalName()));
|
||||
registerClassNameForScript(state.getBindingTrace(), script, classType);
|
||||
|
||||
state.beforeCompile();
|
||||
KotlinCodegenFacade.generateNamespace(
|
||||
|
||||
+6
-5
@@ -22,6 +22,7 @@ import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.jet.codegen.SamCodegenUtil;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
@@ -153,9 +154,9 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
||||
super.visitEnumEntry(enumEntry);
|
||||
}
|
||||
else {
|
||||
JvmClassName jvmClassName = bindingTrace.get(FQN, peekFromStack(classStack));
|
||||
assert PsiCodegenPredictor.checkPredictedNameFromPsi(bindingTrace, descriptor, jvmClassName);
|
||||
bindingTrace.record(FQN, descriptor, jvmClassName);
|
||||
Type asmType = bindingTrace.get(ASM_TYPE, peekFromStack(classStack));
|
||||
assert PsiCodegenPredictor.checkPredictedNameFromPsi(bindingTrace, descriptor, asmType);
|
||||
bindingTrace.record(ASM_TYPE, descriptor, asmType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,7 +232,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
||||
|
||||
classStack.push(classDescriptor);
|
||||
//noinspection ConstantConditions
|
||||
nameStack.push(bindingContext.get(FQN, classDescriptor).getInternalName());
|
||||
nameStack.push(bindingContext.get(ASM_TYPE, classDescriptor).getInternalName());
|
||||
super.visitObjectLiteralExpression(expression);
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
@@ -286,7 +287,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
||||
boolean functionLiteral
|
||||
) {
|
||||
CodegenBinding.recordClosure(bindingTrace, element, classDescriptor, peekFromStack(classStack),
|
||||
JvmClassName.byInternalName(name), functionLiteral);
|
||||
Type.getObjectType(name), functionLiteral);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
@@ -52,7 +51,7 @@ public class CodegenBinding {
|
||||
|
||||
public static final WritableSlice<ScriptDescriptor, ClassDescriptor> CLASS_FOR_SCRIPT = Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<DeclarationDescriptor, JvmClassName> FQN = Slices.createSimpleSlice();
|
||||
public static final WritableSlice<DeclarationDescriptor, Type> ASM_TYPE = Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<ClassDescriptor, Boolean> ENUM_ENTRY_CLASS_NEED_SUBCLASS = Slices.createSimpleSetSlice();
|
||||
|
||||
@@ -82,7 +81,7 @@ public class CodegenBinding {
|
||||
public static Type asmTypeForScriptDescriptor(BindingContext bindingContext, @NotNull ScriptDescriptor scriptDescriptor) {
|
||||
ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor);
|
||||
//noinspection ConstantConditions
|
||||
return fqn(bindingContext, classDescriptor);
|
||||
return asmType(bindingContext, classDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -109,9 +108,9 @@ public class CodegenBinding {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Type fqn(@NotNull BindingContext bindingContext, @NotNull ClassDescriptor descriptor) {
|
||||
private static Type asmType(@NotNull BindingContext bindingContext, @NotNull ClassDescriptor descriptor) {
|
||||
//noinspection ConstantConditions
|
||||
return bindingContext.get(FQN, descriptor).getAsmType();
|
||||
return bindingContext.get(ASM_TYPE, descriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -128,25 +127,25 @@ public class CodegenBinding {
|
||||
return asmTypeForAnonymousClass(bindingContext, functionDescriptor);
|
||||
}
|
||||
|
||||
return fqn(bindingContext, descriptor);
|
||||
return asmType(bindingContext, descriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type asmTypeForAnonymousClass(@NotNull BindingContext bindingContext, @NotNull FunctionDescriptor descriptor) {
|
||||
ClassDescriptor classDescriptor = anonymousClassForFunction(bindingContext, descriptor);
|
||||
return fqn(bindingContext, classDescriptor);
|
||||
return asmType(bindingContext, classDescriptor);
|
||||
}
|
||||
|
||||
public static void registerClassNameForScript(
|
||||
BindingTrace bindingTrace,
|
||||
@NotNull ScriptDescriptor scriptDescriptor,
|
||||
@NotNull JvmClassName className
|
||||
@NotNull Type asmType
|
||||
) {
|
||||
ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl(
|
||||
scriptDescriptor,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
Modality.FINAL,
|
||||
Name.special("<script-" + className + ">"));
|
||||
Name.special("<script-" + asmType.getInternalName() + ">"));
|
||||
classDescriptor.initialize(
|
||||
false,
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
@@ -156,7 +155,7 @@ public class CodegenBinding {
|
||||
null,
|
||||
false);
|
||||
|
||||
recordClosure(bindingTrace, null, classDescriptor, null, className, false);
|
||||
recordClosure(bindingTrace, null, classDescriptor, null, asmType, false);
|
||||
|
||||
bindingTrace.record(CLASS_FOR_SCRIPT, scriptDescriptor, classDescriptor);
|
||||
}
|
||||
@@ -200,7 +199,7 @@ public class CodegenBinding {
|
||||
@Nullable JetElement element,
|
||||
ClassDescriptor classDescriptor,
|
||||
@Nullable ClassDescriptor enclosing,
|
||||
JvmClassName name,
|
||||
Type asmType,
|
||||
boolean functionLiteral
|
||||
) {
|
||||
JetDelegatorToSuperCall superCall = findSuperCall(bindingTrace.getBindingContext(), element);
|
||||
@@ -219,8 +218,8 @@ public class CodegenBinding {
|
||||
|
||||
MutableClosure closure = new MutableClosure(superCall, enclosing, enclosingReceiver);
|
||||
|
||||
assert PsiCodegenPredictor.checkPredictedNameFromPsi(bindingTrace, classDescriptor, name);
|
||||
bindingTrace.record(FQN, classDescriptor, name);
|
||||
assert PsiCodegenPredictor.checkPredictedNameFromPsi(bindingTrace, classDescriptor, asmType);
|
||||
bindingTrace.record(ASM_TYPE, classDescriptor, asmType);
|
||||
bindingTrace.record(CLOSURE, classDescriptor, closure);
|
||||
|
||||
// TODO: this is temporary before we have proper inner classes
|
||||
@@ -249,13 +248,13 @@ public class CodegenBinding {
|
||||
public static void registerClassNameForScript(
|
||||
BindingTrace bindingTrace,
|
||||
@NotNull JetScript jetScript,
|
||||
@NotNull JvmClassName className
|
||||
@NotNull Type asmType
|
||||
) {
|
||||
ScriptDescriptor descriptor = bindingTrace.getBindingContext().get(SCRIPT, jetScript);
|
||||
if (descriptor == null) {
|
||||
throw new IllegalStateException("Descriptor is not found for PSI " + jetScript);
|
||||
}
|
||||
registerClassNameForScript(bindingTrace, descriptor, className);
|
||||
registerClassNameForScript(bindingTrace, descriptor, asmType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -324,22 +323,22 @@ public class CodegenBinding {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JvmClassName getJvmInternalName(@NotNull BindingTrace bindingTrace, @NotNull DeclarationDescriptor descriptor) {
|
||||
public static Type getAsmType(@NotNull BindingTrace bindingTrace, @NotNull DeclarationDescriptor descriptor) {
|
||||
descriptor = descriptor.getOriginal();
|
||||
JvmClassName alreadyComputedName = bindingTrace.getBindingContext().get(FQN, descriptor);
|
||||
if (alreadyComputedName != null) {
|
||||
return alreadyComputedName;
|
||||
Type alreadyComputedType = bindingTrace.getBindingContext().get(ASM_TYPE, descriptor);
|
||||
if (alreadyComputedType != null) {
|
||||
return alreadyComputedType;
|
||||
}
|
||||
|
||||
JvmClassName name = JvmClassName.byInternalName(getJvmInternalFQNameImpl(bindingTrace, descriptor));
|
||||
Type asmType = Type.getObjectType(getAsmTypeImpl(bindingTrace, descriptor));
|
||||
|
||||
assert PsiCodegenPredictor.checkPredictedNameFromPsi(bindingTrace, descriptor, name);
|
||||
bindingTrace.record(FQN, descriptor, name);
|
||||
return name;
|
||||
assert PsiCodegenPredictor.checkPredictedNameFromPsi(bindingTrace, descriptor, asmType);
|
||||
bindingTrace.record(ASM_TYPE, descriptor, asmType);
|
||||
return asmType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getJvmInternalFQNameImpl(@NotNull BindingTrace bindingTrace, @NotNull DeclarationDescriptor descriptor) {
|
||||
private static String getAsmTypeImpl(@NotNull BindingTrace bindingTrace, @NotNull DeclarationDescriptor descriptor) {
|
||||
if (descriptor instanceof FunctionDescriptor) {
|
||||
throw new IllegalStateException("requested fq name for function: " + descriptor);
|
||||
}
|
||||
@@ -357,7 +356,7 @@ public class CodegenBinding {
|
||||
return descriptor.getName().getIdentifier();
|
||||
}
|
||||
|
||||
String containerInternalName = getJvmInternalName(bindingTrace, container).getInternalName();
|
||||
String containerInternalName = getAsmType(bindingTrace, container).getInternalName();
|
||||
|
||||
if (descriptor instanceof ClassDescriptor && container instanceof ClassDescriptor) {
|
||||
ClassDescriptor klass = (ClassDescriptor) descriptor;
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.jet.codegen.NamespaceCodegen;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
@@ -30,7 +31,6 @@ import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
||||
@@ -38,18 +38,19 @@ import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
|
||||
import static org.jetbrains.jet.lang.resolve.java.PackageClassUtils.getPackageClassFqName;
|
||||
|
||||
public final class PsiCodegenPredictor {
|
||||
private PsiCodegenPredictor() {
|
||||
}
|
||||
|
||||
public static boolean checkPredictedNameFromPsi(
|
||||
@NotNull BindingTrace bindingTrace, @NotNull DeclarationDescriptor descriptor, JvmClassName nameFromDescriptors
|
||||
@NotNull BindingTrace bindingTrace, @NotNull DeclarationDescriptor descriptor, @Nullable Type nameFromDescriptors
|
||||
) {
|
||||
PsiElement element = descriptorToDeclaration(bindingTrace.getBindingContext(), descriptor);
|
||||
if (element instanceof JetDeclaration) {
|
||||
JvmClassName classNameFromPsi = getPredefinedJvmClassName((JetDeclaration) element);
|
||||
assert classNameFromPsi == null || classNameFromPsi.equals(nameFromDescriptors) :
|
||||
String classNameFromPsi = getPredefinedJvmInternalName((JetDeclaration) element);
|
||||
assert classNameFromPsi == null || Type.getObjectType(classNameFromPsi).equals(nameFromDescriptors) :
|
||||
String.format("Invalid algorithm for getting qualified name from psi! Predicted: %s, actual %s\n" +
|
||||
"Element: %s", classNameFromPsi, nameFromDescriptors, element.getText());
|
||||
}
|
||||
@@ -57,97 +58,79 @@ public final class PsiCodegenPredictor {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JvmClassName getPredefinedJvmClassName(@NotNull JetFile jetFile, boolean withNamespace) {
|
||||
String packageName = jetFile.getPackageName();
|
||||
if (packageName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JvmClassName packageJvmName = JvmClassName.byFqNameWithoutInnerClasses(packageName);
|
||||
return !withNamespace ? packageJvmName : addPackageClass(packageJvmName);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Finish this method for all cases. Now it's only used and tested in JetLightClass.
|
||||
*
|
||||
* @return null if no prediction can be done.
|
||||
*/
|
||||
@Nullable
|
||||
public static JvmClassName getPredefinedJvmClassName(@NotNull JetDeclaration declaration) {
|
||||
public static String getPredefinedJvmInternalName(@NotNull JetDeclaration declaration) {
|
||||
// TODO: Method won't work for declarations inside class objects
|
||||
// TODO: Method won't give correct class name for traits implementations
|
||||
|
||||
JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(declaration, JetDeclaration.class);
|
||||
if (parentDeclaration instanceof JetClassObject) {
|
||||
assert declaration instanceof JetObjectDeclaration : "Only object declarations can be children of JetClassObject: " + declaration;
|
||||
return getPredefinedJvmClassName(parentDeclaration);
|
||||
return getPredefinedJvmInternalName(parentDeclaration);
|
||||
}
|
||||
|
||||
JvmClassName parentClassName = parentDeclaration != null ?
|
||||
getPredefinedJvmClassName(parentDeclaration) :
|
||||
getPredefinedJvmClassName((JetFile) declaration.getContainingFile(), false);
|
||||
if (parentClassName == null) {
|
||||
return null;
|
||||
String parentInternalName;
|
||||
if (parentDeclaration != null) {
|
||||
parentInternalName = getPredefinedJvmInternalName(parentDeclaration);
|
||||
if (parentInternalName == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
String packageName = ((JetFile) declaration.getContainingFile()).getPackageName();
|
||||
if (packageName == null) {
|
||||
return null;
|
||||
}
|
||||
parentInternalName = JvmClassName.byFqNameWithoutInnerClasses(packageName).getInternalName();
|
||||
}
|
||||
|
||||
if (declaration instanceof JetClassObject) {
|
||||
// Get parent and assign Class object prefix
|
||||
return JvmClassName.byInternalName(parentClassName.getInternalName() + JvmAbi.CLASS_OBJECT_SUFFIX);
|
||||
return parentInternalName + JvmAbi.CLASS_OBJECT_SUFFIX;
|
||||
}
|
||||
|
||||
if (declaration instanceof JetNamedDeclaration) {
|
||||
if (!PsiTreeUtil.instanceOf(declaration, JetClass.class, JetObjectDeclaration.class, JetNamedFunction.class, JetProperty.class) ||
|
||||
declaration instanceof JetEnumEntry) {
|
||||
// Other subclasses are not valid for class name prediction.
|
||||
// For example EnumEntry, JetFunctionLiteral
|
||||
return null;
|
||||
}
|
||||
|
||||
JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) declaration;
|
||||
Name name = namedDeclaration.getNameAsName();
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
FqName fqName = parentClassName.getFqName();
|
||||
|
||||
if (declaration instanceof JetNamedFunction) {
|
||||
if (parentDeclaration == null) {
|
||||
JvmClassName packageClass = addPackageClass(parentClassName);
|
||||
return JvmClassName.byInternalName(packageClass.getInternalName() + "$" + name.asString());
|
||||
}
|
||||
|
||||
if (!(parentDeclaration instanceof JetClass || parentDeclaration instanceof JetObjectDeclaration)) {
|
||||
// Can't generate predefined name for internal functions
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: looks like a bug - for class in getter of top level property class name will be $propertyName$ClassName but not
|
||||
// namespace$propertyName$ClassName
|
||||
if (declaration instanceof JetProperty) {
|
||||
return JvmClassName.byInternalName(parentClassName.getInternalName() + "$" + name.asString());
|
||||
}
|
||||
|
||||
if (fqName.isRoot()) {
|
||||
return JvmClassName.byInternalName(name.asString());
|
||||
}
|
||||
|
||||
return JvmClassName.byInternalName(parentDeclaration == null ?
|
||||
parentClassName.getInternalName() + "/" + name.asString() :
|
||||
parentClassName.getInternalName() + "$" + name.asString());
|
||||
if (!PsiTreeUtil.instanceOf(declaration, JetClass.class, JetObjectDeclaration.class, JetNamedFunction.class, JetProperty.class) ||
|
||||
declaration instanceof JetEnumEntry) {
|
||||
// Other subclasses are not valid for class name prediction.
|
||||
// For example EnumEntry, JetFunctionLiteral
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) declaration;
|
||||
Name name = namedDeclaration.getNameAsName();
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static JvmClassName addPackageClass(JvmClassName packageName) {
|
||||
FqName name = packageName.getFqName();
|
||||
String packageClassName = PackageClassUtils.getPackageClassName(name);
|
||||
return name.isRoot() ?
|
||||
JvmClassName.byFqNameWithoutInnerClasses(packageClassName) :
|
||||
JvmClassName.byInternalName(packageName.getInternalName() + "/" + packageClassName);
|
||||
if (declaration instanceof JetNamedFunction) {
|
||||
if (parentDeclaration == null) {
|
||||
FqName fqName = JvmClassName.byInternalName(parentInternalName).getFqName();
|
||||
JvmClassName packageClass = JvmClassName.byFqNameWithoutInnerClasses(getPackageClassFqName(fqName));
|
||||
return packageClass.getInternalName() + "$" + name.asString();
|
||||
}
|
||||
|
||||
if (!(parentDeclaration instanceof JetClass || parentDeclaration instanceof JetObjectDeclaration)) {
|
||||
// Can't generate predefined name for internal functions
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: looks like a bug - for class in getter of top level property class name will be $propertyName$ClassName but not
|
||||
// namespace$propertyName$ClassName
|
||||
if (declaration instanceof JetProperty) {
|
||||
return parentInternalName + "$" + name.asString();
|
||||
}
|
||||
|
||||
if (parentInternalName.isEmpty()) {
|
||||
return name.asString();
|
||||
}
|
||||
|
||||
return parentInternalName + (parentDeclaration == null ? "/" : "$") + name.asString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -166,7 +149,7 @@ public final class PsiCodegenPredictor {
|
||||
public static JetFile getFileForCodegenNamedClass(
|
||||
@NotNull BindingContext context,
|
||||
@NotNull Collection<JetFile> allNamespaceFiles,
|
||||
@NotNull final JvmClassName className
|
||||
@NotNull final String classInternalName
|
||||
) {
|
||||
final Ref<DeclarationDescriptor> resultingDescriptor = Ref.create();
|
||||
|
||||
@@ -174,8 +157,8 @@ public final class PsiCodegenPredictor {
|
||||
@Override
|
||||
public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
|
||||
super.record(slice, key, value);
|
||||
if (slice == CodegenBinding.FQN && key instanceof DeclarationDescriptor) {
|
||||
if (className.equals(value)) {
|
||||
if (slice == CodegenBinding.ASM_TYPE && key instanceof DeclarationDescriptor && value instanceof Type) {
|
||||
if (classInternalName.equals(((Type) value).getInternalName())) {
|
||||
resultingDescriptor.set((DeclarationDescriptor) key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -278,7 +277,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
ClassDescriptor enclosingClass = getEnclosingClass();
|
||||
outerExpression = enclosingClass != null && canHaveOuter(typeMapper.getBindingContext(), classDescriptor)
|
||||
? StackValue.field(typeMapper.mapType(enclosingClass),
|
||||
CodegenBinding.getJvmInternalName(typeMapper.getBindingTrace(), classDescriptor).getAsmType(),
|
||||
CodegenBinding.getAsmType(typeMapper.getBindingTrace(), classDescriptor),
|
||||
CAPTURED_THIS_FIELD,
|
||||
false)
|
||||
: null;
|
||||
@@ -295,8 +294,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
|
||||
for (LocalLookup.LocalLookupCase aCase : LocalLookup.LocalLookupCase.values()) {
|
||||
if (aCase.isCase(d, state)) {
|
||||
JvmClassName className = state.getBindingContext().get(FQN, getThisDescriptor());
|
||||
Type classType = className == null ? null : className.getAsmType();
|
||||
Type classType = state.getBindingContext().get(ASM_TYPE, getThisDescriptor());
|
||||
StackValue innerValue = aCase.innerValue(d, enclosingLocalLookup, state, closure, classType);
|
||||
if (innerValue == null) {
|
||||
break;
|
||||
|
||||
@@ -334,13 +334,13 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
}
|
||||
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
JvmClassName name = getJvmInternalName(bindingTrace, descriptor);
|
||||
Type descriptorAsmType = getAsmType(bindingTrace, descriptor);
|
||||
Type asmType;
|
||||
if (kind == JetTypeMapperMode.TRAIT_IMPL) {
|
||||
asmType = Type.getObjectType(name.getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX);
|
||||
asmType = Type.getObjectType(descriptorAsmType.getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX);
|
||||
}
|
||||
else {
|
||||
asmType = name.getAsmType();
|
||||
asmType = descriptorAsmType;
|
||||
}
|
||||
|
||||
writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed);
|
||||
|
||||
+4
-4
@@ -43,8 +43,8 @@ import org.jetbrains.jet.codegen.binding.PsiCodegenPredictor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetJavaMirrorMarker;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetJavaMirrorMarker;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
@@ -66,10 +66,10 @@ public class KotlinLightClassForExplicitDeclaration extends AbstractLightClass i
|
||||
return null;
|
||||
}
|
||||
|
||||
JvmClassName jvmClassName = PsiCodegenPredictor.getPredefinedJvmClassName(classOrObject);
|
||||
if (jvmClassName == null) return null;
|
||||
String jvmInternalName = PsiCodegenPredictor.getPredefinedJvmInternalName(classOrObject);
|
||||
if (jvmInternalName == null) return null;
|
||||
|
||||
return new KotlinLightClassForExplicitDeclaration(manager, jvmClassName.getFqName(), classOrObject);
|
||||
return new KotlinLightClassForExplicitDeclaration(manager, JvmClassName.byInternalName(jvmInternalName).getFqName(), classOrObject);
|
||||
}
|
||||
|
||||
private final FqName classFqName; // FqName of (possibly inner) class
|
||||
|
||||
@@ -36,11 +36,10 @@ import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.binding.PsiCodegenPredictor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetClsMethod;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetClsMethod;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.utils.ExceptionUtils;
|
||||
@@ -235,12 +234,11 @@ public class LightClassUtil {
|
||||
|
||||
if (parent instanceof JetFile) {
|
||||
// top-level declaration
|
||||
JvmClassName jvmName = PsiCodegenPredictor.getPredefinedJvmClassName((JetFile) parent, true);
|
||||
if (jvmName != null) {
|
||||
FqName fqName = getPackageClassNameForFile((JetFile) parent);
|
||||
if (fqName != null) {
|
||||
Project project = declaration.getProject();
|
||||
|
||||
String fqName = jvmName.getFqName().asString();
|
||||
return JavaElementFinder.getInstance(project).findClass(fqName, GlobalSearchScope.allScope(project));
|
||||
return JavaElementFinder.getInstance(project).findClass(fqName.asString(), GlobalSearchScope.allScope(project));
|
||||
}
|
||||
}
|
||||
else if (parent instanceof JetClassBody) {
|
||||
@@ -251,6 +249,12 @@ public class LightClassUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static FqName getPackageClassNameForFile(@NotNull JetFile jetFile) {
|
||||
String packageName = jetFile.getPackageName();
|
||||
return packageName == null ? null : PackageClassUtils.getPackageClassFqName(new FqName(packageName));
|
||||
}
|
||||
|
||||
private static PropertyAccessorsPsiMethods extractPropertyAccessors(
|
||||
@NotNull JetDeclaration jetDeclaration,
|
||||
@Nullable PsiMethod specialGetter, @Nullable PsiMethod specialSetter
|
||||
|
||||
@@ -375,11 +375,11 @@ public class JetSourceNavigationHelper {
|
||||
@Nullable
|
||||
public static PsiClass getOriginalClass(@NotNull JetClassOrObject classOrObject) {
|
||||
// Copied from JavaPsiImplementationHelperImpl:getOriginalClass()
|
||||
JvmClassName className = PsiCodegenPredictor.getPredefinedJvmClassName(classOrObject);
|
||||
if (className == null) {
|
||||
String internalName = PsiCodegenPredictor.getPredefinedJvmInternalName(classOrObject);
|
||||
if (internalName == null) {
|
||||
return null;
|
||||
}
|
||||
String fqName = className.getFqName().asString();
|
||||
String fqName = JvmClassName.byInternalName(internalName).getFqName().asString();
|
||||
|
||||
JetFile file = (JetFile) classOrObject.getContainingFile();
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ public class DebuggerUtils {
|
||||
// we may actually need to analyze the project in order to find a file which produces this class
|
||||
AnalyzeExhaust analyzeExhaust = AnalyzerFacadeWithCache.analyzeFileWithCache(anyFile);
|
||||
|
||||
return PsiCodegenPredictor.getFileForCodegenNamedClass(analyzeExhaust.getBindingContext(), allNamespaceFiles, className);
|
||||
return PsiCodegenPredictor.getFileForCodegenNamedClass(analyzeExhaust.getBindingContext(), allNamespaceFiles, className.getInternalName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
Reference in New Issue
Block a user