/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.types;
import com.google.common.collect.Sets;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.analyzer.AnalysisResult;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider;
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl;
import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.psi.KtPsiFactoryKt;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingTraceContext;
import org.jetbrains.kotlin.resolve.TypeResolver;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory;
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeImpl;
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.kotlin.test.ConfigurationKind;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.KotlinTestWithEnvironment;
import org.jetbrains.kotlin.tests.di.ContainerForTests;
import org.jetbrains.kotlin.tests.di.InjectionKt;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class KotlinTypeCheckerTest extends KotlinTestWithEnvironment {
private KotlinBuiltIns builtIns;
private LexicalScope scopeWithImports;
private TypeResolver typeResolver;
private ExpressionTypingServices expressionTypingServices;
@Override
protected KotlinCoreEnvironment createEnvironment() {
return createEnvironmentWithMockJdk(ConfigurationKind.ALL);
}
@Override
public void setUp() throws Exception {
super.setUp();
ModuleDescriptorImpl module = KotlinTestUtils.createEmptyModule();
builtIns = module.getBuiltIns();
ContainerForTests container = InjectionKt.createContainerForTests(getProject(), module);
module.setDependencies(Collections.singletonList(module));
module.initialize(PackageFragmentProvider.Empty.INSTANCE);
typeResolver = container.getTypeResolver();
expressionTypingServices = container.getExpressionTypingServices();
scopeWithImports = getDeclarationsScope("compiler/testData/type-checker-test.kt");
}
@Override
protected void tearDown() throws Exception {
scopeWithImports = null;
expressionTypingServices = null;
typeResolver = null;
builtIns = null;
super.tearDown();
}
public void testConstants() throws Exception {
assertType("1", builtIns.getIntType());
assertType("0x1", builtIns.getIntType());
assertType("0X1", builtIns.getIntType());
assertType("0b1", builtIns.getIntType());
assertType("0B1", builtIns.getIntType());
assertType("1.toLong()", builtIns.getLongType());
assertType("1.0", builtIns.getDoubleType());
assertType("1.0.toDouble()", builtIns.getDoubleType());
assertType("1.0.toFloat()", builtIns.getFloatType());
assertType("true", builtIns.getBooleanType());
assertType("false", builtIns.getBooleanType());
assertType("'d'", builtIns.getCharType());
assertType("\"d\"", builtIns.getStringType());
assertType("\"\"\"d\"\"\"", builtIns.getStringType());
assertType("Unit", builtIns.getUnitType());
assertType("null", builtIns.getNullableNothingType());
}
public void testTypeInfo() throws Exception {
// todo: obsolete since removal of typeinfo
// assertType("typeinfo<Int>", "TypeInfo<Int>");
// assertType("typeinfo<TypeInfo<Int>>", "TypeInfo<TypeInfo<Int>>");
}
public void testJumps() throws Exception {
assertType("throw Exception()", builtIns.getNothingType());
assertType("continue", builtIns.getNothingType());
assertType("break", builtIns.getNothingType());
}
public void testIf() throws Exception {
assertType("if (true) 1", "Unit");
assertType("if (true) 1 else 1", "Int");
assertType("if (true) 1 else throw Exception()", "Int");
assertType("if (true) throw Exception() else 1", "Int");
assertType("if (true) throw Exception() else throw Exception()", "Nothing");
assertType("if (true) 1 else null", "Int?");
assertType("if (true) null else null", "Nothing?");
assertType("if (true) AI() else BI()", "I");
assertType("if (true) else '1'", "Unit");
assertType("if (true) else { var a = 0; a = 1 }", "Unit");
}
public void testWhen() throws Exception {
assertType("when (1) { is 1 -> 2; }", "Int");
assertType("when (1) { is 1 -> AI(); is 1 -> BI()}", "I");
assertType("when (1) { is 1 -> AI(); is 1 -> BI(); is 1 -> null}", "I?");
assertType("when (1) { is 1 -> AI(); is 1 -> BI(); else -> null}", "I?");
assertType("when (1) { is 1 -> AI(); is 1 -> BI(); is 1 -> when(2) {is 1 -> null}}", "I?");
}
public void testTry() throws Exception {
assertType("try {1} finally{2}", "Int");
assertType("try { AI() } catch (e : Exception) { BI() } finally{ CI() }", "I");
assertType("try {1} catch (e : Exception) {2} finally{'a'}", "Int");
assertType("try {CI()} catch (e : Exception) {AI(} finally{BI()}", "I");
assertType("try {AI()} catch (e : Exception) {BI()}", "I");
assertType("try {AI()} catch (e : Exception) {BI()} catch (e : Exception) {null}", "I?");
assertType("try {} catch (e : Exception) {}", "Unit");
}
public void testCommonSupertypes() throws Exception {
assertCommonSupertype("Int", "Int", "Int");
assertCommonSupertype("Int", "Int", "Nothing");
assertCommonSupertype("Int", "Nothing", "Int");
assertCommonSupertype("Nothing", "Nothing", "Nothing");
assertCommonSupertype("Int?", "Int", "Nothing?");
assertCommonSupertype("Nothing?", "Nothing?", "Nothing?");
assertCommonSupertype("I", "AI", "BI");
assertCommonSupertype("Base_T<*>", "Base_T<*>", "Derived_T<*>");
assertCommonSupertype("Any", "Base_inT<*>", "Derived_T<*>");
assertCommonSupertype("Derived_T<Int>", "DDerived_T<Int>", "Derived_T<Int>");
assertCommonSupertype("Derived_T<Int>", "DDerived_T<Int>", "DDerived1_T<Int>");
assertCommonSupertype("Comparable<*>", "Comparable<Int>", "Comparable<Boolean>");
assertCommonSupertype("Base_T<out I>", "Base_T<AI>", "Base_T<BI>");
assertCommonSupertype("Base_T<in Int>", "Base_T<Int>", "Base_T<in Int>");
assertCommonSupertype("Base_T<in Int>", "Derived_T<Int>", "Base_T<in Int>");
assertCommonSupertype("Base_T<in Int>", "Derived_T<in Int>", "Base_T<Int>");
assertCommonSupertype("Base_T<out Any?>", "Base_T<Int>", "Base_T<*>");
assertCommonSupertype("Base_T<out Parent>", "Base_T<A>", "Base_T<B>");
}
public void testCommonSupertypesForRecursive() throws Exception {
assertCommonSupertype("Rec<out Rec<out Rec<out Rec<out Rec<*>>>>>", "ARec", "BRec");
}
public void testIntersect() throws Exception {
assertIntersection("Long", "Long?", "Number");
assertIntersection("Long", "Number", "Long?");
assertIntersection("Number", "Number?", "Number");
assertIntersection("Int?", "Int?", "Int?");
assertIntersection("Int", "Int?", "Int");
assertIntersection("Int", "Int", "Int?");
assertIntersection("Int", "Any", "Int");
assertIntersection("Int", "Int", "Any");
assertIntersection("Int", "Any", "Int?");
assertIntersection("Int", "Int?", "Any");
assertIntersection("Int", "Any?", "Int");
assertIntersection("Int", "Int", "Any?");
assertIntersection("Nothing", "Nothing", "Nothing");
assertIntersection("Nothing?", "Nothing?", "Nothing?");
assertIntersection("Nothing", "Nothing", "Nothing?");
assertIntersection("Nothing", "Nothing?", "Nothing");
assertIntersection("Nothing?", "String?", "Nothing?");
assertIntersection("Nothing?", "Nothing?", "String?");
}
public void testBasicSubtyping() throws Exception {
assertSubtype("Boolean", "Boolean");
assertSubtype("Byte", "Byte");
assertSubtype("Char", "Char");
assertSubtype("Short", "Short");
assertSubtype("Int", "Int");
assertSubtype("Long", "Long");
assertSubtype("Float", "Float");
assertSubtype("Double", "Double");
assertSubtype("Unit", "Unit");
assertSubtype("Boolean", "Any");
assertSubtype("Byte", "Any");
assertSubtype("Char", "Any");
assertSubtype("Short", "Any");
assertSubtype("Int", "Any");
assertSubtype("Long", "Any");
assertSubtype("Float", "Any");
assertSubtype("Double", "Any");
assertSubtype("Unit", "Any");
assertSubtype("Any", "Any");
assertNotSubtype("Boolean", "Byte");
assertNotSubtype("Byte", "Short");
assertNotSubtype("Char", "Int");
assertNotSubtype("Short", "Int");
assertNotSubtype("Int", "Long");
assertNotSubtype("Long", "Double");
assertNotSubtype("Float", "Double");
assertNotSubtype("Double", "Int");
assertNotSubtype("Unit", "Int");
}
public void testProjections() throws Exception {
assertSubtype("Base_T<Int>", "Base_T<Int>");
assertNotSubtype("Base_T<Int>", "Base_T<Any>");
assertSubtype("Base_inT<Int>", "Base_inT<Int>");
assertSubtype("Base_inT<Any>", "Base_inT<Int>");
assertNotSubtype("Base_inT<Int>", "Base_inT<Any>");
assertSubtype("Base_outT<Int>", "Base_outT<Int>");
assertSubtype("Base_outT<Int>", "Base_outT<Any>");
assertNotSubtype("Base_outT<Any>", "Base_outT<Int>");
assertSubtype("Base_T<Int>", "Base_T<out Any>");
assertSubtype("Base_T<Any>", "Base_T<in Int>");
assertSubtype("Base_T<out Int>", "Base_T<out Int>");
assertSubtype("Base_T<in Int>", "Base_T<in Int>");
assertSubtype("Base_inT<out Int>", "Base_inT<out Int>");
assertSubtype("Base_inT<in Int>", "Base_inT<in Int>");
assertSubtype("Base_outT<out Int>", "Base_outT<out Int>");
assertSubtype("Base_outT<in Int>", "Base_outT<in Int>");
assertSubtype("Base_T<Int>", "Base_T<*>");
assertSubtype("Base_T<*>", "Base_T<*>");
assertSubtype("Base_T<Int>", "Base_T<out Any>");
assertSubtype("Base_T<Any>", "Base_T<in Int>");
assertNotSubtype("Base_T<out Any>", "Base_T<in Int>");
assertNotSubtype("Base_T<in Int>", "Base_T<out Int>");
assertNotSubtype("Base_T<*>", "Base_T<out Int>");
assertSubtype("Derived_T<Int>", "Base_T<Int>");
assertSubtype("Derived_outT<Int>", "Base_outT<Int>");
assertSubtype("Derived_inT<Int>", "Base_inT<Int>");
assertSubtype("Derived_T<*>", "Base_T<*>");
assertNotSubtype("Derived_T<Int>", "Base_T<Any>");
assertSubtype("Derived_outT<Int>", "Base_outT<Any>");
assertSubtype("Derived_T<Int>", "Base_T<out Any>");
assertSubtype("Derived_T<Any>", "Base_T<in Int>");
assertSubtype("Derived_T<Int>", "Base_T<in Int>");
assertSubtype("MDerived_T<Int>", "Base_T<in Int>");
assertSubtype("ArrayList<Int>", "InvList<in Int>");
// assertSubtype("java.lang.Integer", "java.lang.Comparable<java.lang.Integer>?");
}
public void testNullable() throws Exception {
assertSubtype("Any?", "Any?");
assertSubtype("Any", "Any?");
assertNotSubtype("Any?", "Any");
assertSubtype("Int", "Any?");
assertSubtype("Int?", "Any?");
assertNotSubtype("Int?", "Any");
}
public void testNothing() throws Exception {
assertSubtype("Nothing", "Any");
assertSubtype("Nothing?", "Any?");
assertNotSubtype("Nothing?", "Any");
assertSubtype("Nothing", "Int");
assertSubtype("Nothing?", "Int?");
assertNotSubtype("Nothing?", "Int");
assertSubtype("Nothing?", "Base_T<*>?");
assertSubtype("Nothing?", "Derived_T<*>?");
}
public void testStars() throws Exception {
assertSubtype("SubStar<*>", "Star<*>");
assertSubtype("SubStar<SubStar<*>>", "Star<*>");
assertSubtype("SubStar<SubStar<*>>", "Star<SubStar<*>>");
assertNotSubtype("SubStar<SubStar<*>>", "Star<Star<*>>");
assertSubtype("Star<Star<*>>", "Star<*>");
assertSubtype("Star<*>", "Star<out Star<*>>");
assertNotSubtype("Star<*>", "Star<Star<*>>");
assertSubtype("SubRec<*>", "Rec<*>");
assertSubtype("SubRec<*>", "Rec<out Any?>");
assertSubtype("Rec<*>", "Rec<out Any?>");
assertNotSubtype("Rec<*>", "Rec<out Any>");
}
public void testThis() throws Exception {
assertType("Derived_T<Int>", "this", "Derived_T<Int>");
// assertType("Derived_T<Int>", "super<Base_T>", "Base_T<Int>");
}
public void testLoops() throws Exception {
assertType("{ while (1) {1} }", "() -> Unit");
assertType("{ do {1} while(1) }", "() -> Unit");
assertType("{ for (i in 1) {1} }", "() -> Unit");
}
public void testFunctionLiterals() throws Exception {
assertType("{ -> }", "() -> Unit");
assertType("fun(): Int = 1", "() -> Int");
assertType("{ 1}", "() -> Int");
assertType("{ a : Int -> 1}", "(a : Int) -> Int");
assertType("{ a : Int, b : String -> 1}", "(a : Int, b : String) -> Int");
assertType("{ a : Int -> 1}", "(Int) -> Int");
assertType("{ a : Int, b : String -> 1}", "(Int, String) -> Int");
assertType("fun Any.(): Int = 1", "Any.() -> Int");
assertType("fun Any.(a : Int) = 1", "Any.(a : Int) -> Int");
assertType("fun Any.(a : Int, b : String) = 1", "Any.(a : Int, b : String) -> Int");
assertType("fun Any.(a : Int) = 1", "Any.(Int) -> Int");
assertType("fun Any.(a : Int, b : String) = 1", "Any.(Int, String) -> Int");
assertType("fun Any.(a : Int, b : String) = b", "Any.(Int, String) -> String");
}
public void testBlocks() throws Exception {
assertType("if (1) {val a = 1; a} else {null}", "Int?");
assertType("if (1) { -> val a = 1; a} else { -> null}", "Function0<Int?>");
assertType("if (1) (fun (): Boolean { val a = 1; a; var b : Boolean; return b }) else null", "Function0<Boolean>?");
assertType("if (1) (fun (): Int { val a = 1; a; var b = a; return b }) else null", "Function0<Int>?");
}
public void testNew() throws Exception {
assertType("Base_T<Int>()", "Base_T<Int>");
}
public void testPropertiesInClasses() throws Exception {
assertType("Properties().p", "Int");
assertType("Props<Int>().p", "Int");
assertType("Props<out Int>().p", "Int");
assertType("Props<Properties>().p.p", "Int");
assertType("(return as Props<in Int>).p", "Any?");
}
public void testOverloads() throws Exception {
assertType("Functions<String>().f()", "Unit");
assertType("Functions<String>().f(1)", "Int");
assertType("Functions<Double>().f(Pair(1, 1))", "Double");
assertType("Functions<Double>().f(1.0)", "Any");
assertType("Functions<Byte>().f<String>(\"\")", "Byte");
assertType("f()", "Unit");
assertType("f(1)", "Int");
assertType("f(1.toFloat(), 1)", "Float");
assertType("f<String>(1.toFloat())", "String");
}
public void testPlus() throws Exception {
assertType("1.0.plus(1.toDouble())", "Double");
assertType("1.0.plus(1.toFloat())", "Double");
assertType("1.0.plus(1.toLong())", "Double");
assertType("1.0.plus(1)", "Double");
assertType("1.toFloat().plus(1.toDouble())", "Double");
assertType("1.toFloat().plus(1.toFloat())", "Float");
assertType("1.toFloat().plus(1.toLong())", "Float");
assertType("1.toFloat().plus(1)", "Float");
assertType("1.toLong().plus(1.toDouble())", "Double");
assertType("1.toLong().plus(1.toFloat())", "Float");
assertType("1.toLong().plus(1.toLong())", "Long");
assertType("1.toLong().plus(1)", "Long");
assertType("1.plus(1.toDouble())", "Double");
assertType("1.plus(1.toFloat())", "Float");
assertType("1.plus(1.toLong())", "Long");
assertType("1.plus(1)", "Int");
assertType("'1'.plus(1)", "Char");
assertType("'1'.minus(1)", "Char");
assertType("'1'.minus('1')", "Int");
assertType("(1.toShort()).plus(1.toDouble())", "Double");
assertType("(1.toShort()).plus(1.toFloat())", "Float");
assertType("(1.toShort()).plus(1.toLong())", "Long");
assertType("(1.toShort()).plus(1)", "Int");
assertType("(1.toShort()).plus(1.toShort())", "Int");
assertType("(1.toByte()).plus(1.toDouble())", "Double");
assertType("(1.toByte()).plus(1.toFloat())", "Float");
assertType("(1.toByte()).plus(1.toLong())", "Long");
assertType("(1.toByte()).plus(1)", "Int");
assertType("(1.toByte()).plus(1.toShort())", "Int");
assertType("(1.toByte()).plus(1.toByte())", "Int");
assertType("\"1\".plus(1.toDouble())", "String");
assertType("\"1\".plus(1.toFloat())", "String");
assertType("\"1\".plus(1.toLong())", "String");
assertType("\"1\".plus(1)", "String");
assertType("\"1\".plus('1')", "String");
}
public void testBinaryOperations() throws Exception {
assertType("1 as Any", "Any");
assertType("1 is Char", "Boolean");
assertType("1 === null", "Boolean");
assertType("1 !== null", "Boolean");
assertType("true && false", "Boolean");
assertType("true || false", "Boolean");
assertType("null ?: false", "Boolean");
// assertType("WithPredicate()?isValid()", "WithPredicate?");
// assertType("WithPredicate()?isValid(1)", "WithPredicate?");
// assertType("WithPredicate()?p", "WithPredicate?");
}
public void testSupertypes() throws Exception {
assertSupertypes("DDerived1_T<Int>", "Derived_T<Int>", "Base_T<Int>", "Any");
assertSupertypes("DDerived2_T<Int>", "Derived_T<Int>", "Base_T<Int>", "Any");
assertSupertypes("Derived1_inT<Int>", "Derived_T<Int>", "Base_T<Int>", "Any", "Base_inT<Int>");
}
public void testEffectiveProjectionKinds() throws Exception {
assertSubtype("Base_outT<Int>", "Base_outT<Int>");
assertSubtype("Base_outT<out Int>", "Base_outT<out Int>");
assertSubtype("Base_outT<out Int>", "Base_outT<Int>");
assertSubtype("Base_outT<Int>", "Base_outT<out Int>");
assertSubtype("Base_outT<in Int>", "Base_outT<out Any?>");
assertSubtype("Base_outT<out Any?>", "Base_outT<in String>");
assertSubtype("Base_inT<Int>", "Base_inT<Int>");
assertSubtype("Base_inT<in Int>", "Base_inT<in Int>");
assertSubtype("Base_inT<in Int>", "Base_inT<Int>");
assertSubtype("Base_inT<Int>", "Base_inT<in Int>");
assertSubtype("Base_inT<out Int>", "Base_inT<out Any?>");
assertSubtype("Base_inT<out Any?>", "Base_inT<out Int>");
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void assertSupertypes(String typeStr, String... supertypeStrs) {
Set<KotlinType> allSupertypes = TypeUtils.getAllSupertypes(makeType(scopeWithImports, typeStr));
Set<KotlinType> expected = Sets.newHashSet();
for (String supertypeStr : supertypeStrs) {
KotlinType supertype = makeType(scopeWithImports, supertypeStr);
expected.add(supertype);
}
assertEquals(expected, allSupertypes);
}
private void assertSubtype(String subtype, String supertype) {
assertSubtypingRelation(subtype, supertype, true);
}
private void assertNotSubtype(String subtype, String supertype) {
assertSubtypingRelation(subtype, supertype, false);
}
private void assertIntersection(String expected, String... types) {
Set<KotlinType> typesToIntersect = new LinkedHashSet<>();
for (String type : types) {
typesToIntersect.add(makeType(type));
}
KotlinType result = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, typesToIntersect);
// assertNotNull("Intersection is null for " + typesToIntersect, result);
assertEquals(makeType(expected), result);
}
private void assertCommonSupertype(String expected, String... types) {
Collection<KotlinType> subtypes = new ArrayList<>();
for (String type : types) {
subtypes.add(makeType(type));
}
KotlinType result = CommonSupertypes.commonSupertype(subtypes);
assertTrue(result + " != " + expected, result.equals(makeType(expected)));
}
private void assertSubtypingRelation(String subtype, String supertype, boolean expected) {
KotlinType typeNode1 = makeType(subtype);
KotlinType typeNode2 = makeType(supertype);
boolean result = KotlinTypeChecker.DEFAULT.isSubtypeOf(
typeNode1,
typeNode2);
String modifier = expected ? "not " : "";
assertTrue(typeNode1 + " is " + modifier + "a subtype of " + typeNode2, result == expected);
}
private void assertType(String expression, KotlinType expectedType) {
Project project = getProject();
KtExpression ktExpression = KtPsiFactoryKt.KtPsiFactory(project).createExpression(expression);
KotlinType type = expressionTypingServices.getType(scopeWithImports, ktExpression, TypeUtils.NO_EXPECTED_TYPE, DataFlowInfoFactory.EMPTY, KotlinTestUtils.DUMMY_TRACE);
assertNotNull(type);
assertTrue(type + " != " + expectedType, type.equals(expectedType));
}
private void assertType(String contextType, String expression, String expectedType) {
KotlinType thisType = makeType(contextType);
ReceiverParameterDescriptorImpl receiverParameterDescriptor = new ReceiverParameterDescriptorImpl(
scopeWithImports.getOwnerDescriptor(),
new TransientReceiver(thisType)
);
LexicalScope scope = new LexicalScopeImpl(scopeWithImports, scopeWithImports.getOwnerDescriptor(), false,
receiverParameterDescriptor, LexicalScopeKind.SYNTHETIC);
assertType(scope, expression, expectedType);
}
private void assertType(String expression, String expectedTypeStr) {
assertType(scopeWithImports, expression, expectedTypeStr);
}
private void assertType(LexicalScope scope, String expression, String expectedTypeStr) {
Project project = getProject();
KtExpression ktExpression = KtPsiFactoryKt.KtPsiFactory(project).createExpression(expression);
KotlinType type = expressionTypingServices.getType(scope, ktExpression, TypeUtils.NO_EXPECTED_TYPE, DataFlowInfoFactory.EMPTY, new BindingTraceContext());
KotlinType expectedType = expectedTypeStr == null ? null : makeType(expectedTypeStr);
assertEquals(expectedType, type);
}
@NotNull
private LexicalScope getDeclarationsScope(String path) throws IOException {
KtFile ktFile = KotlinTestUtils.loadJetFile(getProject(), new File(path));
AnalysisResult result = JvmResolveUtil.analyze(ktFile, getEnvironment());
//noinspection ConstantConditions
return result.getBindingContext().get(BindingContext.LEXICAL_SCOPE, ktFile);
}
private KotlinType makeType(String typeStr) {
return makeType(scopeWithImports, typeStr);
}
private KotlinType makeType(LexicalScope scope, String typeStr) {
return typeResolver.resolveType(scope, KtPsiFactoryKt.KtPsiFactory(getProject()).createType(typeStr), KotlinTestUtils.DUMMY_TRACE, true);
}
}