From 9ba1dbf98aa0b5ebdedf9f02043db558cfb17708 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Mon, 27 Feb 2012 22:59:34 +0200 Subject: [PATCH] refactoring in progress --- .../jetbrains/jet/codegen/ClassCodegen.java | 3 - .../jet/codegen/ClosureAnnotator.java | 288 ++++++++++++++++++ .../jetbrains/jet/codegen/ClosureCodegen.java | 30 +- .../jetbrains/jet/codegen/CodegenContext.java | 4 +- .../jetbrains/jet/codegen/CodegenUtil.java | 15 - .../jet/codegen/ConstructorFrameMap.java | 5 +- .../jet/codegen/ExpressionCodegen.java | 4 +- .../GeneratedAnonymousClassDescriptor.java | 6 +- .../jet/codegen/GenerationState.java | 36 +-- .../codegen/ImplementationBodyCodegen.java | 48 ++- .../jetbrains/jet/codegen/JetTypeMapper.java | 86 ++---- .../jet/codegen/JvmMethodParameterKind.java | 2 - .../jet/codegen/NamespaceCodegen.java | 13 - .../jet/codegen/ObjectOrClosureCodegen.java | 6 +- .../jet/compiler/CompileSession.java | 7 +- .../jetbrains/jet/asJava/JetLightClass.java | 8 +- .../objects/objectLiteralInClosure.jet | 17 ++ .../jetbrains/jet/codegen/ObjectGenTest.java | 5 + .../jetbrains/jet/codegen/TestlibTest.java | 3 +- .../plugin/debugger/JetPositionManager.java | 16 +- .../codewindow/BytecodeToolwindow.java | 3 +- 21 files changed, 396 insertions(+), 209 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/ClosureAnnotator.java create mode 100644 compiler/testData/codegen/objects/objectLiteralInClosure.jet diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java index 03c38ce4fc1..aa8753a8d8d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -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()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureAnnotator.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureAnnotator.java new file mode 100644 index 00000000000..ae6c782e09b --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureAnnotator.java @@ -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 classNamesForAnonymousClasses = new HashMap(); + private final Map classNamesForClassDescriptor = new HashMap(); + private final Map anonymousSubclassesCount = new HashMap(); + private final Map classesForFunctions = new HashMap(); + private final Map enclosing = new HashMap(); + + private final MultiMap namespaceName2Files = MultiMap.create(); + private final BindingContext bindingContext; + + public ClosureAnnotator(BindingContext bindingContext, Collection 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.emptyList(), + name); + classDescriptor.initialize( + false, + Collections.emptyList(), + Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.emptySet(), null); + classesForFunctions.put(funDescriptor, classDescriptor); + } + return classDescriptor; + } + + private void mapFilesToNamespaces(Collection files) { + for (JetFile file : files) { + String fqName = JetPsiUtil.getFQName(file); + namespaceName2Files.putValue(fqName, file); + } + } + + private void prepareAnonymousClasses() { + MyJetVisitorVoid visitor = new MyJetVisitorVoid(); + for (Map.Entry> 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 classStack = new LinkedList(); + private LinkedList nameStack = new LinkedList(); + + 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; + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index df5e3b9e66b..310039906e3 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -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.emptyList(), - name); - function = function.initialize( - false, - Collections.emptyList(), - Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.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 variableDescriptors = new ArrayList(); @@ -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 { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java index 9f203fc1ee2..5224d6aac84 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java @@ -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; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index 55ca8a33101..3edc00c3dfb 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -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( diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java b/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java index 21b94c5fd5c..6c6ea28e187 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java @@ -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 } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 7fb90fc8eb0..9484a9a9368 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -809,7 +809,7 @@ public class ExpressionCodegen extends JetVisitor { 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 { 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()); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedAnonymousClassDescriptor.java b/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedAnonymousClassDescriptor.java index 83d985ae84e..286aaa0fe0a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedAnonymousClassDescriptor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedAnonymousClassDescriptor.java @@ -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 args = new ArrayList(); - 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() { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index 6638960a7ae..cac631f6232 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -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 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 files) { - compileCorrectFiles(bindingContext, files, CompilationErrorHandler.THROW_EXCEPTION); + public void compileCorrectFiles(BindingContext bindingContext, List files, boolean annotate) { + compileCorrectFiles(bindingContext, files, CompilationErrorHandler.THROW_EXCEPTION, annotate); } - public void compileCorrectFiles(BindingContext bindingContext, List files, CompilationErrorHandler errorHandler) { - typeMapper = new JetTypeMapper(standardLibrary, bindingContext); + public void compileCorrectFiles(BindingContext bindingContext, List 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(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index efd53abd0c5..e377090ba2c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -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.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 parameterTypes = new ArrayList(); 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("", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); iv.invokespecial(typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "", 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, "", 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); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 4221e4d5566..b2e0c0a01f2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -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 classNamesForAnonymousClasses = new HashMap(); - private final Map anonymousSubclassesCount = new HashMap(); + 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 knowTypeNames = new HashMap(); private final HashMap knowTypes = new HashMap(); @@ -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 parameters = descriptor.getOriginal().getValueParameters(); - ClassDescriptor classDescriptor = descriptor.getContainingDeclaration(); // constructor type parmeters are fake writeFormalTypeParameters(Collections.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(""); } - 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 allJvmNames(JetClassOrObject jetClass) { Set result = new HashSet(); 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())); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodParameterKind.java b/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodParameterKind.java index 6d464f09494..d0fdd813c14 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodParameterKind.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodParameterKind.java @@ -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, } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index bd15f79af25..d417ad19eb5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -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); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java index 69203c98bd9..549d30f2940 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java @@ -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(); } } diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java index c8f97f02607..804730b40f6 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java @@ -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 fileProcessors = myEnvironment.getCompilerPlugins(); diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java index 42ee6e39684..2cc50f58962 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java @@ -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 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; diff --git a/compiler/testData/codegen/objects/objectLiteralInClosure.jet b/compiler/testData/codegen/objects/objectLiteralInClosure.jet new file mode 100644 index 00000000000..d63c1c879fa --- /dev/null +++ b/compiler/testData/codegen/objects/objectLiteralInClosure.jet @@ -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 +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java index a52c26c6f53..ee83ac306d9 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java @@ -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"); } diff --git a/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java b/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java index 41b752b19d4..67c38f688f2 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java @@ -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()) { diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java b/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java index b57ef95a4ba..554a5e350ec 100644 --- a/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java +++ b/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java @@ -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; } diff --git a/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java b/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java index c3189378eaa..2c5fdaf5244 100644 --- a/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java +++ b/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java @@ -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));