Basic support for resolving top-level SAM interfaces.
This commit is contained in:
+15
-13
@@ -19,10 +19,7 @@ package org.jetbrains.jet.lang.resolve.java.provider;
|
|||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
import org.jetbrains.jet.lang.resolve.java.*;
|
||||||
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.kt.JetClassAnnotation;
|
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.PropertyNameUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.java.prop.PropertyParseResult;
|
import org.jetbrains.jet.lang.resolve.java.prop.PropertyParseResult;
|
||||||
@@ -73,27 +70,28 @@ public final class MembersCache {
|
|||||||
|
|
||||||
//TODO:
|
//TODO:
|
||||||
List<PsiClass> classes = psiPackage != null ? finder.findPsiClasses(psiPackage) : finder.findInnerPsiClasses(psiClass);
|
List<PsiClass> classes = psiPackage != null ? finder.findPsiClasses(psiPackage) : finder.findInnerPsiClasses(psiClass);
|
||||||
membersCache.new ObjectClassProcessor(classes).process();
|
membersCache.new ExtraPackageMembersProcessor(classes).process();
|
||||||
return membersCache;
|
return membersCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ObjectClassProcessor {
|
private class ExtraPackageMembersProcessor { // 'extra' means that PSI elements for these members are not just top-level classes
|
||||||
@NotNull
|
@NotNull
|
||||||
private final List<PsiClass> psiClasses;
|
private final List<PsiClass> psiClasses;
|
||||||
|
|
||||||
private ObjectClassProcessor(@NotNull List<PsiClass> classes) {
|
private ExtraPackageMembersProcessor(@NotNull List<PsiClass> classes) {
|
||||||
psiClasses = classes;
|
psiClasses = classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void process() {
|
private void process() {
|
||||||
for (PsiClass psiClass : psiClasses) {
|
for (PsiClass psiClass : psiClasses) {
|
||||||
if (!psiClass.isPhysical()) { // to filter out JetLightClasses
|
if (!(psiClass instanceof JetJavaMirrorMarker)) { // to filter out JetLightClasses
|
||||||
continue;
|
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));
|
namedMembers.addPropertyAccessor(new PropertyPsiDataElement(new PsiFieldWrapper(instanceField), type, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processFunctionalInterface(@NotNull PsiClass psiClass) {
|
||||||
|
getOrCreateEmpty(Name.identifier(psiClass.getName()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ClassMemberProcessor {
|
private class ClassMemberProcessor {
|
||||||
|
|||||||
+95
@@ -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() {
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-1
@@ -18,10 +18,12 @@ package org.jetbrains.jet.lang.resolve.java.scope;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
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.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
|
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
|
||||||
import org.jetbrains.jet.lang.resolve.java.provider.PackagePsiDeclarationProvider;
|
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.FqName;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
|
|
||||||
@@ -42,7 +44,15 @@ public final class JavaPackageScopeWithoutMembers extends JavaPackageScope {
|
|||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
protected Set<FunctionDescriptor> computeFunctionDescriptor(@NotNull Name name) {
|
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
|
@NotNull
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
public interface Runnable {
|
||||||
|
void run();
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public /*synthesized*/ fun Runnable(/*0*/ function : () -> jet.Unit) : test.Runnable
|
||||||
|
|
||||||
|
public trait Runnable : java.lang.Object {
|
||||||
|
public abstract fun run() : jet.Unit
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public trait SingleAbstractMethod {
|
||||||
|
fun foo()
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public trait SingleAbstractMethod {
|
||||||
|
internal abstract fun foo() : jet.Unit
|
||||||
|
}
|
||||||
@@ -178,6 +178,11 @@ public class LoadCompiledKotlinTestGenerated extends AbstractLoadCompiledKotlinT
|
|||||||
doTestWithAccessors("compiler/testData/loadKotlin/class/NestedGenericClass.kt");
|
doTestWithAccessors("compiler/testData/loadKotlin/class/NestedGenericClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SingleAbstractMethod.kt")
|
||||||
|
public void testSingleAbstractMethod() throws Exception {
|
||||||
|
doTestWithAccessors("compiler/testData/loadKotlin/class/SingleAbstractMethod.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("Trait.kt")
|
@TestMetadata("Trait.kt")
|
||||||
public void testTrait() throws Exception {
|
public void testTrait() throws Exception {
|
||||||
doTestWithAccessors("compiler/testData/loadKotlin/class/Trait.kt");
|
doTestWithAccessors("compiler/testData/loadKotlin/class/Trait.kt");
|
||||||
|
|||||||
@@ -971,7 +971,7 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/loadJava/compiledJava")
|
@TestMetadata("compiler/testData/loadJava/compiledJava")
|
||||||
@InnerTestClasses({CompiledJava.Annotations.class, CompiledJava.ProtectedPackage.class, CompiledJava.ProtectedStatic.class, CompiledJava.SignaturePropagation.class, CompiledJava.Static.class})
|
@InnerTestClasses({CompiledJava.Annotations.class, CompiledJava.ProtectedPackage.class, CompiledJava.ProtectedStatic.class, CompiledJava.SignaturePropagation.class, CompiledJava.SingleAbstractMethod.class, CompiledJava.Static.class})
|
||||||
public static class CompiledJava extends AbstractLoadJavaTest {
|
public static class CompiledJava extends AbstractLoadJavaTest {
|
||||||
public void testAllFilesPresentInCompiledJava() throws Exception {
|
public void testAllFilesPresentInCompiledJava() throws Exception {
|
||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/compiledJava"), Pattern.compile("^(.+)\\.java$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/compiledJava"), Pattern.compile("^(.+)\\.java$"), true);
|
||||||
@@ -1124,6 +1124,19 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/loadJava/compiledJava/singleAbstractMethod")
|
||||||
|
public static class SingleAbstractMethod extends AbstractLoadJavaTest {
|
||||||
|
public void testAllFilesPresentInSingleAbstractMethod() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/compiledJava/singleAbstractMethod"), Pattern.compile("^(.+)\\.java$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Runnable.java")
|
||||||
|
public void testRunnable() throws Exception {
|
||||||
|
doTestCompiledJava("compiler/testData/loadJava/compiledJava/singleAbstractMethod/Runnable.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/loadJava/compiledJava/static")
|
@TestMetadata("compiler/testData/loadJava/compiledJava/static")
|
||||||
public static class Static extends AbstractLoadJavaTest {
|
public static class Static extends AbstractLoadJavaTest {
|
||||||
public void testAllFilesPresentInStatic() throws Exception {
|
public void testAllFilesPresentInStatic() throws Exception {
|
||||||
@@ -1169,6 +1182,7 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
|||||||
suite.addTestSuite(ProtectedPackage.class);
|
suite.addTestSuite(ProtectedPackage.class);
|
||||||
suite.addTestSuite(ProtectedStatic.class);
|
suite.addTestSuite(ProtectedStatic.class);
|
||||||
suite.addTestSuite(SignaturePropagation.class);
|
suite.addTestSuite(SignaturePropagation.class);
|
||||||
|
suite.addTestSuite(SingleAbstractMethod.class);
|
||||||
suite.addTestSuite(Static.class);
|
suite.addTestSuite(Static.class);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -180,6 +180,11 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso
|
|||||||
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/class/NestedGenericClass.kt");
|
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/class/NestedGenericClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SingleAbstractMethod.kt")
|
||||||
|
public void testSingleAbstractMethod() throws Exception {
|
||||||
|
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/class/SingleAbstractMethod.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("Trait.kt")
|
@TestMetadata("Trait.kt")
|
||||||
public void testTrait() throws Exception {
|
public void testTrait() throws Exception {
|
||||||
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/class/Trait.kt");
|
doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadKotlin/class/Trait.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user