refactoring in progress
This commit is contained in:
@@ -37,9 +37,6 @@ public class ClassCodegen {
|
||||
public void generate(CodegenContext context, JetClassOrObject aClass) {
|
||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||
ClassBuilder classBuilder = state.forClassImplementation(descriptor);
|
||||
if (classBuilder.generateCode()) {
|
||||
GenerationState.prepareAnonymousClasses(aClass, state.getTypeMapper());
|
||||
}
|
||||
|
||||
final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state.getTypeMapper());
|
||||
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class ClosureAnnotator {
|
||||
private final Map<JetElement, String> classNamesForAnonymousClasses = new HashMap<JetElement, String>();
|
||||
private final Map<ClassDescriptor, String> classNamesForClassDescriptor = new HashMap<ClassDescriptor, String>();
|
||||
private final Map<String, Integer> anonymousSubclassesCount = new HashMap<String, Integer>();
|
||||
private final Map<FunctionDescriptor, ClassDescriptorImpl> classesForFunctions = new HashMap<FunctionDescriptor, ClassDescriptorImpl>();
|
||||
private final Map<DeclarationDescriptor,ClassDescriptor> enclosing = new HashMap<DeclarationDescriptor, ClassDescriptor>();
|
||||
|
||||
private final MultiMap<String,JetFile> namespaceName2Files = MultiMap.create();
|
||||
private final BindingContext bindingContext;
|
||||
|
||||
public ClosureAnnotator(BindingContext bindingContext, Collection<JetFile> files) {
|
||||
this.bindingContext = bindingContext;
|
||||
mapFilesToNamespaces(files);
|
||||
prepareAnonymousClasses();
|
||||
}
|
||||
|
||||
public ClassDescriptor classDescriptorForFunctionDescriptor(FunctionDescriptor funDescriptor, String name) {
|
||||
ClassDescriptorImpl classDescriptor = classesForFunctions.get(funDescriptor);
|
||||
if(classDescriptor == null) {
|
||||
int arity = funDescriptor.getValueParameters().size();
|
||||
|
||||
classDescriptor = new ClassDescriptorImpl(
|
||||
funDescriptor,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
name);
|
||||
classDescriptor.initialize(
|
||||
false,
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null);
|
||||
classesForFunctions.put(funDescriptor, classDescriptor);
|
||||
}
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
private void mapFilesToNamespaces(Collection<JetFile> files) {
|
||||
for (JetFile file : files) {
|
||||
String fqName = JetPsiUtil.getFQName(file);
|
||||
namespaceName2Files.putValue(fqName, file);
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareAnonymousClasses() {
|
||||
MyJetVisitorVoid visitor = new MyJetVisitorVoid();
|
||||
for (Map.Entry<String,Collection<JetFile>> entry : namespaceName2Files.entrySet()) {
|
||||
for (JetFile jetFile : entry.getValue()) {
|
||||
jetFile.accept(visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String classNameForAnonymousClass(JetElement expression) {
|
||||
if(expression instanceof JetObjectLiteralExpression) {
|
||||
JetObjectLiteralExpression jetObjectLiteralExpression = (JetObjectLiteralExpression) expression;
|
||||
expression = jetObjectLiteralExpression.getObjectDeclaration();
|
||||
}
|
||||
|
||||
if(expression instanceof JetFunctionLiteralExpression) {
|
||||
JetFunctionLiteralExpression jetFunctionLiteralExpression = (JetFunctionLiteralExpression) expression;
|
||||
expression = jetFunctionLiteralExpression.getFunctionLiteral();
|
||||
}
|
||||
|
||||
String name = classNamesForAnonymousClasses.get(expression);
|
||||
assert name != null;
|
||||
return name;
|
||||
}
|
||||
|
||||
public ClassDescriptor getEclosingClassDescriptor(ClassDescriptor descriptor) {
|
||||
return enclosing.get(descriptor);
|
||||
}
|
||||
|
||||
public boolean hasThis0(ClassDescriptor classDescriptor) {
|
||||
if(CodegenUtil.isClassObject(classDescriptor))
|
||||
return false;
|
||||
|
||||
ClassDescriptor other = enclosing.get(classDescriptor);
|
||||
return other != null;
|
||||
}
|
||||
|
||||
private class MyJetVisitorVoid extends JetVisitorVoid {
|
||||
private LinkedList<ClassDescriptor> classStack = new LinkedList<ClassDescriptor>();
|
||||
private LinkedList<String> nameStack = new LinkedList<String>();
|
||||
|
||||
private void recordEnclosing(ClassDescriptor classDescriptor) {
|
||||
if(classStack.size() > 0) {
|
||||
ClassDescriptor put = enclosing.put(classDescriptor, classStack.peek());
|
||||
assert put == null;
|
||||
}
|
||||
}
|
||||
|
||||
private String recordAnonymousClass(JetElement declaration) {
|
||||
String name = classNamesForAnonymousClasses.get(declaration);
|
||||
assert name == null;
|
||||
|
||||
String top = nameStack.peek();
|
||||
Integer cnt = anonymousSubclassesCount.get(top);
|
||||
if(cnt == null) {
|
||||
cnt = 0;
|
||||
}
|
||||
name = top + "$" + (cnt + 1);
|
||||
classNamesForAnonymousClasses.put(declaration, name);
|
||||
anonymousSubclassesCount.put(top, cnt + 1);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
private String recordClassObject(JetClassObject declaration) {
|
||||
String name = classNamesForAnonymousClasses.get(declaration.getObjectDeclaration());
|
||||
assert name == null;
|
||||
|
||||
name = nameStack.peek() + JvmAbi.CLASS_OBJECT_SUFFIX;
|
||||
classNamesForAnonymousClasses.put(declaration.getObjectDeclaration(), name);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJetElement(JetElement element) {
|
||||
super.visitJetElement(element);
|
||||
element.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJetFile(JetFile file) {
|
||||
nameStack.push(JetPsiUtil.getFQName(file).replace('.', '/'));
|
||||
file.acceptChildren(this);
|
||||
nameStack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassObject(JetClassObject classObject) {
|
||||
String name = recordClassObject(classObject);
|
||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, classObject.getObjectDeclaration());
|
||||
recordEnclosing(classDescriptor);
|
||||
recordName(classDescriptor, name);
|
||||
classStack.push(classDescriptor);
|
||||
nameStack.push(name);
|
||||
super.visitClassObject(classObject);
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitObjectDeclaration(JetObjectDeclaration declaration) {
|
||||
if(declaration.getParent() instanceof JetObjectLiteralExpression || declaration.getParent() instanceof JetClassObject) {
|
||||
super.visitObjectDeclaration(declaration);
|
||||
}
|
||||
else {
|
||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, declaration);
|
||||
recordEnclosing(classDescriptor);
|
||||
classStack.push(classDescriptor);
|
||||
String base = nameStack.peek();
|
||||
if(classDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor) {
|
||||
nameStack.push(base.isEmpty() ? classDescriptor.getName() : base + '/' + classDescriptor.getName());
|
||||
}
|
||||
else
|
||||
nameStack.push(base + '$' + classDescriptor.getName());
|
||||
super.visitObjectDeclaration(declaration);
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClass(JetClass klass) {
|
||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, klass);
|
||||
recordEnclosing(classDescriptor);
|
||||
classStack.push(classDescriptor);
|
||||
String base = nameStack.peek();
|
||||
if(classDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor) {
|
||||
nameStack.push(base.isEmpty() ? classDescriptor.getName() : base + '/' + classDescriptor.getName());
|
||||
}
|
||||
else
|
||||
nameStack.push(base + '$' + classDescriptor.getName());
|
||||
super.visitClass(klass);
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) {
|
||||
String name = recordAnonymousClass(expression.getObjectDeclaration());
|
||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, expression.getObjectDeclaration());
|
||||
recordName(classDescriptor, name);
|
||||
recordEnclosing(classDescriptor);
|
||||
classStack.push(classDescriptor);
|
||||
nameStack.push(classNameForClassDescriptor(classDescriptor));
|
||||
super.visitObjectLiteralExpression(expression);
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) {
|
||||
String name = recordAnonymousClass(expression.getFunctionLiteral());
|
||||
FunctionDescriptor declarationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression);
|
||||
ClassDescriptor classDescriptor = classDescriptorForFunctionDescriptor(declarationDescriptor, name);
|
||||
recordName(classDescriptor, name);
|
||||
recordEnclosing(classDescriptor);
|
||||
classStack.push(classDescriptor);
|
||||
nameStack.push(classNameForClassDescriptor(classDescriptor));
|
||||
super.visitFunctionLiteralExpression(expression);
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
}
|
||||
|
||||
private void recordName(ClassDescriptor classDescriptor, String name) {
|
||||
String old = classNamesForClassDescriptor.put(classDescriptor, name);
|
||||
assert old == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitProperty(JetProperty property) {
|
||||
nameStack.push(nameStack.peek() + '$' + property.getName());
|
||||
super.visitProperty(property);
|
||||
nameStack.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNamedFunction(JetNamedFunction function) {
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, function);
|
||||
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
|
||||
if (containingDeclaration instanceof ClassDescriptor) {
|
||||
nameStack.push(nameStack.peek() + '$' + function.getName());
|
||||
super.visitNamedFunction(function);
|
||||
nameStack.pop();
|
||||
}
|
||||
else if (containingDeclaration instanceof NamespaceDescriptor) {
|
||||
String peek = nameStack.peek();
|
||||
if(peek.isEmpty())
|
||||
peek = "namespace";
|
||||
else
|
||||
peek = peek + "/namespace";
|
||||
nameStack.push(peek + '$' + function.getName());
|
||||
super.visitNamedFunction(function);
|
||||
nameStack.pop();
|
||||
}
|
||||
else {
|
||||
String name = recordAnonymousClass(function);
|
||||
ClassDescriptor classDescriptor = classDescriptorForFunctionDescriptor(functionDescriptor, name);
|
||||
recordName(classDescriptor, name);
|
||||
recordEnclosing(classDescriptor);
|
||||
classStack.push(classDescriptor);
|
||||
nameStack.push(name);
|
||||
super.visitNamedFunction(function);
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String classNameForClassDescriptor(ClassDescriptor classDescriptor) {
|
||||
String name = classNamesForClassDescriptor.get(classDescriptor);
|
||||
assert name != null;
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -23,12 +23,10 @@ package org.jetbrains.jet.codegen;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
@@ -40,7 +38,6 @@ import org.objectweb.asm.commons.Method;
|
||||
import org.objectweb.asm.signature.SignatureWriter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
@@ -136,11 +133,11 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
ClassDescriptor thisDescriptor = context.getThisDescriptor();
|
||||
final Type enclosingType = thisDescriptor == null ? null : state.getTypeMapper().mapType(thisDescriptor.getDefaultType());
|
||||
if (enclosingType == null)
|
||||
captureThis = false;
|
||||
captureThis = null;
|
||||
|
||||
final Method constructor = generateConstructor(funClass, fun);
|
||||
|
||||
if (captureThis) {
|
||||
if (captureThis != null) {
|
||||
cv.newField(fun, ACC_FINAL, "this$0", enclosingType.getDescriptor(), null, null);
|
||||
}
|
||||
|
||||
@@ -189,17 +186,8 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetDeclarationWithBody body) {
|
||||
int arity = funDescriptor.getValueParameters().size();
|
||||
|
||||
ClassDescriptorImpl function = new ClassDescriptorImpl(
|
||||
funDescriptor,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
name);
|
||||
function = function.initialize(
|
||||
false,
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null);
|
||||
private Type generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetDeclarationWithBody body) {
|
||||
ClassDescriptor function = state.getTypeMapper().getClosureAnnotator().classDescriptorForFunctionDescriptor(funDescriptor, name);
|
||||
|
||||
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper());
|
||||
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
||||
@@ -248,7 +236,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
}
|
||||
|
||||
private Method generateConstructor(String funClass, PsiElement fun) {
|
||||
int argCount = captureThis ? 1 : 0;
|
||||
int argCount = captureThis != null ? 1 : 0;
|
||||
argCount += (captureReceiver != null ? 1 : 0);
|
||||
|
||||
ArrayList<DeclarationDescriptor> variableDescriptors = new ArrayList<DeclarationDescriptor>();
|
||||
@@ -270,7 +258,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
Type[] argTypes = new Type[argCount];
|
||||
|
||||
int i = 0;
|
||||
if (captureThis) {
|
||||
if (captureThis != null) {
|
||||
argTypes[i++] = state.getTypeMapper().mapType(context.getThisDescriptor().getDefaultType());
|
||||
}
|
||||
|
||||
@@ -285,7 +273,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
argTypes[i++] = type;
|
||||
}
|
||||
else if(CodegenUtil.isNamedFun(descriptor, state.getBindingContext()) && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
|
||||
final Type type = Type.getObjectType(state.getTypeMapper().classNameForAnonymousClass((JetElement) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor)));
|
||||
final Type type = Type.getObjectType(state.getTypeMapper().getClosureAnnotator().classNameForAnonymousClass((JetElement) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor)));
|
||||
argTypes[i++] = type;
|
||||
}
|
||||
}
|
||||
@@ -304,11 +292,11 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
StackValue.local(0, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
|
||||
StackValue.local(i, type).put(type, iv);
|
||||
final String fieldName;
|
||||
if (captureThis && i == 1) {
|
||||
if (captureThis != null && i == 1) {
|
||||
fieldName = "this$0";
|
||||
}
|
||||
else {
|
||||
if (captureReceiver != null && (captureThis && i == 2 || !captureThis && i == 1)) {
|
||||
if (captureReceiver != null && (captureThis != null && i == 2 || captureThis == null && i == 1)) {
|
||||
fieldName = "receiver$0";
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -68,7 +68,7 @@ public abstract class CodegenContext {
|
||||
|
||||
protected StackValue outerExpression;
|
||||
|
||||
protected boolean outerWasUsed ;
|
||||
protected Type outerWasUsed ;
|
||||
|
||||
public CodegenContext(DeclarationDescriptor contextType, OwnerKind contextKind, @Nullable CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
|
||||
this.contextType = contextType;
|
||||
@@ -100,7 +100,7 @@ public abstract class CodegenContext {
|
||||
if(outerExpression == null)
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
outerWasUsed = true;
|
||||
outerWasUsed = outerExpression.type;
|
||||
return prefix != null ? StackValue.composed(prefix, outerExpression) : outerExpression;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,21 +59,6 @@ public class CodegenUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean hasThis0(ClassDescriptor classDescriptor) {
|
||||
return getOuterClassDescriptor(classDescriptor) != null && !isClassObject(classDescriptor);
|
||||
}
|
||||
|
||||
public static ClassDescriptor getOuterClassDescriptor(DeclarationDescriptor descriptor) {
|
||||
DeclarationDescriptor outerDescriptor = descriptor.getContainingDeclaration();
|
||||
while(outerDescriptor != null) {
|
||||
if(outerDescriptor instanceof ClassDescriptor)
|
||||
break;
|
||||
|
||||
outerDescriptor = outerDescriptor.getContainingDeclaration();
|
||||
}
|
||||
return (ClassDescriptor) outerDescriptor;
|
||||
}
|
||||
|
||||
public static SimpleFunctionDescriptor createInvoke(FunctionDescriptor fd) {
|
||||
int arity = fd.getValueParameters().size();
|
||||
SimpleFunctionDescriptorImpl invokeDescriptor = new SimpleFunctionDescriptorImpl(
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.objectweb.asm.Type;
|
||||
@@ -33,10 +32,10 @@ public class ConstructorFrameMap extends FrameMap {
|
||||
private int myOuterThisIndex = -1;
|
||||
private int myTypeInfoIndex = -1;
|
||||
|
||||
public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, ClassDescriptor classDescriptor, OwnerKind kind) {
|
||||
public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, boolean hasThis0) {
|
||||
enterTemp(); // this
|
||||
if (descriptor != null) {
|
||||
if (CodegenUtil.hasThis0(classDescriptor)) {
|
||||
if (hasThis0) {
|
||||
myOuterThisIndex = enterTemp(); // outer class instance
|
||||
}
|
||||
}
|
||||
|
||||
@@ -809,7 +809,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
if(closureCodegen.superCall != null) {
|
||||
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, closureCodegen.superCall.getCalleeExpression().getConstructorReferenceExpression());
|
||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
|
||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(superConstructor.getContainingDeclaration()));
|
||||
Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes();
|
||||
Collections.addAll(consArgTypes, argumentTypes);
|
||||
ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, closureCodegen.superCall.getCalleeExpression());
|
||||
@@ -2258,7 +2258,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
receiver.put(receiver.type, v);
|
||||
}
|
||||
|
||||
CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(((ConstructorDescriptor) constructorDescriptor).getContainingDeclaration()));
|
||||
invokeMethodWithArguments(method, expression, StackValue.none());
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -28,11 +28,11 @@ import java.util.List;
|
||||
public class GeneratedAnonymousClassDescriptor {
|
||||
private final String classname;
|
||||
private Method constructor;
|
||||
private final boolean captureThis;
|
||||
private final Type captureThis;
|
||||
private final Type captureReceiver;
|
||||
private List<StackValue> args = new ArrayList<StackValue>();
|
||||
|
||||
public GeneratedAnonymousClassDescriptor(String classname, Method constructor, boolean captureThis, Type captureReceiver) {
|
||||
public GeneratedAnonymousClassDescriptor(String classname, Method constructor, Type captureThis, Type captureReceiver) {
|
||||
this.classname = classname;
|
||||
this.constructor = constructor;
|
||||
this.captureThis = captureThis;
|
||||
@@ -56,7 +56,7 @@ public class GeneratedAnonymousClassDescriptor {
|
||||
}
|
||||
|
||||
public boolean isCaptureThis() {
|
||||
return captureThis;
|
||||
return captureThis != null;
|
||||
}
|
||||
|
||||
public Type isCaptureReceiver() {
|
||||
|
||||
@@ -22,7 +22,6 @@ package org.jetbrains.jet.codegen;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
||||
@@ -102,7 +101,7 @@ public class GenerationState {
|
||||
}
|
||||
|
||||
public Pair<String, ClassBuilder> forAnonymousSubclass(JetExpression expression) {
|
||||
String className = typeMapper.classNameForAnonymousClass(expression);
|
||||
String className = typeMapper.getClosureAnnotator().classNameForAnonymousClass(expression);
|
||||
return Pair.create(className, factory.forAnonymousSubclass(className));
|
||||
}
|
||||
|
||||
@@ -113,7 +112,7 @@ public class GenerationState {
|
||||
public BindingContext compile(JetFile file) {
|
||||
final BindingContext bindingContext = AnalyzerFacade.analyzeOneFileWithJavaIntegration(file, JetControlFlowDataTraceFactory.EMPTY);
|
||||
AnalyzingUtils.throwExceptionOnErrors(bindingContext);
|
||||
compileCorrectFiles(bindingContext, Collections.singletonList(file));
|
||||
compileCorrectFiles(bindingContext, Collections.singletonList(file), CompilationErrorHandler.THROW_EXCEPTION, true);
|
||||
return bindingContext;
|
||||
// NamespaceCodegen codegen = forNamespace(namespace);
|
||||
// bindingContexts.push(bindingContext);
|
||||
@@ -129,12 +128,13 @@ public class GenerationState {
|
||||
// }
|
||||
}
|
||||
|
||||
public void compileCorrectFiles(BindingContext bindingContext, List<JetFile> files) {
|
||||
compileCorrectFiles(bindingContext, files, CompilationErrorHandler.THROW_EXCEPTION);
|
||||
public void compileCorrectFiles(BindingContext bindingContext, List<JetFile> files, boolean annotate) {
|
||||
compileCorrectFiles(bindingContext, files, CompilationErrorHandler.THROW_EXCEPTION, annotate);
|
||||
}
|
||||
|
||||
public void compileCorrectFiles(BindingContext bindingContext, List<JetFile> files, CompilationErrorHandler errorHandler) {
|
||||
typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
||||
public void compileCorrectFiles(BindingContext bindingContext, List<JetFile> files, CompilationErrorHandler errorHandler, boolean annotate) {
|
||||
ClosureAnnotator closureAnnotator = !annotate ? null : new ClosureAnnotator(bindingContext, files);
|
||||
typeMapper = new JetTypeMapper(standardLibrary, bindingContext, closureAnnotator);
|
||||
bindingContexts.push(bindingContext);
|
||||
try {
|
||||
for (JetFile namespace : files) {
|
||||
@@ -172,30 +172,10 @@ public class GenerationState {
|
||||
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate();
|
||||
|
||||
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
|
||||
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
||||
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature().getAsmMethod(), objectContext.outerWasUsed, null);
|
||||
}
|
||||
|
||||
public static void prepareAnonymousClasses(PsiElement element, final JetTypeMapper typeMapper) {
|
||||
element.acceptChildren(new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitJetElement(JetElement element) {
|
||||
super.visitJetElement(element);
|
||||
element.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) {
|
||||
typeMapper.classNameForAnonymousClass(expression.getObjectDeclaration());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) {
|
||||
typeMapper.classNameForAnonymousClass(expression.getFunctionLiteral());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String createText() {
|
||||
StringBuilder answer = new StringBuilder();
|
||||
|
||||
|
||||
@@ -403,6 +403,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
JvmMethodSignature constructorMethod;
|
||||
CallableMethod callableMethod;
|
||||
boolean hasThis0 = typeMapper.hasThis0(descriptor);
|
||||
if (constructorDescriptor == null) {
|
||||
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
|
||||
|
||||
@@ -411,9 +412,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
signatureWriter.writeParametersStart();
|
||||
|
||||
if (CodegenUtil.hasThis0(descriptor)) {
|
||||
if (hasThis0) {
|
||||
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0);
|
||||
typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION, signatureWriter, false);
|
||||
typeMapper.mapType(typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION, signatureWriter, false);
|
||||
signatureWriter.writeParameterTypeEnd();
|
||||
}
|
||||
|
||||
@@ -425,7 +426,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
callableMethod = new CallableMethod("", "", "", constructorMethod, INVOKESPECIAL);
|
||||
}
|
||||
else {
|
||||
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
|
||||
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
||||
constructorMethod = callableMethod.getSignature();
|
||||
}
|
||||
|
||||
@@ -435,13 +436,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
int insert = 0;
|
||||
if(closure != null) {
|
||||
if(closure.captureThis) {
|
||||
if(!CodegenUtil.hasThis0(descriptor))
|
||||
if(closure.captureThis != null) {
|
||||
if(!hasThis0)
|
||||
consArgTypes.add(insert, new JvmMethodParameterSignature(Type.getObjectType(context.getThisDescriptor().getName()), "", JvmMethodParameterKind.THIS0));
|
||||
insert++;
|
||||
}
|
||||
else {
|
||||
if(CodegenUtil.hasThis0(descriptor))
|
||||
if(hasThis0)
|
||||
insert++;
|
||||
}
|
||||
|
||||
@@ -469,7 +470,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
declarationDescriptor = ((ClassDescriptor)declarationDescriptor).getUnsubstitutedPrimaryConstructor();
|
||||
}
|
||||
ConstructorDescriptor superConstructor = (ConstructorDescriptor) declarationDescriptor;
|
||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
|
||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(superConstructor.getContainingDeclaration()));
|
||||
firstSuperArgument = insert;
|
||||
for(Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
|
||||
consArgTypes.add(insert++, new JvmMethodParameterSignature(t, "", JvmMethodParameterKind.SHARED_VAR));
|
||||
@@ -494,7 +495,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
if (constructorDescriptor != null) {
|
||||
int i = 0;
|
||||
|
||||
if (CodegenUtil.hasThis0(descriptor)) {
|
||||
if (hasThis0) {
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -514,7 +515,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
? constructorDescriptor.getValueParameters()
|
||||
: Collections.<ValueParameterDescriptor>emptyList();
|
||||
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, descriptor, kind);
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, hasThis0);
|
||||
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, constructorContext, state);
|
||||
@@ -548,9 +549,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
List<Type> parameterTypes = new ArrayList<Type>();
|
||||
assert superType != null;
|
||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||
if (CodegenUtil.hasThis0(superClassDescriptor)) {
|
||||
if (typeMapper.hasThis0(superClassDescriptor)) {
|
||||
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
||||
parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
|
||||
parameterTypes.add(typeMapper.mapType(typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
|
||||
}
|
||||
Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||
iv.invokespecial(typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "<init>", superCallMethod.getDescriptor());
|
||||
@@ -587,9 +588,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
final ClassDescriptor outerDescriptor = getOuterClassDescriptor();
|
||||
if (outerDescriptor != null && !CodegenUtil.isClassObject(outerDescriptor)) {
|
||||
final Type type = typeMapper.mapType(outerDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION);
|
||||
final ClassDescriptor outerDescriptor = typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor);
|
||||
if (typeMapper.hasThis0(descriptor) && outerDescriptor != null) {
|
||||
final Type type = typeMapper.mapType(outerDescriptor.getDefaultType());
|
||||
String interfaceDesc = type.getDescriptor();
|
||||
final String fieldName = "this$0";
|
||||
v.newField(myClass, ACC_FINAL, fieldName, interfaceDesc, null, null);
|
||||
@@ -714,15 +715,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ClassDescriptor getOuterClassDescriptor() {
|
||||
if (myClass.getParent() instanceof JetClassObject) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return CodegenUtil.getOuterClassDescriptor(descriptor);
|
||||
}
|
||||
|
||||
private void generateDelegatorToConstructorCall(InstructionAdapter iv, ExpressionCodegen codegen, JetCallElement constructorCall,
|
||||
ConstructorDescriptor constructorDescriptor,
|
||||
ConstructorFrameMap frameMap, int firstSuperArgument) {
|
||||
@@ -734,11 +726,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.load(frameMap.getOuterThisIndex(), typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), OwnerKind.IMPLEMENTATION));
|
||||
}
|
||||
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
||||
|
||||
if(myClass instanceof JetObjectDeclaration && superCall instanceof JetDelegatorToSuperCall && ((JetObjectDeclaration) myClass).isObjectLiteral()) {
|
||||
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
|
||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
|
||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(superConstructor.getContainingDeclaration()));
|
||||
int nextVar = firstSuperArgument+1;
|
||||
for(Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
|
||||
iv.load(nextVar, t);
|
||||
@@ -799,7 +791,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
if (specifier instanceof JetDelegatorToSuperCall) {
|
||||
final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier;
|
||||
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
||||
codegen.invokeMethodWithArguments(method, superCall, StackValue.none());
|
||||
}
|
||||
else {
|
||||
@@ -818,13 +810,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
if (constructorDescriptor == null) {
|
||||
throw new UnsupportedOperationException("failed to get descriptor for secondary constructor");
|
||||
}
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
||||
int flags = ACC_PUBLIC; // TODO
|
||||
final MethodVisitor mv = v.newMethod(constructor, flags, "<init>", method.getSignature().getAsmMethod().getDescriptor(), null, null);
|
||||
if (v.generateCode()) {
|
||||
mv.visitCode();
|
||||
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, descriptor, kind);
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
||||
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
||||
|
||||
@@ -21,10 +21,12 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.*;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -51,9 +53,17 @@ public class JetTypeMapper {
|
||||
public static final Type ARRAY_GENERIC_TYPE = Type.getType(Object[].class);
|
||||
|
||||
private final JetStandardLibrary standardLibrary;
|
||||
private final BindingContext bindingContext;
|
||||
private final Map<JetElement, String> classNamesForAnonymousClasses = new HashMap<JetElement, String>();
|
||||
private final Map<String, Integer> anonymousSubclassesCount = new HashMap<String, Integer>();
|
||||
public final BindingContext bindingContext;
|
||||
|
||||
public boolean hasThis0(ClassDescriptor classDescriptor) {
|
||||
return closureAnnotator.hasThis0(classDescriptor);
|
||||
}
|
||||
|
||||
public ClosureAnnotator getClosureAnnotator() {
|
||||
return closureAnnotator;
|
||||
}
|
||||
|
||||
private final ClosureAnnotator closureAnnotator;
|
||||
|
||||
private final HashMap<JetType,String> knowTypeNames = new HashMap<JetType, String>();
|
||||
private final HashMap<JetType,Type> knowTypes = new HashMap<JetType, Type>();
|
||||
@@ -72,13 +82,10 @@ public class JetTypeMapper {
|
||||
public static final Type TYPE_FUNCTION0 = Type.getObjectType("jet/Function0");
|
||||
public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
|
||||
|
||||
public JetStandardLibrary getStandardLibrary() {
|
||||
return standardLibrary;
|
||||
}
|
||||
|
||||
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
|
||||
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext, ClosureAnnotator closureAnnotator) {
|
||||
this.standardLibrary = standardLibrary;
|
||||
this.bindingContext = bindingContext;
|
||||
this.closureAnnotator = closureAnnotator;
|
||||
initKnownTypes();
|
||||
initKnownTypeNames();
|
||||
}
|
||||
@@ -193,7 +200,7 @@ public class JetTypeMapper {
|
||||
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||
String name = descriptor.getName();
|
||||
if(JetPsiUtil.NO_NAME_PROVIDED.equals(name)) {
|
||||
return classNameForAnonymousClass((JetElement) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor));
|
||||
return closureAnnotator.classNameForAnonymousClass((JetElement) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor));
|
||||
}
|
||||
if(name.contains("/"))
|
||||
return name;
|
||||
@@ -667,21 +674,20 @@ public class JetTypeMapper {
|
||||
return new JvmPropertyAccessorSignature(jvmMethodSignature, jvmMethodSignature.getKotlinParameterType(jvmMethodSignature.getParameterCount() - 1));
|
||||
}
|
||||
|
||||
private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor) {
|
||||
private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, boolean hasThis0) {
|
||||
|
||||
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
|
||||
|
||||
List<ValueParameterDescriptor> parameters = descriptor.getOriginal().getValueParameters();
|
||||
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
|
||||
|
||||
// constructor type parmeters are fake
|
||||
writeFormalTypeParameters(Collections.<TypeParameterDescriptor>emptyList(), signatureWriter);
|
||||
|
||||
signatureWriter.writeParametersStart();
|
||||
|
||||
if (CodegenUtil.hasThis0(classDescriptor)) {
|
||||
if (hasThis0) {
|
||||
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0);
|
||||
mapType(CodegenUtil.getOuterClassDescriptor(classDescriptor).getDefaultType(), OwnerKind.IMPLEMENTATION, signatureWriter);
|
||||
mapType(closureAnnotator.getEclosingClassDescriptor(descriptor.getContainingDeclaration()).getDefaultType(), OwnerKind.IMPLEMENTATION, signatureWriter);
|
||||
signatureWriter.writeParameterTypeEnd();
|
||||
}
|
||||
|
||||
@@ -698,8 +704,8 @@ public class JetTypeMapper {
|
||||
return signatureWriter.makeJvmMethodSignature("<init>");
|
||||
}
|
||||
|
||||
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) {
|
||||
final JvmMethodSignature method = mapConstructorSignature(descriptor);
|
||||
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind, boolean hasThis0) {
|
||||
final JvmMethodSignature method = mapConstructorSignature(descriptor, hasThis0);
|
||||
String owner = mapType(descriptor.getContainingDeclaration().getDefaultType(), kind).getInternalName();
|
||||
return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL);
|
||||
}
|
||||
@@ -726,54 +732,6 @@ public class JetTypeMapper {
|
||||
}
|
||||
}
|
||||
|
||||
String classNameForAnonymousClass(JetElement expression) {
|
||||
if(expression instanceof JetObjectLiteralExpression) {
|
||||
JetObjectLiteralExpression jetObjectLiteralExpression = (JetObjectLiteralExpression) expression;
|
||||
expression = jetObjectLiteralExpression.getObjectDeclaration();
|
||||
}
|
||||
|
||||
if(expression instanceof JetFunctionLiteralExpression) {
|
||||
JetFunctionLiteralExpression jetFunctionLiteralExpression = (JetFunctionLiteralExpression) expression;
|
||||
expression = jetFunctionLiteralExpression.getFunctionLiteral();
|
||||
}
|
||||
|
||||
String name = classNamesForAnonymousClasses.get(expression);
|
||||
if (name != null) {
|
||||
return name;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
PsiElement container = PsiTreeUtil.getParentOfType(expression, JetFile.class, JetClass.class, JetObjectDeclaration.class, JetFunctionLiteral.class);
|
||||
|
||||
String baseName;
|
||||
if(container instanceof JetFile) {
|
||||
baseName = NamespaceCodegen.getJVMClassName(JetPsiUtil.getFQName(((JetFile) container)), true);
|
||||
}
|
||||
else if(container instanceof JetClass) {
|
||||
ClassDescriptor aClass = bindingContext.get(BindingContext.CLASS, container);
|
||||
baseName = mapType(aClass.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
|
||||
|
||||
ClassDescriptor myClass = bindingContext.get(BindingContext.CLASS, expression);
|
||||
if(CodegenUtil.isClassObject(myClass)) {
|
||||
return mapType(aClass.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName() + JvmAbi.CLASS_OBJECT_SUFFIX;
|
||||
}
|
||||
else
|
||||
baseName = classNameForAnonymousClass((JetElement) container);
|
||||
}
|
||||
else {
|
||||
baseName = classNameForAnonymousClass((JetElement) container);
|
||||
}
|
||||
|
||||
Integer count = anonymousSubclassesCount.get(baseName);
|
||||
if (count == null) count = 0;
|
||||
|
||||
anonymousSubclassesCount.put(baseName, count + 1);
|
||||
|
||||
final String className = baseName + "$" + (count + 1);
|
||||
classNamesForAnonymousClasses.put(expression, className);
|
||||
return className;
|
||||
}
|
||||
|
||||
public Collection<String> allJvmNames(JetClassOrObject jetClass) {
|
||||
Set<String> result = new HashSet<String>();
|
||||
final ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, jetClass);
|
||||
@@ -856,7 +814,7 @@ public class JetTypeMapper {
|
||||
}
|
||||
else if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
|
||||
PsiElement psiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor);
|
||||
return Type.getObjectType(classNameForAnonymousClass((JetElement) psiElement));
|
||||
return Type.getObjectType(closureAnnotator.classNameForAnonymousClass((JetElement) psiElement));
|
||||
}
|
||||
else if (descriptor instanceof FunctionDescriptor) {
|
||||
return StackValue.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType()));
|
||||
|
||||
@@ -24,9 +24,7 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
public enum JvmMethodParameterKind {
|
||||
VALUE,
|
||||
THIS,
|
||||
/** @see CodegenUtil#hasThis0(ClassDescriptor) */
|
||||
THIS0,
|
||||
RECEIVER,
|
||||
TYPE_INFO,
|
||||
SHARED_VAR,
|
||||
}
|
||||
|
||||
@@ -17,24 +17,15 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
/**
|
||||
@@ -68,10 +59,6 @@ public class NamespaceCodegen {
|
||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
||||
final ClassCodegen classCodegen = state.forClass();
|
||||
|
||||
if (v.generateCode()) {
|
||||
GenerationState.prepareAnonymousClasses(file, state.getTypeMapper());
|
||||
}
|
||||
|
||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
propertyCodegen.gen((JetProperty) declaration);
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.Map;
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class ObjectOrClosureCodegen {
|
||||
protected boolean captureThis;
|
||||
protected Type captureThis;
|
||||
protected Type captureReceiver;
|
||||
|
||||
public final GenerationState state;
|
||||
@@ -83,7 +83,7 @@ public class ObjectOrClosureCodegen {
|
||||
if (idx < 0) return null;
|
||||
|
||||
JetElement expression = (JetElement) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, vd);
|
||||
String cn = state.getTypeMapper().classNameForAnonymousClass(expression);
|
||||
String cn = state.getTypeMapper().getClosureAnnotator().classNameForAnonymousClass(expression);
|
||||
Type localType = Type.getObjectType(cn);
|
||||
|
||||
StackValue outerValue = StackValue.local(idx, localType);
|
||||
@@ -131,6 +131,6 @@ public class ObjectOrClosureCodegen {
|
||||
}
|
||||
|
||||
public boolean isConst () {
|
||||
return !captureThis && captureReceiver != null && closure.isEmpty();
|
||||
return captureThis == null && captureReceiver == null && closure.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,10 +25,7 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.codegen.ClassBuilderFactory;
|
||||
import org.jetbrains.jet.codegen.ClassFileFactory;
|
||||
import org.jetbrains.jet.codegen.GenerationState;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.*;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
|
||||
@@ -201,7 +198,7 @@ public class CompileSession {
|
||||
public ClassFileFactory generate() {
|
||||
Project project = myEnvironment.getProject();
|
||||
GenerationState generationState = new GenerationState(project, ClassBuilderFactory.BINARIES, myFileNameTransformer);
|
||||
generationState.compileCorrectFiles(myBindingContext, mySourceFiles);
|
||||
generationState.compileCorrectFiles(myBindingContext, mySourceFiles, CompilationErrorHandler.THROW_EXCEPTION, true);
|
||||
ClassFileFactory answer = generationState.getFactory();
|
||||
|
||||
List<CompilerPlugin> fileProcessors = myEnvironment.getCompilerPlugins();
|
||||
|
||||
@@ -43,7 +43,9 @@ import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.codegen.ClassBuilder;
|
||||
import org.jetbrains.jet.codegen.ClassBuilderFactory;
|
||||
import org.jetbrains.jet.codegen.CompilationErrorHandler;
|
||||
import org.jetbrains.jet.codegen.GenerationState;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -184,8 +186,10 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa
|
||||
};
|
||||
|
||||
List<JetFile> files = Collections.singletonList(file);
|
||||
final BindingContext context = AnalyzerFacade.shallowAnalyzeFiles(files);
|
||||
state.compileCorrectFiles(context, files);
|
||||
//todo:
|
||||
// final BindingContext context = AnalyzerFacade.shallowAnalyzeFiles(files);
|
||||
final BindingContext context = AnalyzerFacade.analyzeOneFileWithJavaIntegration(file, JetControlFlowDataTraceFactory.EMPTY);
|
||||
state.compileCorrectFiles(context, files, CompilationErrorHandler.THROW_EXCEPTION, true);
|
||||
state.getFactory().files();
|
||||
|
||||
return answer;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package p
|
||||
|
||||
class C(val y : Int) {
|
||||
val initChild = { ->
|
||||
object : java.lang.Object() {
|
||||
override fun toString(): String {
|
||||
return "child" + y
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val c = C(3).initChild
|
||||
val x = c().toString()
|
||||
return if(x == "child3") "OK" else x
|
||||
}
|
||||
@@ -31,6 +31,11 @@ public class ObjectGenTest extends CodegenTestCase {
|
||||
// System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testObjectLiteralInClosure() throws Exception {
|
||||
blackBoxFile("objects/objectLiteralInClosure.jet");
|
||||
// System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testMethodOnObject() throws Exception {
|
||||
blackBoxFile("objects/methodOnObject.jet");
|
||||
}
|
||||
|
||||
@@ -96,7 +96,8 @@ public class TestlibTest extends CodegenTestCase {
|
||||
new URLClassLoader(new URL[]{ForTestCompileStdlib.stdlibJarForTests().toURI().toURL(), junitJar.toURI().toURL()},
|
||||
TestCase.class.getClassLoader()));
|
||||
|
||||
JetTypeMapper typeMapper = new JetTypeMapper(classFileFactory.state.getStandardLibrary(), session.getMyBindingContext());
|
||||
ClosureAnnotator closureAnnotator = new ClosureAnnotator(session.getMyBindingContext(), session.getSourceFileNamespaces());
|
||||
JetTypeMapper typeMapper = new JetTypeMapper(classFileFactory.state.getStandardLibrary(), session.getMyBindingContext(), closureAnnotator);
|
||||
TestSuite suite = new TestSuite("stdlib_test");
|
||||
try {
|
||||
for(JetFile jetFile : session.getSourceFileNamespaces()) {
|
||||
|
||||
@@ -34,7 +34,7 @@ import com.sun.jdi.ReferenceType;
|
||||
import com.sun.jdi.request.ClassPrepareRequest;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.GenerationState;
|
||||
import org.jetbrains.jet.codegen.ClosureAnnotator;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.NamespaceCodegen;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
@@ -154,18 +154,8 @@ public class JetPositionManager implements PositionManager {
|
||||
}
|
||||
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
||||
final JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
|
||||
final JetTypeMapper typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
||||
file.acceptChildren(new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitJetElement(JetElement element) {
|
||||
element.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClass(JetClass klass) {
|
||||
GenerationState.prepareAnonymousClasses(klass, typeMapper);
|
||||
}
|
||||
});
|
||||
ClosureAnnotator closureAnnotator = new ClosureAnnotator(bindingContext, Collections.singleton(file));
|
||||
final JetTypeMapper typeMapper = new JetTypeMapper(standardLibrary, bindingContext, closureAnnotator);
|
||||
myTypeMappers.put(file, typeMapper);
|
||||
return typeMapper;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.intellij.psi.PsiManager;
|
||||
import com.intellij.util.Alarm;
|
||||
import org.jetbrains.jet.codegen.ClassBuilderFactory;
|
||||
import org.jetbrains.jet.codegen.ClassFileFactory;
|
||||
import org.jetbrains.jet.codegen.CompilationErrorHandler;
|
||||
import org.jetbrains.jet.codegen.GenerationState;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
@@ -203,7 +204,7 @@ public class BytecodeToolwindow extends JPanel implements Disposable {
|
||||
try {
|
||||
BindingContext binding = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
||||
AnalyzingUtils.throwExceptionOnErrors(binding);
|
||||
state.compileCorrectFiles(binding, Collections.singletonList(file));
|
||||
state.compileCorrectFiles(binding, Collections.singletonList(file), CompilationErrorHandler.THROW_EXCEPTION, true);
|
||||
} catch (Exception e) {
|
||||
StringWriter out = new StringWriter(1024);
|
||||
e.printStackTrace(new PrintWriter(out));
|
||||
|
||||
Reference in New Issue
Block a user