001    /*
002     * Copyright 2010-2013 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.jet.codegen;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.jet.lang.descriptors.*;
021    import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
022    import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
023    import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor;
024    import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
025    import org.jetbrains.jet.lang.reflect.ReflectionTypes;
026    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
027    import org.jetbrains.jet.lang.resolve.ImportPath;
028    import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
029    import org.jetbrains.jet.lang.resolve.name.FqName;
030    import org.jetbrains.jet.lang.resolve.name.Name;
031    import org.jetbrains.jet.lang.types.*;
032    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
033    
034    import java.util.*;
035    
036    public class JvmFunctionImplTypes {
037        private final ReflectionTypes reflectionTypes;
038    
039        private final ClassDescriptor functionImpl;
040        private final ClassDescriptor extensionFunctionImpl;
041        private final ClassDescriptor kFunctionImpl;
042        private final ClassDescriptor kMemberFunctionImpl;
043        private final ClassDescriptor kExtensionFunctionImpl;
044    
045        public JvmFunctionImplTypes(@NotNull ReflectionTypes reflectionTypes) {
046            this.reflectionTypes = reflectionTypes;
047    
048            ModuleDescriptor fakeModule = new ModuleDescriptorImpl(Name.special("<fake module for functions impl>"),
049                                                                   Collections.<ImportPath>emptyList(), JavaToKotlinClassMap.getInstance());
050    
051            PackageFragmentDescriptor kotlinJvmInternal =
052                    new MutablePackageFragmentDescriptor(fakeModule, new FqName("kotlin.jvm.internal"));
053            PackageFragmentDescriptor kotlinReflectJvmInternal =
054                    new MutablePackageFragmentDescriptor(fakeModule, new FqName("kotlin.reflect.jvm.internal"));
055    
056            this.functionImpl = createClass(kotlinJvmInternal, "FunctionImpl", "out R");
057            this.extensionFunctionImpl = createClass(kotlinJvmInternal, "ExtensionFunctionImpl", "in T", "out R");
058            this.kFunctionImpl = createClass(kotlinReflectJvmInternal, "KFunctionImpl", "out R");
059            this.kExtensionFunctionImpl = createClass(kotlinReflectJvmInternal, "KExtensionFunctionImpl", "in T", "out R");
060            this.kMemberFunctionImpl = createClass(kotlinReflectJvmInternal, "KMemberFunctionImpl", "in T", "out R");
061        }
062    
063        @NotNull
064        private static ClassDescriptor createClass(
065                @NotNull PackageFragmentDescriptor packageFragment,
066                @NotNull String name,
067                @NotNull String... typeParameters
068        ) {
069            MutableClassDescriptor descriptor = new MutableClassDescriptor(packageFragment, packageFragment.getMemberScope(),
070                                                                           ClassKind.CLASS, false, Name.identifier(name));
071            List<TypeParameterDescriptor> typeParameterDescriptors = new ArrayList<TypeParameterDescriptor>(typeParameters.length);
072            for (int i = 0; i < typeParameters.length; i++) {
073                String[] s = typeParameters[i].split(" ");
074                Variance variance = Variance.valueOf(s[0].toUpperCase() + "_VARIANCE");
075                String typeParameterName = s[1];
076                TypeParameterDescriptorImpl typeParameter = TypeParameterDescriptorImpl.createForFurtherModification(
077                        descriptor, Annotations.EMPTY, false, variance, Name.identifier(typeParameterName), i
078                );
079                typeParameter.setInitialized();
080                typeParameterDescriptors.add(typeParameter);
081            }
082    
083            descriptor.setModality(Modality.FINAL);
084            descriptor.setVisibility(Visibilities.PUBLIC);
085            descriptor.setTypeParameterDescriptors(typeParameterDescriptors);
086            descriptor.createTypeConstructor();
087    
088            return descriptor;
089        }
090    
091        @NotNull
092        public Collection<JetType> getSupertypesForClosure(@NotNull FunctionDescriptor descriptor) {
093            ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
094    
095            List<TypeProjection> typeArguments = new ArrayList<TypeProjection>(2);
096    
097            ClassDescriptor classDescriptor;
098            if (receiverParameter != null) {
099                classDescriptor = extensionFunctionImpl;
100                typeArguments.add(new TypeProjectionImpl(receiverParameter.getType()));
101            }
102            else {
103                classDescriptor = functionImpl;
104            }
105    
106            //noinspection ConstantConditions
107            typeArguments.add(new TypeProjectionImpl(descriptor.getReturnType()));
108    
109            JetType functionImplType = new JetTypeImpl(
110                    classDescriptor.getDefaultType().getAnnotations(),
111                    classDescriptor.getTypeConstructor(),
112                    false,
113                    typeArguments,
114                    classDescriptor.getMemberScope(typeArguments)
115            );
116    
117            JetType functionType = KotlinBuiltIns.getInstance().getFunctionType(
118                    Annotations.EMPTY,
119                    receiverParameter == null ? null : receiverParameter.getType(),
120                    DescriptorUtils.getValueParametersTypes(descriptor.getValueParameters()),
121                    descriptor.getReturnType()
122            );
123    
124            return Arrays.asList(functionImplType, functionType);
125        }
126    
127        @NotNull
128        public Collection<JetType> getSupertypesForCallableReference(@NotNull FunctionDescriptor descriptor) {
129            ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
130            ReceiverParameterDescriptor expectedThisObject = descriptor.getExpectedThisObject();
131    
132            List<TypeProjection> typeArguments = new ArrayList<TypeProjection>(2);
133    
134            ClassDescriptor classDescriptor;
135            JetType receiverType;
136            if (receiverParameter != null) {
137                classDescriptor = kExtensionFunctionImpl;
138                receiverType = receiverParameter.getType();
139                typeArguments.add(new TypeProjectionImpl(receiverType));
140            }
141            else if (expectedThisObject != null) {
142                classDescriptor = kMemberFunctionImpl;
143                receiverType = expectedThisObject.getType();
144                typeArguments.add(new TypeProjectionImpl(receiverType));
145            }
146            else {
147                classDescriptor = kFunctionImpl;
148                receiverType = null;
149            }
150    
151            //noinspection ConstantConditions
152            typeArguments.add(new TypeProjectionImpl(descriptor.getReturnType()));
153    
154            JetType kFunctionImplType = new JetTypeImpl(
155                    classDescriptor.getDefaultType().getAnnotations(),
156                    classDescriptor.getTypeConstructor(),
157                    false,
158                    typeArguments,
159                    classDescriptor.getMemberScope(typeArguments)
160            );
161    
162            JetType kFunctionType = reflectionTypes.getKFunctionType(
163                    Annotations.EMPTY,
164                    receiverType,
165                    DescriptorUtils.getValueParametersTypes(descriptor.getValueParameters()),
166                    descriptor.getReturnType(),
167                    receiverParameter != null
168            );
169    
170            return Arrays.asList(kFunctionImplType, kFunctionType);
171        }
172    }