refactoring in progress
This commit is contained in:
@@ -37,9 +37,6 @@ public class ClassCodegen {
|
|||||||
public void generate(CodegenContext context, JetClassOrObject aClass) {
|
public void generate(CodegenContext context, JetClassOrObject aClass) {
|
||||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||||
ClassBuilder classBuilder = state.forClassImplementation(descriptor);
|
ClassBuilder classBuilder = state.forClassImplementation(descriptor);
|
||||||
if (classBuilder.generateCode()) {
|
|
||||||
GenerationState.prepareAnonymousClasses(aClass, state.getTypeMapper());
|
|
||||||
}
|
|
||||||
|
|
||||||
final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION, 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.openapi.util.Pair;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
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.JetDeclarationWithBody;
|
||||||
import org.jetbrains.jet.lang.psi.JetElement;
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
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.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
@@ -40,7 +38,6 @@ import org.objectweb.asm.commons.Method;
|
|||||||
import org.objectweb.asm.signature.SignatureWriter;
|
import org.objectweb.asm.signature.SignatureWriter;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.objectweb.asm.Opcodes.*;
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
@@ -136,11 +133,11 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
ClassDescriptor thisDescriptor = context.getThisDescriptor();
|
ClassDescriptor thisDescriptor = context.getThisDescriptor();
|
||||||
final Type enclosingType = thisDescriptor == null ? null : state.getTypeMapper().mapType(thisDescriptor.getDefaultType());
|
final Type enclosingType = thisDescriptor == null ? null : state.getTypeMapper().mapType(thisDescriptor.getDefaultType());
|
||||||
if (enclosingType == null)
|
if (enclosingType == null)
|
||||||
captureThis = false;
|
captureThis = null;
|
||||||
|
|
||||||
final Method constructor = generateConstructor(funClass, fun);
|
final Method constructor = generateConstructor(funClass, fun);
|
||||||
|
|
||||||
if (captureThis) {
|
if (captureThis != null) {
|
||||||
cv.newField(fun, ACC_FINAL, "this$0", enclosingType.getDescriptor(), null, 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) {
|
private Type generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetDeclarationWithBody body) {
|
||||||
int arity = funDescriptor.getValueParameters().size();
|
ClassDescriptor function = state.getTypeMapper().getClosureAnnotator().classDescriptorForFunctionDescriptor(funDescriptor, name);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper());
|
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper());
|
||||||
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
||||||
@@ -248,7 +236,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Method generateConstructor(String funClass, PsiElement fun) {
|
private Method generateConstructor(String funClass, PsiElement fun) {
|
||||||
int argCount = captureThis ? 1 : 0;
|
int argCount = captureThis != null ? 1 : 0;
|
||||||
argCount += (captureReceiver != null ? 1 : 0);
|
argCount += (captureReceiver != null ? 1 : 0);
|
||||||
|
|
||||||
ArrayList<DeclarationDescriptor> variableDescriptors = new ArrayList<DeclarationDescriptor>();
|
ArrayList<DeclarationDescriptor> variableDescriptors = new ArrayList<DeclarationDescriptor>();
|
||||||
@@ -270,7 +258,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
Type[] argTypes = new Type[argCount];
|
Type[] argTypes = new Type[argCount];
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (captureThis) {
|
if (captureThis != null) {
|
||||||
argTypes[i++] = state.getTypeMapper().mapType(context.getThisDescriptor().getDefaultType());
|
argTypes[i++] = state.getTypeMapper().mapType(context.getThisDescriptor().getDefaultType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,7 +273,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
argTypes[i++] = type;
|
argTypes[i++] = type;
|
||||||
}
|
}
|
||||||
else if(CodegenUtil.isNamedFun(descriptor, state.getBindingContext()) && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
|
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;
|
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(0, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
|
||||||
StackValue.local(i, type).put(type, iv);
|
StackValue.local(i, type).put(type, iv);
|
||||||
final String fieldName;
|
final String fieldName;
|
||||||
if (captureThis && i == 1) {
|
if (captureThis != null && i == 1) {
|
||||||
fieldName = "this$0";
|
fieldName = "this$0";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (captureReceiver != null && (captureThis && i == 2 || !captureThis && i == 1)) {
|
if (captureReceiver != null && (captureThis != null && i == 2 || captureThis == null && i == 1)) {
|
||||||
fieldName = "receiver$0";
|
fieldName = "receiver$0";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public abstract class CodegenContext {
|
|||||||
|
|
||||||
protected StackValue outerExpression;
|
protected StackValue outerExpression;
|
||||||
|
|
||||||
protected boolean outerWasUsed ;
|
protected Type outerWasUsed ;
|
||||||
|
|
||||||
public CodegenContext(DeclarationDescriptor contextType, OwnerKind contextKind, @Nullable CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
|
public CodegenContext(DeclarationDescriptor contextType, OwnerKind contextKind, @Nullable CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
|
||||||
this.contextType = contextType;
|
this.contextType = contextType;
|
||||||
@@ -100,7 +100,7 @@ public abstract class CodegenContext {
|
|||||||
if(outerExpression == null)
|
if(outerExpression == null)
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
outerWasUsed = true;
|
outerWasUsed = outerExpression.type;
|
||||||
return prefix != null ? StackValue.composed(prefix, outerExpression) : outerExpression;
|
return prefix != null ? StackValue.composed(prefix, outerExpression) : outerExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,21 +59,6 @@ public class CodegenUtil {
|
|||||||
return false;
|
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) {
|
public static SimpleFunctionDescriptor createInvoke(FunctionDescriptor fd) {
|
||||||
int arity = fd.getValueParameters().size();
|
int arity = fd.getValueParameters().size();
|
||||||
SimpleFunctionDescriptorImpl invokeDescriptor = new SimpleFunctionDescriptorImpl(
|
SimpleFunctionDescriptorImpl invokeDescriptor = new SimpleFunctionDescriptorImpl(
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
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.ConstructorDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
@@ -33,10 +32,10 @@ public class ConstructorFrameMap extends FrameMap {
|
|||||||
private int myOuterThisIndex = -1;
|
private int myOuterThisIndex = -1;
|
||||||
private int myTypeInfoIndex = -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
|
enterTemp(); // this
|
||||||
if (descriptor != null) {
|
if (descriptor != null) {
|
||||||
if (CodegenUtil.hasThis0(classDescriptor)) {
|
if (hasThis0) {
|
||||||
myOuterThisIndex = enterTemp(); // outer class instance
|
myOuterThisIndex = enterTemp(); // outer class instance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -809,7 +809,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
if(closureCodegen.superCall != null) {
|
if(closureCodegen.superCall != null) {
|
||||||
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, closureCodegen.superCall.getCalleeExpression().getConstructorReferenceExpression());
|
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();
|
Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes();
|
||||||
Collections.addAll(consArgTypes, argumentTypes);
|
Collections.addAll(consArgTypes, argumentTypes);
|
||||||
ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, closureCodegen.superCall.getCalleeExpression());
|
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);
|
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());
|
invokeMethodWithArguments(method, expression, StackValue.none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -28,11 +28,11 @@ import java.util.List;
|
|||||||
public class GeneratedAnonymousClassDescriptor {
|
public class GeneratedAnonymousClassDescriptor {
|
||||||
private final String classname;
|
private final String classname;
|
||||||
private Method constructor;
|
private Method constructor;
|
||||||
private final boolean captureThis;
|
private final Type captureThis;
|
||||||
private final Type captureReceiver;
|
private final Type captureReceiver;
|
||||||
private List<StackValue> args = new ArrayList<StackValue>();
|
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.classname = classname;
|
||||||
this.constructor = constructor;
|
this.constructor = constructor;
|
||||||
this.captureThis = captureThis;
|
this.captureThis = captureThis;
|
||||||
@@ -56,7 +56,7 @@ public class GeneratedAnonymousClassDescriptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCaptureThis() {
|
public boolean isCaptureThis() {
|
||||||
return captureThis;
|
return captureThis != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type isCaptureReceiver() {
|
public Type isCaptureReceiver() {
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ package org.jetbrains.jet.codegen;
|
|||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.intellij.openapi.util.Pair;
|
||||||
import com.intellij.psi.PsiElement;
|
|
||||||
import com.intellij.util.containers.Stack;
|
import com.intellij.util.containers.Stack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
||||||
@@ -102,7 +101,7 @@ public class GenerationState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Pair<String, ClassBuilder> forAnonymousSubclass(JetExpression expression) {
|
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));
|
return Pair.create(className, factory.forAnonymousSubclass(className));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +112,7 @@ public class GenerationState {
|
|||||||
public BindingContext compile(JetFile file) {
|
public BindingContext compile(JetFile file) {
|
||||||
final BindingContext bindingContext = AnalyzerFacade.analyzeOneFileWithJavaIntegration(file, JetControlFlowDataTraceFactory.EMPTY);
|
final BindingContext bindingContext = AnalyzerFacade.analyzeOneFileWithJavaIntegration(file, JetControlFlowDataTraceFactory.EMPTY);
|
||||||
AnalyzingUtils.throwExceptionOnErrors(bindingContext);
|
AnalyzingUtils.throwExceptionOnErrors(bindingContext);
|
||||||
compileCorrectFiles(bindingContext, Collections.singletonList(file));
|
compileCorrectFiles(bindingContext, Collections.singletonList(file), CompilationErrorHandler.THROW_EXCEPTION, true);
|
||||||
return bindingContext;
|
return bindingContext;
|
||||||
// NamespaceCodegen codegen = forNamespace(namespace);
|
// NamespaceCodegen codegen = forNamespace(namespace);
|
||||||
// bindingContexts.push(bindingContext);
|
// bindingContexts.push(bindingContext);
|
||||||
@@ -129,12 +128,13 @@ public class GenerationState {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void compileCorrectFiles(BindingContext bindingContext, List<JetFile> files) {
|
public void compileCorrectFiles(BindingContext bindingContext, List<JetFile> files, boolean annotate) {
|
||||||
compileCorrectFiles(bindingContext, files, CompilationErrorHandler.THROW_EXCEPTION);
|
compileCorrectFiles(bindingContext, files, CompilationErrorHandler.THROW_EXCEPTION, annotate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void compileCorrectFiles(BindingContext bindingContext, List<JetFile> files, CompilationErrorHandler errorHandler) {
|
public void compileCorrectFiles(BindingContext bindingContext, List<JetFile> files, CompilationErrorHandler errorHandler, boolean annotate) {
|
||||||
typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
ClosureAnnotator closureAnnotator = !annotate ? null : new ClosureAnnotator(bindingContext, files);
|
||||||
|
typeMapper = new JetTypeMapper(standardLibrary, bindingContext, closureAnnotator);
|
||||||
bindingContexts.push(bindingContext);
|
bindingContexts.push(bindingContext);
|
||||||
try {
|
try {
|
||||||
for (JetFile namespace : files) {
|
for (JetFile namespace : files) {
|
||||||
@@ -172,30 +172,10 @@ public class GenerationState {
|
|||||||
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate();
|
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate();
|
||||||
|
|
||||||
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
|
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);
|
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() {
|
public String createText() {
|
||||||
StringBuilder answer = new StringBuilder();
|
StringBuilder answer = new StringBuilder();
|
||||||
|
|
||||||
|
|||||||
@@ -403,6 +403,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
JvmMethodSignature constructorMethod;
|
JvmMethodSignature constructorMethod;
|
||||||
CallableMethod callableMethod;
|
CallableMethod callableMethod;
|
||||||
|
boolean hasThis0 = typeMapper.hasThis0(descriptor);
|
||||||
if (constructorDescriptor == null) {
|
if (constructorDescriptor == null) {
|
||||||
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
|
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
|
||||||
|
|
||||||
@@ -411,9 +412,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
signatureWriter.writeParametersStart();
|
signatureWriter.writeParametersStart();
|
||||||
|
|
||||||
if (CodegenUtil.hasThis0(descriptor)) {
|
if (hasThis0) {
|
||||||
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0);
|
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();
|
signatureWriter.writeParameterTypeEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,7 +426,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
callableMethod = new CallableMethod("", "", "", constructorMethod, INVOKESPECIAL);
|
callableMethod = new CallableMethod("", "", "", constructorMethod, INVOKESPECIAL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
|
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
|
||||||
constructorMethod = callableMethod.getSignature();
|
constructorMethod = callableMethod.getSignature();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,13 +436,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
int insert = 0;
|
int insert = 0;
|
||||||
if(closure != null) {
|
if(closure != null) {
|
||||||
if(closure.captureThis) {
|
if(closure.captureThis != null) {
|
||||||
if(!CodegenUtil.hasThis0(descriptor))
|
if(!hasThis0)
|
||||||
consArgTypes.add(insert, new JvmMethodParameterSignature(Type.getObjectType(context.getThisDescriptor().getName()), "", JvmMethodParameterKind.THIS0));
|
consArgTypes.add(insert, new JvmMethodParameterSignature(Type.getObjectType(context.getThisDescriptor().getName()), "", JvmMethodParameterKind.THIS0));
|
||||||
insert++;
|
insert++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(CodegenUtil.hasThis0(descriptor))
|
if(hasThis0)
|
||||||
insert++;
|
insert++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,7 +470,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
declarationDescriptor = ((ClassDescriptor)declarationDescriptor).getUnsubstitutedPrimaryConstructor();
|
declarationDescriptor = ((ClassDescriptor)declarationDescriptor).getUnsubstitutedPrimaryConstructor();
|
||||||
}
|
}
|
||||||
ConstructorDescriptor superConstructor = (ConstructorDescriptor) declarationDescriptor;
|
ConstructorDescriptor superConstructor = (ConstructorDescriptor) declarationDescriptor;
|
||||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
|
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(superConstructor.getContainingDeclaration()));
|
||||||
firstSuperArgument = insert;
|
firstSuperArgument = insert;
|
||||||
for(Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
|
for(Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
|
||||||
consArgTypes.add(insert++, new JvmMethodParameterSignature(t, "", JvmMethodParameterKind.SHARED_VAR));
|
consArgTypes.add(insert++, new JvmMethodParameterSignature(t, "", JvmMethodParameterKind.SHARED_VAR));
|
||||||
@@ -494,7 +495,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
if (constructorDescriptor != null) {
|
if (constructorDescriptor != null) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
if (CodegenUtil.hasThis0(descriptor)) {
|
if (hasThis0) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,7 +515,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
? constructorDescriptor.getValueParameters()
|
? constructorDescriptor.getValueParameters()
|
||||||
: Collections.<ValueParameterDescriptor>emptyList();
|
: Collections.<ValueParameterDescriptor>emptyList();
|
||||||
|
|
||||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, descriptor, kind);
|
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, hasThis0);
|
||||||
|
|
||||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, constructorContext, state);
|
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>();
|
List<Type> parameterTypes = new ArrayList<Type>();
|
||||||
assert superType != null;
|
assert superType != null;
|
||||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||||
if (CodegenUtil.hasThis0(superClassDescriptor)) {
|
if (typeMapper.hasThis0(superClassDescriptor)) {
|
||||||
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
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()]));
|
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());
|
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();
|
final ClassDescriptor outerDescriptor = typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor);
|
||||||
if (outerDescriptor != null && !CodegenUtil.isClassObject(outerDescriptor)) {
|
if (typeMapper.hasThis0(descriptor) && outerDescriptor != null) {
|
||||||
final Type type = typeMapper.mapType(outerDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION);
|
final Type type = typeMapper.mapType(outerDescriptor.getDefaultType());
|
||||||
String interfaceDesc = type.getDescriptor();
|
String interfaceDesc = type.getDescriptor();
|
||||||
final String fieldName = "this$0";
|
final String fieldName = "this$0";
|
||||||
v.newField(myClass, ACC_FINAL, fieldName, interfaceDesc, null, null);
|
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,
|
private void generateDelegatorToConstructorCall(InstructionAdapter iv, ExpressionCodegen codegen, JetCallElement constructorCall,
|
||||||
ConstructorDescriptor constructorDescriptor,
|
ConstructorDescriptor constructorDescriptor,
|
||||||
ConstructorFrameMap frameMap, int firstSuperArgument) {
|
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));
|
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()) {
|
if(myClass instanceof JetObjectDeclaration && superCall instanceof JetDelegatorToSuperCall && ((JetObjectDeclaration) myClass).isObjectLiteral()) {
|
||||||
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
|
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;
|
int nextVar = firstSuperArgument+1;
|
||||||
for(Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
|
for(Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
|
||||||
iv.load(nextVar, t);
|
iv.load(nextVar, t);
|
||||||
@@ -799,7 +791,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
if (specifier instanceof JetDelegatorToSuperCall) {
|
if (specifier instanceof JetDelegatorToSuperCall) {
|
||||||
final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier;
|
final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier;
|
||||||
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
|
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());
|
codegen.invokeMethodWithArguments(method, superCall, StackValue.none());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -818,13 +810,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
if (constructorDescriptor == null) {
|
if (constructorDescriptor == null) {
|
||||||
throw new UnsupportedOperationException("failed to get descriptor for secondary constructor");
|
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
|
int flags = ACC_PUBLIC; // TODO
|
||||||
final MethodVisitor mv = v.newMethod(constructor, flags, "<init>", method.getSignature().getAsmMethod().getDescriptor(), null, null);
|
final MethodVisitor mv = v.newMethod(constructor, flags, "<init>", method.getSignature().getAsmMethod().getDescriptor(), null, null);
|
||||||
if (v.generateCode()) {
|
if (v.generateCode()) {
|
||||||
mv.visitCode();
|
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);
|
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
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.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.java.*;
|
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.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@@ -51,9 +53,17 @@ public class JetTypeMapper {
|
|||||||
public static final Type ARRAY_GENERIC_TYPE = Type.getType(Object[].class);
|
public static final Type ARRAY_GENERIC_TYPE = Type.getType(Object[].class);
|
||||||
|
|
||||||
private final JetStandardLibrary standardLibrary;
|
private final JetStandardLibrary standardLibrary;
|
||||||
private final BindingContext bindingContext;
|
public final BindingContext bindingContext;
|
||||||
private final Map<JetElement, String> classNamesForAnonymousClasses = new HashMap<JetElement, String>();
|
|
||||||
private final Map<String, Integer> anonymousSubclassesCount = new HashMap<String, Integer>();
|
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,String> knowTypeNames = new HashMap<JetType, String>();
|
||||||
private final HashMap<JetType,Type> knowTypes = new HashMap<JetType, Type>();
|
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_FUNCTION0 = Type.getObjectType("jet/Function0");
|
||||||
public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
|
public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
|
||||||
|
|
||||||
public JetStandardLibrary getStandardLibrary() {
|
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext, ClosureAnnotator closureAnnotator) {
|
||||||
return standardLibrary;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
|
|
||||||
this.standardLibrary = standardLibrary;
|
this.standardLibrary = standardLibrary;
|
||||||
this.bindingContext = bindingContext;
|
this.bindingContext = bindingContext;
|
||||||
|
this.closureAnnotator = closureAnnotator;
|
||||||
initKnownTypes();
|
initKnownTypes();
|
||||||
initKnownTypeNames();
|
initKnownTypeNames();
|
||||||
}
|
}
|
||||||
@@ -193,7 +200,7 @@ public class JetTypeMapper {
|
|||||||
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||||
String name = descriptor.getName();
|
String name = descriptor.getName();
|
||||||
if(JetPsiUtil.NO_NAME_PROVIDED.equals(name)) {
|
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("/"))
|
if(name.contains("/"))
|
||||||
return name;
|
return name;
|
||||||
@@ -667,21 +674,20 @@ public class JetTypeMapper {
|
|||||||
return new JvmPropertyAccessorSignature(jvmMethodSignature, jvmMethodSignature.getKotlinParameterType(jvmMethodSignature.getParameterCount() - 1));
|
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);
|
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
|
||||||
|
|
||||||
List<ValueParameterDescriptor> parameters = descriptor.getOriginal().getValueParameters();
|
List<ValueParameterDescriptor> parameters = descriptor.getOriginal().getValueParameters();
|
||||||
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
|
|
||||||
|
|
||||||
// constructor type parmeters are fake
|
// constructor type parmeters are fake
|
||||||
writeFormalTypeParameters(Collections.<TypeParameterDescriptor>emptyList(), signatureWriter);
|
writeFormalTypeParameters(Collections.<TypeParameterDescriptor>emptyList(), signatureWriter);
|
||||||
|
|
||||||
signatureWriter.writeParametersStart();
|
signatureWriter.writeParametersStart();
|
||||||
|
|
||||||
if (CodegenUtil.hasThis0(classDescriptor)) {
|
if (hasThis0) {
|
||||||
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0);
|
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0);
|
||||||
mapType(CodegenUtil.getOuterClassDescriptor(classDescriptor).getDefaultType(), OwnerKind.IMPLEMENTATION, signatureWriter);
|
mapType(closureAnnotator.getEclosingClassDescriptor(descriptor.getContainingDeclaration()).getDefaultType(), OwnerKind.IMPLEMENTATION, signatureWriter);
|
||||||
signatureWriter.writeParameterTypeEnd();
|
signatureWriter.writeParameterTypeEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,8 +704,8 @@ public class JetTypeMapper {
|
|||||||
return signatureWriter.makeJvmMethodSignature("<init>");
|
return signatureWriter.makeJvmMethodSignature("<init>");
|
||||||
}
|
}
|
||||||
|
|
||||||
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) {
|
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind, boolean hasThis0) {
|
||||||
final JvmMethodSignature method = mapConstructorSignature(descriptor);
|
final JvmMethodSignature method = mapConstructorSignature(descriptor, hasThis0);
|
||||||
String owner = mapType(descriptor.getContainingDeclaration().getDefaultType(), kind).getInternalName();
|
String owner = mapType(descriptor.getContainingDeclaration().getDefaultType(), kind).getInternalName();
|
||||||
return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL);
|
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) {
|
public Collection<String> allJvmNames(JetClassOrObject jetClass) {
|
||||||
Set<String> result = new HashSet<String>();
|
Set<String> result = new HashSet<String>();
|
||||||
final ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, jetClass);
|
final ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, jetClass);
|
||||||
@@ -856,7 +814,7 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
else if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
|
else if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
|
||||||
PsiElement psiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor);
|
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) {
|
else if (descriptor instanceof FunctionDescriptor) {
|
||||||
return StackValue.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType()));
|
return StackValue.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType()));
|
||||||
|
|||||||
@@ -24,9 +24,7 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
|||||||
public enum JvmMethodParameterKind {
|
public enum JvmMethodParameterKind {
|
||||||
VALUE,
|
VALUE,
|
||||||
THIS,
|
THIS,
|
||||||
/** @see CodegenUtil#hasThis0(ClassDescriptor) */
|
|
||||||
THIS0,
|
THIS0,
|
||||||
RECEIVER,
|
RECEIVER,
|
||||||
TYPE_INFO,
|
|
||||||
SHARED_VAR,
|
SHARED_VAR,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,24 +17,15 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import com.intellij.psi.PsiFile;
|
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.NamespaceDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
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.MethodVisitor;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.commons.InstructionAdapter;
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.objectweb.asm.Opcodes.*;
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,10 +59,6 @@ public class NamespaceCodegen {
|
|||||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
||||||
final ClassCodegen classCodegen = state.forClass();
|
final ClassCodegen classCodegen = state.forClass();
|
||||||
|
|
||||||
if (v.generateCode()) {
|
|
||||||
GenerationState.prepareAnonymousClasses(file, state.getTypeMapper());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||||
if (declaration instanceof JetProperty) {
|
if (declaration instanceof JetProperty) {
|
||||||
propertyCodegen.gen((JetProperty) declaration);
|
propertyCodegen.gen((JetProperty) declaration);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import java.util.Map;
|
|||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public class ObjectOrClosureCodegen {
|
public class ObjectOrClosureCodegen {
|
||||||
protected boolean captureThis;
|
protected Type captureThis;
|
||||||
protected Type captureReceiver;
|
protected Type captureReceiver;
|
||||||
|
|
||||||
public final GenerationState state;
|
public final GenerationState state;
|
||||||
@@ -83,7 +83,7 @@ public class ObjectOrClosureCodegen {
|
|||||||
if (idx < 0) return null;
|
if (idx < 0) return null;
|
||||||
|
|
||||||
JetElement expression = (JetElement) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, vd);
|
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);
|
Type localType = Type.getObjectType(cn);
|
||||||
|
|
||||||
StackValue outerValue = StackValue.local(idx, localType);
|
StackValue outerValue = StackValue.local(idx, localType);
|
||||||
@@ -131,6 +131,6 @@ public class ObjectOrClosureCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConst () {
|
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.PsiManager;
|
||||||
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
|
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.codegen.ClassBuilderFactory;
|
import org.jetbrains.jet.codegen.*;
|
||||||
import org.jetbrains.jet.codegen.ClassFileFactory;
|
|
||||||
import org.jetbrains.jet.codegen.GenerationState;
|
|
||||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
|
||||||
@@ -201,7 +198,7 @@ public class CompileSession {
|
|||||||
public ClassFileFactory generate() {
|
public ClassFileFactory generate() {
|
||||||
Project project = myEnvironment.getProject();
|
Project project = myEnvironment.getProject();
|
||||||
GenerationState generationState = new GenerationState(project, ClassBuilderFactory.BINARIES, myFileNameTransformer);
|
GenerationState generationState = new GenerationState(project, ClassBuilderFactory.BINARIES, myFileNameTransformer);
|
||||||
generationState.compileCorrectFiles(myBindingContext, mySourceFiles);
|
generationState.compileCorrectFiles(myBindingContext, mySourceFiles, CompilationErrorHandler.THROW_EXCEPTION, true);
|
||||||
ClassFileFactory answer = generationState.getFactory();
|
ClassFileFactory answer = generationState.getFactory();
|
||||||
|
|
||||||
List<CompilerPlugin> fileProcessors = myEnvironment.getCompilerPlugins();
|
List<CompilerPlugin> fileProcessors = myEnvironment.getCompilerPlugins();
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ import com.intellij.util.containers.Stack;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.codegen.ClassBuilder;
|
import org.jetbrains.jet.codegen.ClassBuilder;
|
||||||
import org.jetbrains.jet.codegen.ClassBuilderFactory;
|
import org.jetbrains.jet.codegen.ClassBuilderFactory;
|
||||||
|
import org.jetbrains.jet.codegen.CompilationErrorHandler;
|
||||||
import org.jetbrains.jet.codegen.GenerationState;
|
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.JetFile;
|
||||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -184,8 +186,10 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa
|
|||||||
};
|
};
|
||||||
|
|
||||||
List<JetFile> files = Collections.singletonList(file);
|
List<JetFile> files = Collections.singletonList(file);
|
||||||
final BindingContext context = AnalyzerFacade.shallowAnalyzeFiles(files);
|
//todo:
|
||||||
state.compileCorrectFiles(context, files);
|
// 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();
|
state.getFactory().files();
|
||||||
|
|
||||||
return answer;
|
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());
|
// System.out.println(generateToText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testObjectLiteralInClosure() throws Exception {
|
||||||
|
blackBoxFile("objects/objectLiteralInClosure.jet");
|
||||||
|
// System.out.println(generateToText());
|
||||||
|
}
|
||||||
|
|
||||||
public void testMethodOnObject() throws Exception {
|
public void testMethodOnObject() throws Exception {
|
||||||
blackBoxFile("objects/methodOnObject.jet");
|
blackBoxFile("objects/methodOnObject.jet");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ public class TestlibTest extends CodegenTestCase {
|
|||||||
new URLClassLoader(new URL[]{ForTestCompileStdlib.stdlibJarForTests().toURI().toURL(), junitJar.toURI().toURL()},
|
new URLClassLoader(new URL[]{ForTestCompileStdlib.stdlibJarForTests().toURI().toURL(), junitJar.toURI().toURL()},
|
||||||
TestCase.class.getClassLoader()));
|
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");
|
TestSuite suite = new TestSuite("stdlib_test");
|
||||||
try {
|
try {
|
||||||
for(JetFile jetFile : session.getSourceFileNamespaces()) {
|
for(JetFile jetFile : session.getSourceFileNamespaces()) {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import com.sun.jdi.ReferenceType;
|
|||||||
import com.sun.jdi.request.ClassPrepareRequest;
|
import com.sun.jdi.request.ClassPrepareRequest;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
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.JetTypeMapper;
|
||||||
import org.jetbrains.jet.codegen.NamespaceCodegen;
|
import org.jetbrains.jet.codegen.NamespaceCodegen;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
@@ -154,18 +154,8 @@ public class JetPositionManager implements PositionManager {
|
|||||||
}
|
}
|
||||||
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
||||||
final JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
|
final JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
|
||||||
final JetTypeMapper typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
ClosureAnnotator closureAnnotator = new ClosureAnnotator(bindingContext, Collections.singleton(file));
|
||||||
file.acceptChildren(new JetVisitorVoid() {
|
final JetTypeMapper typeMapper = new JetTypeMapper(standardLibrary, bindingContext, closureAnnotator);
|
||||||
@Override
|
|
||||||
public void visitJetElement(JetElement element) {
|
|
||||||
element.acceptChildren(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitClass(JetClass klass) {
|
|
||||||
GenerationState.prepareAnonymousClasses(klass, typeMapper);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
myTypeMappers.put(file, typeMapper);
|
myTypeMappers.put(file, typeMapper);
|
||||||
return typeMapper;
|
return typeMapper;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import com.intellij.psi.PsiManager;
|
|||||||
import com.intellij.util.Alarm;
|
import com.intellij.util.Alarm;
|
||||||
import org.jetbrains.jet.codegen.ClassBuilderFactory;
|
import org.jetbrains.jet.codegen.ClassBuilderFactory;
|
||||||
import org.jetbrains.jet.codegen.ClassFileFactory;
|
import org.jetbrains.jet.codegen.ClassFileFactory;
|
||||||
|
import org.jetbrains.jet.codegen.CompilationErrorHandler;
|
||||||
import org.jetbrains.jet.codegen.GenerationState;
|
import org.jetbrains.jet.codegen.GenerationState;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||||
@@ -203,7 +204,7 @@ public class BytecodeToolwindow extends JPanel implements Disposable {
|
|||||||
try {
|
try {
|
||||||
BindingContext binding = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
BindingContext binding = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
|
||||||
AnalyzingUtils.throwExceptionOnErrors(binding);
|
AnalyzingUtils.throwExceptionOnErrors(binding);
|
||||||
state.compileCorrectFiles(binding, Collections.singletonList(file));
|
state.compileCorrectFiles(binding, Collections.singletonList(file), CompilationErrorHandler.THROW_EXCEPTION, true);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
StringWriter out = new StringWriter(1024);
|
StringWriter out = new StringWriter(1024);
|
||||||
e.printStackTrace(new PrintWriter(out));
|
e.printStackTrace(new PrintWriter(out));
|
||||||
|
|||||||
Reference in New Issue
Block a user