From f06e5581aa8a6758b1d0eb8a5fd10274cd22c179 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Thu, 16 Oct 2014 19:19:10 +0400 Subject: [PATCH] Support creating flexible types in tests Flexible types can not be created in normal user code, but if there's a special classifier `kotlin.internal.flexible.ft` with two type parameters, its occurrences are replaced by flexible types, e.g. `ft` becomes `Int!` --- .../di/InjectorForLazyResolveWithJava.java | 4 ++ .../di/InjectorForTopDownAnalyzerForJvm.java | 4 ++ .../JavaFlexibleTypeCapabilitiesProvider.kt | 25 +++++++++ .../jet/di/InjectorForBodyResolve.java | 4 ++ .../jet/di/InjectorForLazyResolve.java | 4 ++ .../jetbrains/jet/di/InjectorForMacros.java | 4 ++ .../di/InjectorForTopDownAnalyzerBasic.java | 4 ++ .../jet/lang/resolve/DescriptorResolver.java | 20 +++++-- .../jet/lang/resolve/TypeResolver.java | 24 +++++++++ .../explicitFlexibleNoPackage.kt | 8 +++ .../explicitFlexibleNoPackage.txt | 11 ++++ .../explicitFlexibleWithPackage.kt | 9 ++++ .../explicitFlexibleWithPackage.txt | 13 +++++ .../checkers/AbstractJetDiagnosticsTest.java | 6 +-- .../jet/checkers/BaseDiagnosticsTest.java | 53 +++++++++++++++++-- .../checkers/JetDiagnosticsTestGenerated.java | 12 +++++ .../jetbrains/jet/di/InjectorForTests.java | 4 ++ .../jetbrains/jet/lang/types/flexibleTypes.kt | 11 ++++ .../generators/injectors/GenerateInjectors.kt | 7 ++- .../di/InjectorForTopDownAnalyzerForJs.java | 4 ++ 20 files changed, 220 insertions(+), 11 deletions(-) create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaFlexibleTypeCapabilitiesProvider.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleNoPackage.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleNoPackage.txt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleWithPackage.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleWithPackage.txt diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForLazyResolveWithJava.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForLazyResolveWithJava.java index 52b1c0faeb1..98c4d2e114e 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForLazyResolveWithJava.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForLazyResolveWithJava.java @@ -36,6 +36,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.PsiBasedMethodSignatureCheck import org.jetbrains.jet.lang.resolve.java.resolver.PsiBasedExternalAnnotationResolver; import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaPropertyInitializerEvaluatorImpl; import org.jetbrains.jet.lang.resolve.java.resolver.JavaSourceElementFactoryImpl; +import org.jetbrains.jet.lang.resolve.java.JavaFlexibleTypeCapabilitiesProvider; import org.jetbrains.jet.lang.resolve.AdditionalCheckerProvider; import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; @@ -92,6 +93,7 @@ public class InjectorForLazyResolveWithJava { private final PsiBasedExternalAnnotationResolver psiBasedExternalAnnotationResolver; private final JavaPropertyInitializerEvaluatorImpl javaPropertyInitializerEvaluator; private final JavaSourceElementFactoryImpl javaSourceElementFactory; + private final JavaFlexibleTypeCapabilitiesProvider javaFlexibleTypeCapabilitiesProvider; private final AdditionalCheckerProvider additionalCheckerProvider; private final AnnotationResolver annotationResolver; private final CallResolver callResolver; @@ -154,6 +156,7 @@ public class InjectorForLazyResolveWithJava { this.globalJavaResolverContext = new GlobalJavaResolverContext(storageManager, javaClassFinder, virtualFileFinder, deserializedDescriptorResolver, psiBasedExternalAnnotationResolver, traceBasedExternalSignatureResolver, traceBasedErrorReporter, psiBasedMethodSignatureChecker, lazyResolveBasedCache, javaPropertyInitializerEvaluator, javaSourceElementFactory, moduleClassResolver); this.lazyJavaPackageFragmentProvider = new LazyJavaPackageFragmentProvider(globalJavaResolverContext, module); this.javaDescriptorResolver = new JavaDescriptorResolver(lazyJavaPackageFragmentProvider, module); + this.javaFlexibleTypeCapabilitiesProvider = new JavaFlexibleTypeCapabilitiesProvider(); this.additionalCheckerProvider = org.jetbrains.jet.lang.resolve.kotlin.JavaDeclarationCheckerProvider.INSTANCE$; this.annotationResolver = new AnnotationResolver(); this.callResolver = new CallResolver(); @@ -250,6 +253,7 @@ public class InjectorForLazyResolveWithJava { delegatedPropertyResolver.setExpressionTypingServices(expressionTypingServices); typeResolver.setAnnotationResolver(annotationResolver); + typeResolver.setFlexibleTypeCapabilitiesProvider(javaFlexibleTypeCapabilitiesProvider); typeResolver.setModuleDescriptor(module); typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java index ac9c1fdabf3..d84032bb26f 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -38,6 +38,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.PsiBasedExternalAnnotationRe import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaPropertyInitializerEvaluatorImpl; import org.jetbrains.jet.lang.resolve.java.resolver.JavaSourceElementFactoryImpl; import org.jetbrains.jet.lang.resolve.java.lazy.SingleModuleClassResolver; +import org.jetbrains.jet.lang.resolve.java.JavaFlexibleTypeCapabilitiesProvider; import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileFinder; import org.jetbrains.jet.lang.resolve.BodyResolver; import org.jetbrains.jet.lang.resolve.AnnotationResolver; @@ -105,6 +106,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly private final JavaPropertyInitializerEvaluatorImpl javaPropertyInitializerEvaluator; private final JavaSourceElementFactoryImpl javaSourceElementFactory; private final SingleModuleClassResolver singleModuleClassResolver; + private final JavaFlexibleTypeCapabilitiesProvider javaFlexibleTypeCapabilitiesProvider; private final VirtualFileFinder virtualFileFinder; private final BodyResolver bodyResolver; private final AnnotationResolver annotationResolver; @@ -179,6 +181,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly this.deserializationGlobalContextForJava = new DeserializationGlobalContextForJava(storageManager, getModuleDescriptor(), javaClassDataFinder, annotationDescriptorLoader, constantDescriptorLoader, lazyJavaPackageFragmentProvider); this.additionalCheckerProvider = org.jetbrains.jet.lang.resolve.kotlin.JavaDeclarationCheckerProvider.INSTANCE$; this.globalSearchScope = com.intellij.psi.search.GlobalSearchScope.allScope(project); + this.javaFlexibleTypeCapabilitiesProvider = new JavaFlexibleTypeCapabilitiesProvider(); this.bodyResolver = new BodyResolver(); this.annotationResolver = new AnnotationResolver(); this.callResolver = new CallResolver(); @@ -303,6 +306,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly delegatedPropertyResolver.setExpressionTypingServices(expressionTypingServices); typeResolver.setAnnotationResolver(annotationResolver); + typeResolver.setFlexibleTypeCapabilitiesProvider(javaFlexibleTypeCapabilitiesProvider); typeResolver.setModuleDescriptor(moduleDescriptor); typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaFlexibleTypeCapabilitiesProvider.kt b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaFlexibleTypeCapabilitiesProvider.kt new file mode 100644 index 00000000000..9f8c5208bc4 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaFlexibleTypeCapabilitiesProvider.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2014 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 + +import org.jetbrains.jet.lang.resolve.TypeResolver.FlexibleTypeCapabilitiesProvider +import org.jetbrains.jet.lang.types.FlexibleTypeCapabilities +import org.jetbrains.jet.lang.resolve.java.lazy.types.LazyJavaTypeResolver + +public class JavaFlexibleTypeCapabilitiesProvider : FlexibleTypeCapabilitiesProvider() { + override fun getCapabilities(): FlexibleTypeCapabilities = LazyJavaTypeResolver.FlexibleJavaClassifierTypeCapabilities +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java index c3cb6aa4e1d..69761524c4d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForBodyResolve.java @@ -37,6 +37,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver; import org.jetbrains.jet.lang.resolve.DescriptorResolver; import org.jetbrains.jet.lang.resolve.DelegatedPropertyResolver; import org.jetbrains.jet.lang.resolve.TypeResolver; +import org.jetbrains.jet.lang.resolve.TypeResolver.FlexibleTypeCapabilitiesProvider; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolverExtensionProvider; import org.jetbrains.jet.lang.resolve.calls.CallCompleter; @@ -74,6 +75,7 @@ public class InjectorForBodyResolve { private final DescriptorResolver descriptorResolver; private final DelegatedPropertyResolver delegatedPropertyResolver; private final TypeResolver typeResolver; + private final FlexibleTypeCapabilitiesProvider flexibleTypeCapabilitiesProvider; private final QualifiedExpressionResolver qualifiedExpressionResolver; private final CallResolverExtensionProvider callResolverExtensionProvider; private final CallCompleter callCompleter; @@ -112,6 +114,7 @@ public class InjectorForBodyResolve { this.descriptorResolver = new DescriptorResolver(); this.delegatedPropertyResolver = new DelegatedPropertyResolver(); this.typeResolver = new TypeResolver(); + this.flexibleTypeCapabilitiesProvider = new FlexibleTypeCapabilitiesProvider(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.callResolverExtensionProvider = new CallResolverExtensionProvider(); this.candidateResolver = new CandidateResolver(); @@ -179,6 +182,7 @@ public class InjectorForBodyResolve { delegatedPropertyResolver.setExpressionTypingServices(expressionTypingServices); typeResolver.setAnnotationResolver(annotationResolver); + typeResolver.setFlexibleTypeCapabilitiesProvider(flexibleTypeCapabilitiesProvider); typeResolver.setModuleDescriptor(moduleDescriptor); typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java index b3e4cb04347..54860f07a43 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForLazyResolve.java @@ -38,6 +38,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver; import org.jetbrains.jet.lang.resolve.DescriptorResolver; import org.jetbrains.jet.lang.resolve.DelegatedPropertyResolver; import org.jetbrains.jet.lang.resolve.TypeResolver; +import org.jetbrains.jet.lang.resolve.TypeResolver.FlexibleTypeCapabilitiesProvider; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolverExtensionProvider; import org.jetbrains.jet.lang.resolve.calls.CallCompleter; @@ -74,6 +75,7 @@ public class InjectorForLazyResolve { private final DescriptorResolver descriptorResolver; private final DelegatedPropertyResolver delegatedPropertyResolver; private final TypeResolver typeResolver; + private final FlexibleTypeCapabilitiesProvider flexibleTypeCapabilitiesProvider; private final QualifiedExpressionResolver qualifiedExpressionResolver; private final CallResolverExtensionProvider callResolverExtensionProvider; private final CallCompleter callCompleter; @@ -112,6 +114,7 @@ public class InjectorForLazyResolve { this.descriptorResolver = new DescriptorResolver(); this.delegatedPropertyResolver = new DelegatedPropertyResolver(); this.typeResolver = new TypeResolver(); + this.flexibleTypeCapabilitiesProvider = new FlexibleTypeCapabilitiesProvider(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.callResolverExtensionProvider = new CallResolverExtensionProvider(); this.candidateResolver = new CandidateResolver(); @@ -175,6 +178,7 @@ public class InjectorForLazyResolve { delegatedPropertyResolver.setExpressionTypingServices(expressionTypingServices); typeResolver.setAnnotationResolver(annotationResolver); + typeResolver.setFlexibleTypeCapabilitiesProvider(flexibleTypeCapabilitiesProvider); typeResolver.setModuleDescriptor(moduleDescriptor); typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java index 0933ca98b58..eec3c63ffa9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java @@ -27,6 +27,7 @@ import org.jetbrains.jet.storage.StorageManager; import org.jetbrains.jet.lang.resolve.AdditionalCheckerProvider; import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.TypeResolver; +import org.jetbrains.jet.lang.resolve.TypeResolver.FlexibleTypeCapabilitiesProvider; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver; import org.jetbrains.jet.lang.resolve.DescriptorResolver; @@ -57,6 +58,7 @@ public class InjectorForMacros { private final AdditionalCheckerProvider additionalCheckerProvider; private final AnnotationResolver annotationResolver; private final TypeResolver typeResolver; + private final FlexibleTypeCapabilitiesProvider flexibleTypeCapabilitiesProvider; private final QualifiedExpressionResolver qualifiedExpressionResolver; private final CallExpressionResolver callExpressionResolver; private final DescriptorResolver descriptorResolver; @@ -85,6 +87,7 @@ public class InjectorForMacros { this.additionalCheckerProvider = org.jetbrains.jet.lang.resolve.AdditionalCheckerProvider.Empty.INSTANCE$; this.annotationResolver = new AnnotationResolver(); this.typeResolver = new TypeResolver(); + this.flexibleTypeCapabilitiesProvider = new FlexibleTypeCapabilitiesProvider(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.callExpressionResolver = new CallExpressionResolver(); this.descriptorResolver = new DescriptorResolver(); @@ -127,6 +130,7 @@ public class InjectorForMacros { annotationResolver.setTypeResolver(typeResolver); typeResolver.setAnnotationResolver(annotationResolver); + typeResolver.setFlexibleTypeCapabilitiesProvider(flexibleTypeCapabilitiesProvider); typeResolver.setModuleDescriptor(moduleDescriptor); typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java index bf3e0f9af85..69aa01d2258 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java @@ -40,6 +40,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver; import org.jetbrains.jet.lang.resolve.DescriptorResolver; import org.jetbrains.jet.lang.resolve.DelegatedPropertyResolver; import org.jetbrains.jet.lang.resolve.TypeResolver; +import org.jetbrains.jet.lang.resolve.TypeResolver.FlexibleTypeCapabilitiesProvider; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolverExtensionProvider; import org.jetbrains.jet.lang.resolve.calls.CallCompleter; @@ -87,6 +88,7 @@ public class InjectorForTopDownAnalyzerBasic { private final DescriptorResolver descriptorResolver; private final DelegatedPropertyResolver delegatedPropertyResolver; private final TypeResolver typeResolver; + private final FlexibleTypeCapabilitiesProvider flexibleTypeCapabilitiesProvider; private final QualifiedExpressionResolver qualifiedExpressionResolver; private final CallResolverExtensionProvider callResolverExtensionProvider; private final CallCompleter callCompleter; @@ -135,6 +137,7 @@ public class InjectorForTopDownAnalyzerBasic { this.descriptorResolver = new DescriptorResolver(); this.delegatedPropertyResolver = new DelegatedPropertyResolver(); this.typeResolver = new TypeResolver(); + this.flexibleTypeCapabilitiesProvider = new FlexibleTypeCapabilitiesProvider(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.callResolverExtensionProvider = new CallResolverExtensionProvider(); this.candidateResolver = new CandidateResolver(); @@ -228,6 +231,7 @@ public class InjectorForTopDownAnalyzerBasic { delegatedPropertyResolver.setExpressionTypingServices(expressionTypingServices); typeResolver.setAnnotationResolver(annotationResolver); + typeResolver.setFlexibleTypeCapabilitiesProvider(flexibleTypeCapabilitiesProvider); typeResolver.setModuleDescriptor(moduleDescriptor); typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index 041df5b63ed..f950c172572 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -1353,7 +1353,7 @@ public class DescriptorResolver { return propertyDescriptor; } - public static void checkBounds(@NotNull JetTypeReference typeReference, @NotNull JetType type, BindingTrace trace) { + public static void checkBounds(@NotNull JetTypeReference typeReference, @NotNull JetType type, @NotNull BindingTrace trace) { if (type.isError()) return; JetTypeElement typeElement = typeReference.getTypeElement(); @@ -1364,7 +1364,20 @@ public class DescriptorResolver { assert parameters.size() == arguments.size(); List jetTypeArguments = typeElement.getTypeArgumentsAsTypes(); - assert jetTypeArguments.size() == arguments.size() : typeElement.getText(); + + // A type reference from Kotlin code can yield a flexible type only if it's `ft`, whose bounds should not be checked + if (TypesPackage.isFlexible(type)) { + assert jetTypeArguments.size() == 2 + : "Flexible type cannot be denoted in Kotlin otherwise than as ft, but was: " + + JetPsiUtil.getElementTextWithContext(typeReference); + // it's really ft + Flexibility flexibility = TypesPackage.flexibility(type); + checkBounds(jetTypeArguments.get(0), flexibility.getLowerBound(), trace); + checkBounds(jetTypeArguments.get(1), flexibility.getUpperBound(), trace); + return; + } + + assert jetTypeArguments.size() == arguments.size() : typeElement.getText() + ": " + jetTypeArguments + " - " + arguments; TypeSubstitutor substitutor = TypeSubstitutor.create(type); for (int i = 0; i < jetTypeArguments.size(); i++) { @@ -1384,7 +1397,8 @@ public class DescriptorResolver { @NotNull JetTypeReference jetTypeArgument, @NotNull JetType typeArgument, @NotNull TypeParameterDescriptor typeParameterDescriptor, - @NotNull TypeSubstitutor substitutor, BindingTrace trace + @NotNull TypeSubstitutor substitutor, + @NotNull BindingTrace trace ) { for (JetType bound : typeParameterDescriptor.getUpperBounds()) { JetType substitutedBound = substitutor.safeSubstitute(bound, Variance.INVARIANT); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index 6dcd309de29..16b5faa55f0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -39,9 +39,16 @@ import static org.jetbrains.jet.storage.LockBasedStorageManager.NO_LOCKS; public class TypeResolver { + public static class FlexibleTypeCapabilitiesProvider { + public FlexibleTypeCapabilities getCapabilities() { + return FlexibleTypeCapabilities.NONE.INSTANCE$; + } + } + private AnnotationResolver annotationResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; private ModuleDescriptor moduleDescriptor; + private FlexibleTypeCapabilitiesProvider flexibleTypeCapabilitiesProvider; @Inject public void setAnnotationResolver(AnnotationResolver annotationResolver) { @@ -58,6 +65,12 @@ public class TypeResolver { this.moduleDescriptor = moduleDescriptor; } + + @Inject + public void setFlexibleTypeCapabilitiesProvider(@NotNull FlexibleTypeCapabilitiesProvider flexibleTypeCapabilitiesProvider) { + this.flexibleTypeCapabilitiesProvider = flexibleTypeCapabilitiesProvider; + } + @NotNull public JetType resolveType(@NotNull JetScope scope, @NotNull JetTypeReference typeReference, BindingTrace trace, boolean checkBounds) { // bare types are not allowed @@ -163,6 +176,17 @@ public class TypeResolver { } } else { + if (Flexibility.FLEXIBLE_TYPE_CLASSIFIER.asSingleFqName().equals(DescriptorUtils.getFqName(classifierDescriptor)) + && classDescriptor.getTypeConstructor().getParameters().size() == 2) { + // We create flexible types by convention here + // This is not intended to be used in normal users' environments, only for tests and debugger etc + result[0] = type(DelegatingFlexibleType.create( + arguments.get(0).getType(), + arguments.get(1).getType(), + flexibleTypeCapabilitiesProvider.getCapabilities() + )); + return; + } JetTypeImpl resultingType = new JetTypeImpl( annotations, typeConstructor, diff --git a/compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleNoPackage.kt b/compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleNoPackage.kt new file mode 100644 index 00000000000..a4ffd2a0567 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleNoPackage.kt @@ -0,0 +1,8 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !EXPLICIT_FLEXIBLE_TYPES +// !CHECK_TYPE + +fun foo(f: ft) { + f.checkType { it : _ } + f.checkType { it : _ } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleNoPackage.txt b/compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleNoPackage.txt new file mode 100644 index 00000000000..8712355dea2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleNoPackage.txt @@ -0,0 +1,11 @@ +package + +internal fun foo(/*0*/ f: kotlin.Int!): kotlin.Unit +internal fun T.checkType(/*0*/ f: (_) -> kotlin.Unit): (_) -> kotlin.Unit + +internal final class _ { + public constructor _() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleWithPackage.kt b/compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleWithPackage.kt new file mode 100644 index 00000000000..6082d7b856e --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleWithPackage.kt @@ -0,0 +1,9 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !EXPLICIT_FLEXIBLE_TYPES +// !CHECK_TYPE +package ppp + +fun foo(f: ft) { + f.checkType { it : _ } + f.checkType { it : _ } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleWithPackage.txt b/compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleWithPackage.txt new file mode 100644 index 00000000000..3eb50860a4e --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleWithPackage.txt @@ -0,0 +1,13 @@ +package + +package ppp { + internal fun foo(/*0*/ f: kotlin.Int!): kotlin.Unit + internal fun T.checkType(/*0*/ f: (ppp._) -> kotlin.Unit): (ppp._) -> kotlin.Unit + + internal final class _ { + public constructor _() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/AbstractJetDiagnosticsTest.java b/compiler/tests/org/jetbrains/jet/checkers/AbstractJetDiagnosticsTest.java index 6c3b6e199f3..0b28f61abfd 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/AbstractJetDiagnosticsTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/AbstractJetDiagnosticsTest.java @@ -81,7 +81,7 @@ public abstract class AbstractJetDiagnosticsTest extends BaseDiagnosticsTest { TestModule testModule = entry.getKey(); List testFilesInModule = entry.getValue(); - List jetFiles = getJetFiles(testFilesInModule); + List jetFiles = getJetFiles(testFilesInModule, true); allJetFiles.addAll(jetFiles); ModuleDescriptorImpl module = modules.get(testModule); @@ -194,8 +194,8 @@ public abstract class AbstractJetDiagnosticsTest extends BaseDiagnosticsTest { JetTestUtils.assertEqualsToFile(expectedFile, rootPackageText.toString()); } - public static RecursiveDescriptorComparator.Configuration createdAffectedPackagesConfiguration(List testFiles) { - final Set packagesNames = LazyResolveTestUtil.getTopLevelPackagesFromFileList(getJetFiles(testFiles)); + public RecursiveDescriptorComparator.Configuration createdAffectedPackagesConfiguration(List testFiles) { + final Set packagesNames = LazyResolveTestUtil.getTopLevelPackagesFromFileList(getJetFiles(testFiles, false)); Predicate stepIntoFilter = new Predicate() { @Override diff --git a/compiler/tests/org/jetbrains/jet/checkers/BaseDiagnosticsTest.java b/compiler/tests/org/jetbrains/jet/checkers/BaseDiagnosticsTest.java index df353d0ebce..9a67db5e7fa 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/BaseDiagnosticsTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/BaseDiagnosticsTest.java @@ -46,6 +46,7 @@ import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.Diagnostics; +import org.jetbrains.jet.lang.types.Flexibility; import org.jetbrains.jet.utils.UtilsPackage; import org.junit.Assert; @@ -73,6 +74,14 @@ public abstract class BaseDiagnosticsTest extends JetLiteFixture { private static final String CHECK_TYPE_DECLARATIONS = "\nclass _" + "\nfun T.checkType(f: (_) -> Unit) = f"; + public static final String EXPLICIT_FLEXIBLE_TYPES_DIRECTIVE = "EXPLICIT_FLEXIBLE_TYPES"; + public static final String EXPLICIT_FLEXIBLE_PACKAGE = Flexibility.FLEXIBLE_TYPE_CLASSIFIER.getPackageFqName().asString(); + public static final String EXPLICIT_FLEXIBLE_CLASS_NAME = Flexibility.FLEXIBLE_TYPE_CLASSIFIER.getRelativeClassName().asString(); + private static final String EXPLICIT_FLEXIBLE_TYPES_DECLARATIONS + = "\npackage " + EXPLICIT_FLEXIBLE_PACKAGE + + "\npublic class " + EXPLICIT_FLEXIBLE_CLASS_NAME + ""; + private static final String EXPLICIT_FLEXIBLE_TYPES_IMPORT = "import " + EXPLICIT_FLEXIBLE_PACKAGE + "." + EXPLICIT_FLEXIBLE_CLASS_NAME; + @Override protected JetCoreEnvironment createEnvironment() { File javaFilesDir = createJavaFilesDir(); @@ -172,13 +181,20 @@ public abstract class BaseDiagnosticsTest extends JetLiteFixture { List files ); - protected static List getJetFiles(List testFiles) { + protected List getJetFiles(List testFiles, boolean includeExtras) { + boolean declareFlexibleType = false; List jetFiles = Lists.newArrayList(); for (TestFile testFile : testFiles) { if (testFile.getJetFile() != null) { jetFiles.add(testFile.getJetFile()); } + declareFlexibleType |= testFile.declareFlexibleType; } + + if (declareFlexibleType && includeExtras) { + jetFiles.add(createPsiFile(null, "EXPLICIT_FLEXIBLE_TYPES.kt", EXPLICIT_FLEXIBLE_TYPES_DECLARATIONS)); + } + return jetFiles; } @@ -280,6 +296,7 @@ public abstract class BaseDiagnosticsTest extends JetLiteFixture { private final JetFile jetFile; private final Condition whatDiagnosticsToConsider; private final boolean declareCheckType; + private final boolean declareFlexibleType; public TestFile( @Nullable TestModule module, @@ -290,6 +307,7 @@ public abstract class BaseDiagnosticsTest extends JetLiteFixture { this.module = module; this.whatDiagnosticsToConsider = parseDiagnosticFilterDirective(directives); this.declareCheckType = directives.containsKey(CHECK_TYPE_DIRECTIVE); + this.declareFlexibleType = directives.containsKey(EXPLICIT_FLEXIBLE_TYPES_DIRECTIVE); if (fileName.endsWith(".java")) { PsiFileFactory.getInstance(getProject()).createFileFromText(fileName, JavaLanguage.INSTANCE, textWithMarkers); // TODO: check there's not syntax errors @@ -299,14 +317,40 @@ public abstract class BaseDiagnosticsTest extends JetLiteFixture { else { expectedText = textWithMarkers; clearText = CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges); - this.jetFile = createCheckAndReturnPsiFile( - null, fileName, declareCheckType ? clearText + CHECK_TYPE_DECLARATIONS : clearText); + this.jetFile = createCheckAndReturnPsiFile(null, fileName, makeText()); for (CheckerTestUtil.DiagnosedRange diagnosedRange : diagnosedRanges) { diagnosedRange.setFile(jetFile); } } } + private String makeText() { + String text = declareCheckType ? clearText + CHECK_TYPE_DECLARATIONS : clearText; + if (declareFlexibleType) { + Pattern pattern = Pattern.compile("^package [\\.\\w\\d]*\n", Pattern.MULTILINE); + Matcher matcher = pattern.matcher(text); + if (matcher.find()) { + // add import after the package directive + text = text.substring(0, matcher.end()) + EXPLICIT_FLEXIBLE_TYPES_IMPORT + "\n" + text.substring(matcher.end()); + } + else { + // add import at the beginning + text = EXPLICIT_FLEXIBLE_TYPES_IMPORT + "\n" + text; + } + } + return text; + } + + private void stripFlexibleTypes(StringBuilder actualText) { + if (declareFlexibleType) { + String pattern = EXPLICIT_FLEXIBLE_TYPES_IMPORT + "\n"; + int start = actualText.indexOf(pattern); + if (start >= 0) { + actualText.delete(start, start + pattern.length()); + } + } + } + @Nullable public TestModule getModule() { return module; @@ -358,6 +402,9 @@ public abstract class BaseDiagnosticsTest extends JetLiteFixture { return declareCheckType ? StringUtil.trimEnd(text, CHECK_TYPE_DECLARATIONS) : text; } })); + + stripFlexibleTypes(actualText); + return ok[0]; } diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index bd20880a91e..46e182d0346 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -7705,6 +7705,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("explicitFlexibleNoPackage.kt") + public void testExplicitFlexibleNoPackage() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleNoPackage.kt"); + doTest(fileName); + } + + @TestMetadata("explicitFlexibleWithPackage.kt") + public void testExplicitFlexibleWithPackage() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/explicitFlexibleWithPackage.kt"); + doTest(fileName); + } + @TestMetadata("getParentOfType.kt") public void testGetParentOfType() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/getParentOfType.kt"); diff --git a/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java b/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java index 39aa65f88a4..2656425be67 100644 --- a/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java +++ b/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java @@ -38,6 +38,7 @@ import org.jetbrains.jet.lang.types.expressions.ForLoopConventionsChecker; import org.jetbrains.jet.lang.reflect.ReflectionTypes; import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolverExtensionProvider; +import org.jetbrains.jet.lang.resolve.TypeResolver.FlexibleTypeCapabilitiesProvider; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.annotations.NotNull; import javax.annotation.PreDestroy; @@ -68,6 +69,7 @@ public class InjectorForTests { private final ReflectionTypes reflectionTypes; private final CallExpressionResolver callExpressionResolver; private final CallResolverExtensionProvider callResolverExtensionProvider; + private final FlexibleTypeCapabilitiesProvider flexibleTypeCapabilitiesProvider; private final QualifiedExpressionResolver qualifiedExpressionResolver; public InjectorForTests( @@ -96,6 +98,7 @@ public class InjectorForTests { this.reflectionTypes = new ReflectionTypes(moduleDescriptor); this.callExpressionResolver = new CallExpressionResolver(); this.callResolverExtensionProvider = new CallResolverExtensionProvider(); + this.flexibleTypeCapabilitiesProvider = new FlexibleTypeCapabilitiesProvider(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.descriptorResolver.setAnnotationResolver(annotationResolver); @@ -113,6 +116,7 @@ public class InjectorForTests { this.expressionTypingServices.setTypeResolver(typeResolver); this.typeResolver.setAnnotationResolver(annotationResolver); + this.typeResolver.setFlexibleTypeCapabilitiesProvider(flexibleTypeCapabilitiesProvider); this.typeResolver.setModuleDescriptor(moduleDescriptor); this.typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/flexibleTypes.kt b/core/descriptors/src/org/jetbrains/jet/lang/types/flexibleTypes.kt index f290f538fee..a1e6cefaffb 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/flexibleTypes.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/flexibleTypes.kt @@ -20,6 +20,9 @@ import org.jetbrains.jet.lang.types.checker.JetTypeChecker import org.jetbrains.jet.lang.types.Approximation.DataFlowExtras import org.jetbrains.jet.lang.resolve.name.FqName import kotlin.platform.platformStatic +import org.jetbrains.jet.lang.resolve.name.ClassId +import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe +import org.jetbrains.jet.lang.resolve.name.Name public trait FlexibleTypeCapabilities { fun getCapability(capabilityClass: Class, jetType: JetType, flexibility: Flexibility): T? @@ -32,6 +35,14 @@ public trait FlexibleTypeCapabilities { } public trait Flexibility : TypeCapability { + class object { + // This is a "magic" classifier: when type resolver sees it in the code, e.g. ft, instead of creating a normal type, + // it creates a flexible type, e.g. (Foo..Foo?). + // This is used in tests and Evaluate Expression to have flexible types in the code, + // but normal users should not be referencing this classifier + public val FLEXIBLE_TYPE_CLASSIFIER: ClassId = ClassId(FqName("kotlin.internal.flexible"), FqNameUnsafe.topLevel(Name.identifier("ft"))) + } + // lowerBound is a subtype of upperBound public val lowerBound: JetType public val upperBound: JetType diff --git a/generators/src/org/jetbrains/jet/generators/injectors/GenerateInjectors.kt b/generators/src/org/jetbrains/jet/generators/injectors/GenerateInjectors.kt index f7537eb2489..1834a2c47d0 100644 --- a/generators/src/org/jetbrains/jet/generators/injectors/GenerateInjectors.kt +++ b/generators/src/org/jetbrains/jet/generators/injectors/GenerateInjectors.kt @@ -41,6 +41,7 @@ import org.jetbrains.jet.lang.resolve.java.lazy.SingleModuleClassResolver import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileFinderFactory import org.jetbrains.jet.lang.resolve.java.TopDownAnalyzerFacadeForJVM import org.jetbrains.jet.lang.resolve.kotlin.JavaDeclarationCheckerProvider +import org.jetbrains.jet.lang.resolve.java.JavaFlexibleTypeCapabilitiesProvider // NOTE: After making changes, you need to re-generate the injectors. // To do that, you can run main in this file. @@ -120,7 +121,8 @@ private fun generatorForTopDownAnalyzerForJvm() = javaClass(), javaClass(), javaClass(), - javaClass() + javaClass(), + javaClass() ) field(javaClass(), init = GivenExpression(javaClass().getName() + ".SERVICE.getInstance(project)")) } @@ -185,7 +187,8 @@ private fun generatorForLazyResolveWithJava() = javaClass(), javaClass(), javaClass(), - javaClass() + javaClass(), + javaClass() ) field(javaClass(), init = GivenExpression(javaClass().getName() + ".INSTANCE$")) diff --git a/js/js.frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java b/js/js.frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java index 90cbe4aa2c8..b7ea13d0776 100644 --- a/js/js.frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java +++ b/js/js.frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java @@ -40,6 +40,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver; import org.jetbrains.jet.lang.resolve.DescriptorResolver; import org.jetbrains.jet.lang.resolve.DelegatedPropertyResolver; import org.jetbrains.jet.lang.resolve.TypeResolver; +import org.jetbrains.jet.lang.resolve.TypeResolver.FlexibleTypeCapabilitiesProvider; import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolverExtensionProvider; import org.jetbrains.jet.lang.resolve.calls.CallCompleter; @@ -87,6 +88,7 @@ public class InjectorForTopDownAnalyzerForJs { private final DescriptorResolver descriptorResolver; private final DelegatedPropertyResolver delegatedPropertyResolver; private final TypeResolver typeResolver; + private final FlexibleTypeCapabilitiesProvider flexibleTypeCapabilitiesProvider; private final QualifiedExpressionResolver qualifiedExpressionResolver; private final CallResolverExtensionProvider callResolverExtensionProvider; private final CallCompleter callCompleter; @@ -134,6 +136,7 @@ public class InjectorForTopDownAnalyzerForJs { this.descriptorResolver = new DescriptorResolver(); this.delegatedPropertyResolver = new DelegatedPropertyResolver(); this.typeResolver = new TypeResolver(); + this.flexibleTypeCapabilitiesProvider = new FlexibleTypeCapabilitiesProvider(); this.qualifiedExpressionResolver = new QualifiedExpressionResolver(); this.callResolverExtensionProvider = new CallResolverExtensionProvider(); this.candidateResolver = new CandidateResolver(); @@ -227,6 +230,7 @@ public class InjectorForTopDownAnalyzerForJs { delegatedPropertyResolver.setExpressionTypingServices(expressionTypingServices); typeResolver.setAnnotationResolver(annotationResolver); + typeResolver.setFlexibleTypeCapabilitiesProvider(flexibleTypeCapabilitiesProvider); typeResolver.setModuleDescriptor(moduleDescriptor); typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver);