refactoring in progress

This commit is contained in:
Alex Tkachman
2012-02-27 22:59:34 +02:00
parent 1610e7eefd
commit 9ba1dbf98a
21 changed files with 396 additions and 209 deletions
@@ -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());
}
}
@@ -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));