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<Int, Int?>` becomes `Int!`
This commit is contained in:
Andrey Breslav
2014-10-16 19:19:10 +04:00
parent 8067a9ad56
commit f06e5581aa
20 changed files with 220 additions and 11 deletions
@@ -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);
@@ -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);
@@ -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
}
@@ -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);
@@ -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);
@@ -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);
@@ -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);
@@ -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<JetTypeReference> 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<T1, T2>`, 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<T1, T2>, but was: "
+ JetPsiUtil.getElementTextWithContext(typeReference);
// it's really ft<Foo, Bar>
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);
@@ -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,
@@ -0,0 +1,8 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !EXPLICIT_FLEXIBLE_TYPES
// !CHECK_TYPE
fun foo(f: ft<Int, Int?>) {
f.checkType { it : _<Int> }
f.checkType { it : _<Int?> }
}
@@ -0,0 +1,11 @@
package
internal fun foo(/*0*/ f: kotlin.Int!): kotlin.Unit
internal fun </*0*/ T> T.checkType(/*0*/ f: (_<T>) -> kotlin.Unit): (_<T>) -> kotlin.Unit
internal final class _</*0*/ T> {
public constructor _</*0*/ T>()
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
}
@@ -0,0 +1,9 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !EXPLICIT_FLEXIBLE_TYPES
// !CHECK_TYPE
package ppp
fun foo(f: ft<Int, Int?>) {
f.checkType { it : _<Int> }
f.checkType { it : _<Int?> }
}
@@ -0,0 +1,13 @@
package
package ppp {
internal fun foo(/*0*/ f: kotlin.Int!): kotlin.Unit
internal fun </*0*/ T> T.checkType(/*0*/ f: (ppp._<T>) -> kotlin.Unit): (ppp._<T>) -> kotlin.Unit
internal final class _</*0*/ T> {
public constructor _</*0*/ T>()
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
}
}
@@ -81,7 +81,7 @@ public abstract class AbstractJetDiagnosticsTest extends BaseDiagnosticsTest {
TestModule testModule = entry.getKey();
List<? extends TestFile> testFilesInModule = entry.getValue();
List<JetFile> jetFiles = getJetFiles(testFilesInModule);
List<JetFile> 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<TestFile> testFiles) {
final Set<Name> packagesNames = LazyResolveTestUtil.getTopLevelPackagesFromFileList(getJetFiles(testFiles));
public RecursiveDescriptorComparator.Configuration createdAffectedPackagesConfiguration(List<TestFile> testFiles) {
final Set<Name> packagesNames = LazyResolveTestUtil.getTopLevelPackagesFromFileList(getJetFiles(testFiles, false));
Predicate<DeclarationDescriptor> stepIntoFilter = new Predicate<DeclarationDescriptor>() {
@Override
@@ -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 _<T>" +
"\nfun <T> T.checkType(f: (_<T>) -> 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 + "<L, U>";
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<TestFile> files
);
protected static List<JetFile> getJetFiles(List<? extends TestFile> testFiles) {
protected List<JetFile> getJetFiles(List<? extends TestFile> testFiles, boolean includeExtras) {
boolean declareFlexibleType = false;
List<JetFile> 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<Diagnostic> 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];
}
@@ -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");
@@ -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);
@@ -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 <T: TypeCapability> getCapability(capabilityClass: Class<T>, 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<Foo, Foo?>, 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
@@ -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<MutablePackageFragmentProvider>(),
javaClass<JavaPropertyInitializerEvaluatorImpl>(),
javaClass<JavaSourceElementFactoryImpl>(),
javaClass<SingleModuleClassResolver>()
javaClass<SingleModuleClassResolver>(),
javaClass<JavaFlexibleTypeCapabilitiesProvider>()
)
field(javaClass<VirtualFileFinder>(), init = GivenExpression(javaClass<VirtualFileFinder>().getName() + ".SERVICE.getInstance(project)"))
}
@@ -185,7 +187,8 @@ private fun generatorForLazyResolveWithJava() =
javaClass<PsiBasedMethodSignatureChecker>(),
javaClass<PsiBasedExternalAnnotationResolver>(),
javaClass<JavaPropertyInitializerEvaluatorImpl>(),
javaClass<JavaSourceElementFactoryImpl>()
javaClass<JavaSourceElementFactoryImpl>(),
javaClass<JavaFlexibleTypeCapabilitiesProvider>()
)
field(javaClass<AdditionalCheckerProvider>(),
init = GivenExpression(javaClass<JavaDeclarationCheckerProvider>().getName() + ".INSTANCE$"))
@@ -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);