Basic support for resolving top-level SAM interfaces.

This commit is contained in:
Evgeny Gerashchenko
2013-03-12 18:58:37 +04:00
parent 282c69eb6b
commit 2718f7698c
10 changed files with 168 additions and 15 deletions
@@ -19,10 +19,7 @@ package org.jetbrains.jet.lang.resolve.java.provider;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
import org.jetbrains.jet.lang.resolve.java.PsiClassFinder;
import org.jetbrains.jet.lang.resolve.java.TypeSource;
import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation;
import org.jetbrains.jet.lang.resolve.java.prop.PropertyNameUtils;
import org.jetbrains.jet.lang.resolve.java.prop.PropertyParseResult;
@@ -73,27 +70,28 @@ public final class MembersCache {
//TODO:
List<PsiClass> classes = psiPackage != null ? finder.findPsiClasses(psiPackage) : finder.findInnerPsiClasses(psiClass);
membersCache.new ObjectClassProcessor(classes).process();
membersCache.new ExtraPackageMembersProcessor(classes).process();
return membersCache;
}
private class ObjectClassProcessor {
private class ExtraPackageMembersProcessor { // 'extra' means that PSI elements for these members are not just top-level classes
@NotNull
private final List<PsiClass> psiClasses;
private ObjectClassProcessor(@NotNull List<PsiClass> classes) {
private ExtraPackageMembersProcessor(@NotNull List<PsiClass> classes) {
psiClasses = classes;
}
private void process() {
for (PsiClass psiClass : psiClasses) {
if (!psiClass.isPhysical()) { // to filter out JetLightClasses
continue;
if (!(psiClass instanceof JetJavaMirrorMarker)) { // to filter out JetLightClasses
if (JetClassAnnotation.get(psiClass).kind() == JvmStdlibNames.FLAG_CLASS_KIND_OBJECT) {
processObjectClass(psiClass);
}
if (!DescriptorResolverUtils.isKotlinClass(psiClass) && psiClass.isInterface()) {
processFunctionalInterface(psiClass);
}
}
if (JetClassAnnotation.get(psiClass).kind() != JvmStdlibNames.FLAG_CLASS_KIND_OBJECT) {
continue;
}
processObjectClass(psiClass);
}
}
@@ -106,6 +104,10 @@ public final class MembersCache {
namedMembers.addPropertyAccessor(new PropertyPsiDataElement(new PsiFieldWrapper(instanceField), type, null));
}
}
private void processFunctionalInterface(@NotNull PsiClass psiClass) {
getOrCreateEmpty(Name.identifier(psiClass.getName()));
}
}
private class ClassMemberProcessor {
@@ -0,0 +1,95 @@
/*
* Copyright 2010-2013 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.lang.resolve.java.sam;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SingleAbstractMethodUtils {
public static boolean isFunctionalInterface(@NotNull ClassDescriptor klass) {
if (klass.getKind() != ClassKind.TRAIT) {
return false;
}
List<CallableMemberDescriptor> abstractMembers = getAbstractMembers(klass);
return abstractMembers.size() == 1 && abstractMembers.get(0) instanceof SimpleFunctionDescriptor;
}
@NotNull
private static List<CallableMemberDescriptor> getAbstractMembers(@NotNull ClassDescriptor klass) {
List<CallableMemberDescriptor> abstractMembers = Lists.newArrayList();
for (DeclarationDescriptor member : klass.getDefaultType().getMemberScope().getAllDescriptors()) {
if (member instanceof CallableMemberDescriptor && ((CallableMemberDescriptor) member).getModality() == Modality.ABSTRACT) {
abstractMembers.add((CallableMemberDescriptor) member);
}
}
return abstractMembers;
}
@NotNull
private static JetType getFunctionalTypeForFunction(@NotNull FunctionDescriptor function) {
// TODO substitute type parameters of class
// TODO substitute type parameters of function with star projections
JetType returnType = function.getReturnType();
assert returnType != null : "function is not initialized: " + function;
List<JetType> parameterTypes = Lists.newArrayList();
for (ValueParameterDescriptor parameter : function.getValueParameters()) {
parameterTypes.add(parameter.getType());
}
return KotlinBuiltIns.getInstance().getFunctionType(Collections.<AnnotationDescriptor>emptyList(), null, parameterTypes, returnType);
}
public static SimpleFunctionDescriptor createConstructorFunction(@NotNull ClassDescriptor klass) {
SimpleFunctionDescriptorImpl result = new SimpleFunctionDescriptorImpl(
klass.getContainingDeclaration(),
klass.getAnnotations(),
klass.getName(),
CallableMemberDescriptor.Kind.SYNTHESIZED
);
JetType parameterType = getFunctionalTypeForFunction((SimpleFunctionDescriptor) getAbstractMembers(klass).get(0));
ValueParameterDescriptor parameter = new ValueParameterDescriptorImpl(
result, 0, Collections.<AnnotationDescriptor>emptyList(), Name.identifier("function"), parameterType, false, null);
result.initialize(
null,
null,
Lists.<TypeParameterDescriptor>newArrayList(), // TODO recreate type parameters of class
Arrays.asList(parameter),
klass.getDefaultType(), // TODO substitute type parameters of class
Modality.FINAL,
klass.getVisibility(),
false
);
return result;
}
private SingleAbstractMethodUtils() {
}
}
@@ -18,10 +18,12 @@ package org.jetbrains.jet.lang.resolve.java.scope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
import org.jetbrains.jet.lang.resolve.java.provider.PackagePsiDeclarationProvider;
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -42,7 +44,15 @@ public final class JavaPackageScopeWithoutMembers extends JavaPackageScope {
@Override
@NotNull
protected Set<FunctionDescriptor> computeFunctionDescriptor(@NotNull Name name) {
return Collections.emptySet();
ClassifierDescriptor classifier = getClassifier(name);
if (classifier instanceof ClassDescriptor && SingleAbstractMethodUtils.isFunctionalInterface((ClassDescriptor) classifier)) {
FunctionDescriptor constructorFunction = SingleAbstractMethodUtils.createConstructorFunction((ClassDescriptor) classifier);
return Collections.singleton(constructorFunction);
}
return Collections.emptySet();
}
@NotNull