001 /* 002 * Copyright 2010-2015 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.kotlin.codegen.binding; 018 019 import com.intellij.openapi.util.Pair; 020 import org.jetbrains.annotations.NotNull; 021 import org.jetbrains.annotations.Nullable; 022 import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor; 023 import org.jetbrains.kotlin.descriptors.*; 024 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; 025 import org.jetbrains.kotlin.types.JetType; 026 import org.jetbrains.org.objectweb.asm.Type; 027 028 import java.util.*; 029 030 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.getDirectMember; 031 032 public final class MutableClosure implements CalculatedClosure { 033 private final ResolvedCall<ConstructorDescriptor> superCall; 034 035 private final ClassDescriptor enclosingClass; 036 private final CallableDescriptor enclosingFunWithReceiverDescriptor; 037 038 private boolean captureThis; 039 private boolean captureReceiver; 040 041 private Map<DeclarationDescriptor, EnclosedValueDescriptor> captureVariables; 042 private List<Pair<String, Type>> recordedFields; 043 044 MutableClosure( 045 @NotNull ClassDescriptor classDescriptor, 046 @Nullable ResolvedCall<ConstructorDescriptor> superCall, 047 @Nullable ClassDescriptor enclosingClass 048 ) { 049 this.enclosingClass = enclosingClass; 050 this.superCall = superCall; 051 this.enclosingFunWithReceiverDescriptor = enclosingExtensionMemberForClass(classDescriptor); 052 } 053 054 @Nullable 055 private static CallableDescriptor enclosingExtensionMemberForClass(@NotNull ClassDescriptor classDescriptor) { 056 DeclarationDescriptor classContainer = classDescriptor.getContainingDeclaration(); 057 if (classContainer instanceof CallableMemberDescriptor) { 058 CallableMemberDescriptor member = getDirectMember((CallableMemberDescriptor) classContainer); 059 if (member.getExtensionReceiverParameter() != null) { 060 return member; 061 } 062 } 063 return null; 064 } 065 066 @Nullable 067 public ClassDescriptor getEnclosingClass() { 068 return enclosingClass; 069 } 070 071 @Override 072 public ResolvedCall<ConstructorDescriptor> getSuperCall() { 073 return superCall; 074 } 075 076 @Override 077 public ClassDescriptor getCaptureThis() { 078 return captureThis ? enclosingClass : null; 079 } 080 081 public void setCaptureThis() { 082 this.captureThis = true; 083 } 084 085 @Override 086 public JetType getCaptureReceiverType() { 087 if (captureReceiver) { 088 ReceiverParameterDescriptor parameter = getEnclosingReceiverDescriptor(); 089 assert parameter != null : "Receiver parameter should exist in " + enclosingFunWithReceiverDescriptor; 090 return parameter.getType(); 091 } 092 093 return null; 094 } 095 096 public void setCaptureReceiver() { 097 if (enclosingFunWithReceiverDescriptor == null) { 098 throw new IllegalStateException("Extension receiver parameter should exist"); 099 } 100 this.captureReceiver = true; 101 } 102 103 @NotNull 104 @Override 105 public Map<DeclarationDescriptor, EnclosedValueDescriptor> getCaptureVariables() { 106 return captureVariables != null ? captureVariables : Collections.<DeclarationDescriptor, EnclosedValueDescriptor>emptyMap(); 107 } 108 109 @NotNull 110 @Override 111 public List<Pair<String, Type>> getRecordedFields() { 112 return recordedFields != null ? recordedFields : Collections.<Pair<String, Type>>emptyList(); 113 } 114 115 public void recordField(String name, Type type) { 116 if (recordedFields == null) { 117 recordedFields = new LinkedList<Pair<String, Type>>(); 118 } 119 recordedFields.add(new Pair<String, Type>(name, type)); 120 } 121 122 public void captureVariable(EnclosedValueDescriptor value) { 123 if (captureVariables == null) { 124 captureVariables = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>(); 125 } 126 captureVariables.put(value.getDescriptor(), value); 127 } 128 129 @Nullable 130 public ReceiverParameterDescriptor getEnclosingReceiverDescriptor() { 131 return enclosingFunWithReceiverDescriptor != null ? enclosingFunWithReceiverDescriptor.getExtensionReceiverParameter() : null; 132 } 133 }