Iniital implementation of synthetic extensions for SAM-adapter functions (non-static only)
This commit is contained in:
+19
-9
@@ -239,30 +239,40 @@ public class SingleAbstractMethodUtils {
|
||||
JetType returnTypeUnsubstituted = original.getReturnType();
|
||||
assert returnTypeUnsubstituted != null : "Creating SAM adapter for not initialized original: " + original;
|
||||
|
||||
JetType returnType = typeParameters.substitutor.substitute(returnTypeUnsubstituted, Variance.OUT_VARIANCE);
|
||||
TypeSubstitutor substitutor = typeParameters.substitutor;
|
||||
JetType returnType = substitutor.substitute(returnTypeUnsubstituted, Variance.OUT_VARIANCE);
|
||||
assert returnType != null : "couldn't substitute type: " + returnTypeUnsubstituted +
|
||||
", substitutor = " + typeParameters.substitutor;
|
||||
", substitutor = " + substitutor;
|
||||
|
||||
|
||||
List<ValueParameterDescriptor> valueParameters = createValueParametersForSamAdapter(original, adapter, substitutor);
|
||||
|
||||
initializer.initialize(typeParameters.descriptors, valueParameters, returnType);
|
||||
|
||||
return adapter;
|
||||
}
|
||||
|
||||
public static List<ValueParameterDescriptor> createValueParametersForSamAdapter(
|
||||
@NotNull FunctionDescriptor original,
|
||||
@NotNull FunctionDescriptor samAdapter,
|
||||
@NotNull TypeSubstitutor substitutor
|
||||
) {
|
||||
List<ValueParameterDescriptor> originalValueParameters = original.getValueParameters();
|
||||
List<ValueParameterDescriptor> valueParameters = new ArrayList<ValueParameterDescriptor>(originalValueParameters.size());
|
||||
for (ValueParameterDescriptor originalParam : originalValueParameters) {
|
||||
JetType originalType = originalParam.getType();
|
||||
JetType functionType = getFunctionTypeForSamType(originalType, false);
|
||||
JetType newTypeUnsubstituted = functionType != null ? functionType : originalType;
|
||||
JetType newType = typeParameters.substitutor.substitute(newTypeUnsubstituted, Variance.IN_VARIANCE);
|
||||
assert newType != null : "couldn't substitute type: " + newTypeUnsubstituted + ", substitutor = " + typeParameters.substitutor;
|
||||
JetType newType = substitutor.substitute(newTypeUnsubstituted, Variance.IN_VARIANCE);
|
||||
assert newType != null : "couldn't substitute type: " + newTypeUnsubstituted + ", substitutor = " + substitutor;
|
||||
|
||||
ValueParameterDescriptor newParam = new ValueParameterDescriptorImpl(
|
||||
adapter, null, originalParam.getIndex(), originalParam.getAnnotations(),
|
||||
samAdapter, null, originalParam.getIndex(), originalParam.getAnnotations(),
|
||||
originalParam.getName(), newType, false, null, SourceElement.NO_SOURCE
|
||||
);
|
||||
valueParameters.add(newParam);
|
||||
}
|
||||
|
||||
initializer.initialize(typeParameters.descriptors, valueParameters, returnType);
|
||||
|
||||
return adapter;
|
||||
return valueParameters;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.resolve.lazy.FileScopeProvider
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
class AdditionalScopesWithJavaSyntheticExtensions(storageManager: StorageManager) : FileScopeProvider.AdditionalScopes {
|
||||
private val scopes = listOf(JavaSyntheticPropertiesScope(storageManager), SamAdapterFunctionsScope(storageManager))
|
||||
|
||||
override fun scopes(file: JetFile) = scopes
|
||||
}
|
||||
+11
-18
@@ -22,21 +22,19 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.lazy.FileScopeProvider
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScopeImpl
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.isBoolean
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeFirstWord
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.decapitalizeSmart
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.ArrayList
|
||||
import java.util.HashSet
|
||||
@@ -84,13 +82,7 @@ interface SyntheticJavaPropertyDescriptor : PropertyDescriptor {
|
||||
}
|
||||
}
|
||||
|
||||
class AdditionalScopesWithJavaSyntheticExtensions(storageManager: StorageManager) : FileScopeProvider.AdditionalScopes {
|
||||
private val scope = JavaSyntheticExtensionsScope(storageManager)
|
||||
|
||||
override fun scopes(file: JetFile) = listOf(scope)
|
||||
}
|
||||
|
||||
class JavaSyntheticExtensionsScope(storageManager: StorageManager) : JetScope by JetScope.Empty {
|
||||
class JavaSyntheticPropertiesScope(storageManager: StorageManager) : JetScopeImpl() {
|
||||
private val syntheticPropertyInClass = storageManager.createMemoizedFunctionWithNullableValues<Pair<ClassDescriptor, Name>, PropertyDescriptor> { pair ->
|
||||
syntheticPropertyInClassNotCached(pair.first, pair.second)
|
||||
}
|
||||
@@ -117,13 +109,6 @@ class JavaSyntheticExtensionsScope(storageManager: StorageManager) : JetScope by
|
||||
return MyPropertyDescriptor(ownerClass, getMethod.original, setMethod?.original, name, propertyType)
|
||||
}
|
||||
|
||||
private fun FunctionDescriptor.hasJavaOriginInHierarchy(): Boolean {
|
||||
return if (overriddenDescriptors.isEmpty())
|
||||
containingDeclaration is JavaClassDescriptor
|
||||
else
|
||||
overriddenDescriptors.any { it.hasJavaOriginInHierarchy() }
|
||||
}
|
||||
|
||||
private fun isGoodGetMethod(descriptor: FunctionDescriptor): Boolean {
|
||||
val returnType = descriptor.returnType ?: return false
|
||||
if (returnType.isUnit()) return false
|
||||
@@ -251,6 +236,14 @@ class JavaSyntheticExtensionsScope(storageManager: StorageManager) : JetScope by
|
||||
return Name.identifier("set" + identifier.removePrefix(prefix))
|
||||
}
|
||||
|
||||
override fun getContainingDeclaration(): DeclarationDescriptor {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun printScopeStructure(p: Printer) {
|
||||
p.println(javaClass.simpleName)
|
||||
}
|
||||
|
||||
private class MyPropertyDescriptor(
|
||||
ownerClass: ClassDescriptor,
|
||||
override val getMethod: FunctionDescriptor,
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.load.java.sam.SingleAbstractMethodUtils
|
||||
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.JetScope
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.DescriptorSubstitutor
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitution
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import java.util.ArrayList
|
||||
|
||||
interface SamAdapterExtensionFunctionDescriptor : FunctionDescriptor {
|
||||
val originalFunction: FunctionDescriptor
|
||||
}
|
||||
|
||||
class SamAdapterFunctionsScope(storageManager: StorageManager) : JetScope by JetScope.Empty {
|
||||
private val extensionForFunction = storageManager.createMemoizedFunctionWithNullableValues<FunctionDescriptor, FunctionDescriptor> { function ->
|
||||
extensionForFunctionNotCached(function)
|
||||
}
|
||||
|
||||
private fun extensionForFunctionNotCached(function: FunctionDescriptor): FunctionDescriptor? {
|
||||
//TODO!
|
||||
if (function.visibility == Visibilities.PRIVATE || function.visibility == Visibilities.PRIVATE_TO_THIS || function.visibility == Visibilities.INVISIBLE_FAKE) return null
|
||||
if (!function.hasJavaOriginInHierarchy()) return null //TODO: should we go into base at all?
|
||||
if (!SingleAbstractMethodUtils.isSamAdapterNecessary(function)) return null
|
||||
val returnType = function.returnType ?: return null
|
||||
return MyFunctionDescriptor(function, returnType)
|
||||
}
|
||||
|
||||
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<JetType>, name: Name): Collection<FunctionDescriptor> {
|
||||
var result: SmartList<FunctionDescriptor>? = null
|
||||
for (type in receiverTypes) {
|
||||
for (function in type.memberScope.getFunctions(name)) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
private class MyFunctionDescriptor(
|
||||
override val originalFunction: FunctionDescriptor,
|
||||
originalReturnType: JetType
|
||||
) : SamAdapterExtensionFunctionDescriptor, SimpleFunctionDescriptorImpl(
|
||||
DescriptorUtils.getContainingModule(originalFunction),
|
||||
null,
|
||||
Annotations.EMPTY, //TODO
|
||||
originalFunction.name,
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
originalFunction.source
|
||||
) {
|
||||
init {
|
||||
val typeParamsSum = (originalFunction.typeParameters).toArrayList()
|
||||
val ownerClass = originalFunction.containingDeclaration as ClassDescriptor
|
||||
//TODO: should we go up parents for getters/setters too?
|
||||
for (parent in ownerClass.parentsWithSelf) {
|
||||
if (parent !is ClassDescriptor) break
|
||||
typeParamsSum += parent.typeConstructor.parameters
|
||||
}
|
||||
//TODO: duplicated parameter names
|
||||
|
||||
val typeParameters = ArrayList<TypeParameterDescriptor>(typeParamsSum.size())
|
||||
val typeSubstitutor = DescriptorSubstitutor.substituteTypeParameters(typeParamsSum, TypeSubstitution.EMPTY, this, typeParameters)
|
||||
|
||||
val returnType = typeSubstitutor.safeSubstitute(originalReturnType, Variance.OUT_VARIANCE)
|
||||
val receiverType = typeSubstitutor.safeSubstitute(ownerClass.defaultType, Variance.INVARIANT)
|
||||
val valueParameters = SingleAbstractMethodUtils.createValueParametersForSamAdapter(originalFunction, this, typeSubstitutor)
|
||||
initialize(receiverType, null, typeParameters, valueParameters, returnType, Modality.FINAL, Visibilities.PUBLIC)
|
||||
}
|
||||
|
||||
override fun hasStableParameterNames() = originalFunction.hasStableParameterNames()
|
||||
override fun hasSynthesizedParameterNames() = originalFunction.hasSynthesizedParameterNames()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
|
||||
fun FunctionDescriptor.hasJavaOriginInHierarchy(): Boolean {
|
||||
return if (overriddenDescriptors.isEmpty())
|
||||
containingDeclaration is JavaClassDescriptor
|
||||
else
|
||||
overriddenDescriptors.any { it.hasJavaOriginInHierarchy() }
|
||||
}
|
||||
Reference in New Issue
Block a user