All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.synthetic.SamAdapterFunctionsScope.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-Beta1
Show newest version
/*
 * Copyright 2010-2015 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.kotlin.synthetic

import com.intellij.util.SmartList
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
import org.jetbrains.kotlin.load.java.typeEnhancement.enhanceSignature
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.SyntheticScope
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.*
import java.util.*
import kotlin.properties.Delegates

interface SamAdapterExtensionFunctionDescriptor : FunctionDescriptor {
    val sourceFunction: FunctionDescriptor
}

class SamAdapterFunctionsScope(storageManager: StorageManager) : SyntheticScope {
    private val extensionForFunction = storageManager.createMemoizedFunctionWithNullableValues { function ->
        extensionForFunctionNotCached(function)
    }

    private fun extensionForFunctionNotCached(function: FunctionDescriptor): FunctionDescriptor? {
        if (!function.visibility.isVisibleOutside()) return null
        if (!function.hasJavaOriginInHierarchy()) return null //TODO: should we go into base at all?
        if (!SingleAbstractMethodUtils.isSamAdapterNecessary(function)) return null
        if (function.returnType == null) return null
        //TODO: it's a temporary hack while original returns a function with platform types
        val enhancedFunction = function.enhanceSignature()
        return MyFunctionDescriptor.create(enhancedFunction)
    }

    override fun getSyntheticExtensionFunctions(receiverTypes: Collection, name: Name, location: LookupLocation): Collection {
        var result: SmartList? = null
        for (type in receiverTypes) {
            for (function in type.memberScope.getContributedFunctions(name, location)) {
                val extension = extensionForFunction(function.original)
                if (extension != null) {
                    if (result == null) {
                        result = SmartList()
                    }
                    result.add(extension)
                }
            }
        }
        return when {
            result == null -> emptyList()
            result.size > 1 -> result.toSet()
            else -> result
        }
    }

    override fun getSyntheticExtensionFunctions(receiverTypes: Collection): Collection {
        return receiverTypes.flatMapTo(LinkedHashSet()) { type ->
            type.memberScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
                    .filterIsInstance()
                    .mapNotNull { extensionForFunction(it.original) }
        }
    }

    override fun getSyntheticExtensionProperties(receiverTypes: Collection, name: Name, location: LookupLocation): Collection = emptyList()

    override fun getSyntheticExtensionProperties(receiverTypes: Collection): Collection = emptyList()

    private class MyFunctionDescriptor(
            containingDeclaration: DeclarationDescriptor,
            original: SimpleFunctionDescriptor?,
            annotations: Annotations,
            name: Name,
            kind: CallableMemberDescriptor.Kind,
            source: SourceElement
    ) : SamAdapterExtensionFunctionDescriptor, SimpleFunctionDescriptorImpl(containingDeclaration, original, annotations, name, kind, source) {

        override var sourceFunction: FunctionDescriptor by Delegates.notNull()
            private set

        private var toSourceFunctionTypeParameters: Map? = null

        companion object {
            fun create(sourceFunction: FunctionDescriptor): MyFunctionDescriptor {
                val descriptor = MyFunctionDescriptor(DescriptorUtils.getContainingModule(sourceFunction),
                                                      null,
                                                      sourceFunction.annotations,
                                                      sourceFunction.name,
                                                      CallableMemberDescriptor.Kind.SYNTHESIZED,
                                                      sourceFunction.original.source)
                descriptor.sourceFunction = sourceFunction

                val sourceTypeParams = (sourceFunction.typeParameters).toMutableList()
                val ownerClass = sourceFunction.containingDeclaration as ClassDescriptor
                //TODO: should we go up parents for getters/setters too?
                //TODO: non-inner classes
                for (parent in ownerClass.parentsWithSelf) {
                    if (parent !is ClassDescriptor) break
                    sourceTypeParams += parent.declaredTypeParameters
                }
                //TODO: duplicated parameter names

                val typeParameters = ArrayList(sourceTypeParams.size)
                val typeSubstitutor = DescriptorSubstitutor.substituteTypeParameters(sourceTypeParams, TypeSubstitution.EMPTY, descriptor, typeParameters)

                descriptor.toSourceFunctionTypeParameters = typeParameters.zip(sourceTypeParams).toMap()

                val returnType = typeSubstitutor.safeSubstitute(sourceFunction.returnType!!, Variance.INVARIANT)
                val receiverType = typeSubstitutor.safeSubstitute(ownerClass.defaultType, Variance.INVARIANT)
                val valueParameters = SingleAbstractMethodUtils.createValueParametersForSamAdapter(sourceFunction, descriptor, typeSubstitutor)

                val visibility = syntheticExtensionVisibility(sourceFunction)

                descriptor.initialize(receiverType, null, typeParameters, valueParameters, returnType,
                                      Modality.FINAL, visibility)

                descriptor.isOperator = sourceFunction.isOperator
                descriptor.isInfix = sourceFunction.isInfix

                return descriptor
            }
        }

        override fun hasStableParameterNames() = sourceFunction.hasStableParameterNames()
        override fun hasSynthesizedParameterNames() = sourceFunction.hasSynthesizedParameterNames()

        override fun createSubstitutedCopy(
                newOwner: DeclarationDescriptor,
                original: FunctionDescriptor?,
                kind: CallableMemberDescriptor.Kind,
                newName: Name?,
                preserveSource: Boolean
        ): MyFunctionDescriptor {
            return MyFunctionDescriptor(
                    containingDeclaration, original as SimpleFunctionDescriptor?, annotations, newName ?: name, kind, source
            ).apply {
                sourceFunction = [email protected]
            }
        }

        override fun doSubstitute(configuration: CopyConfiguration): FunctionDescriptor? {
            val descriptor = super.doSubstitute(configuration) as MyFunctionDescriptor? ?: return null
            val original = configuration.original
                           ?: throw UnsupportedOperationException("doSubstitute with no original should not be called for synthetic extension")

            original as MyFunctionDescriptor
            assert(original.original == original) { "original in doSubstitute should have no other original" }

            val substitutionMap = HashMap()
            for (typeParameter in original.typeParameters) {
                val typeProjection = configuration.originalSubstitutor.substitution[typeParameter.defaultType] ?: continue
                val sourceTypeParameter = original.toSourceFunctionTypeParameters!![typeParameter]!!
                substitutionMap[sourceTypeParameter.typeConstructor] = typeProjection

            }

            val sourceFunctionSubstitutor = TypeSubstitutor.create(substitutionMap)
            descriptor.sourceFunction = original.sourceFunction.substitute(sourceFunctionSubstitutor)

            return descriptor
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy