added ConstraintSystemTest
This commit is contained in:
@@ -376,7 +376,7 @@ public class Renderers {
|
||||
typeBounds.add(constraintSystem.getTypeBounds(variable));
|
||||
}
|
||||
Function<TypeBounds, String> renderTypeBounds = rendererToFunction(RENDER_TYPE_BOUNDS);
|
||||
return "type parameter bounds: \n" + StringUtil.join(typeBounds, renderTypeBounds, ";\n") + "\n" +
|
||||
return "type parameter bounds:\n" + StringUtil.join(typeBounds, renderTypeBounds, ";\n") + "\n" +
|
||||
"status:\n" + ConstraintsUtil.getDebugMessageForStatus(constraintSystem.getStatus());
|
||||
}
|
||||
};
|
||||
|
||||
+6
@@ -123,6 +123,12 @@ public class ConstraintsUtil {
|
||||
interestingMethods.add(method);
|
||||
}
|
||||
}
|
||||
Collections.sort(interestingMethods, new Comparator<Method>() {
|
||||
@Override
|
||||
public int compare(@NotNull Method method1, @NotNull Method method2) {
|
||||
return method1.getName().compareTo(method2.getName());
|
||||
}
|
||||
});
|
||||
for (Iterator<Method> iterator = interestingMethods.iterator(); iterator.hasNext(); ) {
|
||||
Method method = iterator.next();
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
fun foo<T, P, Q, R, S>() = 42
|
||||
|
||||
trait A
|
||||
trait B : A
|
||||
trait C : B
|
||||
|
||||
trait Consumer<in T>
|
||||
trait Producer<out T>
|
||||
|
||||
trait My<T>
|
||||
@@ -0,0 +1,18 @@
|
||||
VARIABLES T
|
||||
|
||||
SUBTYPE T Int
|
||||
SUPERTYPE T Int !
|
||||
|
||||
type parameter bounds:
|
||||
T >: Int(SPECIAL), <: Int(SPECIAL)
|
||||
status:
|
||||
-hasConflictingConstraints: false
|
||||
-hasContradiction: false
|
||||
-hasErrorInConstrainingTypes: false
|
||||
-hasTypeConstructorMismatch: false
|
||||
-hasUnknownParameters: false
|
||||
-hasViolatedUpperBound: false
|
||||
-isSuccessful: true
|
||||
|
||||
result:
|
||||
T=Int
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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.resolve.constraintSystem
|
||||
|
||||
import com.google.common.collect.ImmutableMap
|
||||
import com.google.common.collect.Maps
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.jet.ConfigurationKind
|
||||
import org.jetbrains.jet.JetLiteFixture
|
||||
import org.jetbrains.jet.JetTestUtils
|
||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust
|
||||
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment
|
||||
import org.jetbrains.jet.di.InjectorForTests
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory
|
||||
import org.jetbrains.jet.lang.diagnostics.rendering.Renderers
|
||||
import org.jetbrains.jet.lang.psi.*
|
||||
import org.jetbrains.jet.lang.resolve.*
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.types.Variance
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.Collections
|
||||
import com.intellij.openapi.project.Project
|
||||
import java.util.HashMap
|
||||
import java.util.regex.Pattern
|
||||
import org.jetbrains.jet.resolve.constraintSystem.ConstraintSystemTest.MyConstraintKind
|
||||
import org.jetbrains.jet.resolve.constraintSystem.ConstraintSystemTest.MyConstraint
|
||||
import java.util.ArrayList
|
||||
import kotlin.test.assertEquals
|
||||
import org.junit.Assert
|
||||
|
||||
public class ConstraintSystemTest() : JetLiteFixture() {
|
||||
|
||||
val constraintPattern = Pattern.compile("(SUBTYPE|SUPERTYPE|EQUALITY)\\s+(\\w+)\\s+(\\w+)", Pattern.MULTILINE)
|
||||
val variablesPattern = Pattern.compile("VARIABLES\\s+(.*)")
|
||||
|
||||
private var builtIns: KotlinBuiltIns? = null
|
||||
private var typeResolver: TypeResolver? = null
|
||||
private var expressionTypingServices: ExpressionTypingServices? = null
|
||||
private var functionDescriptor: FunctionDescriptor? = null
|
||||
private var scopeToResolveTypeParameters: JetScope? = null
|
||||
|
||||
override fun createEnvironment(): JetCoreEnvironment {
|
||||
return createEnvironmentWithMockJdk(ConfigurationKind.ALL)
|
||||
}
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
|
||||
builtIns = KotlinBuiltIns.getInstance()
|
||||
|
||||
val injector = InjectorForTests(getProject(), JetTestUtils.createEmptyModule()!!)
|
||||
typeResolver = injector.getTypeResolver()
|
||||
expressionTypingServices = injector.getExpressionTypingServices()
|
||||
|
||||
analyzeDeclarations()
|
||||
}
|
||||
|
||||
override fun getTestDataPath(): String {
|
||||
return super.getTestDataPath() + "/constraintSystem/"
|
||||
}
|
||||
|
||||
private fun analyzeDeclarations(): MyDeclarations {
|
||||
val fileName = "declarations/declarations.kt"
|
||||
|
||||
val psiFile = createPsiFile(null, fileName, loadFile(fileName))
|
||||
val analyzeExhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(psiFile, Collections.emptyList<AnalyzerScriptParameter>())!!
|
||||
val bindingContext = analyzeExhaust.getBindingContext()
|
||||
return MyDeclarations(bindingContext, getProject(), typeResolver!!)
|
||||
}
|
||||
|
||||
public fun testSimpleSuccessful() {
|
||||
doTest("compiler/testData/constraintSystem/simpleSuccessful.bounds")
|
||||
}
|
||||
|
||||
public fun doTest(filePath: String) {
|
||||
val file = File(filePath)
|
||||
val fileText = JetTestUtils.doLoadFile(file)!!
|
||||
|
||||
val constraintSystem = ConstraintSystemImpl()
|
||||
val myDeclarations = analyzeDeclarations()
|
||||
|
||||
val typeParameterDescriptors = HashMap<TypeParameterDescriptor, Variance>()
|
||||
val variables = parseVariables(fileText)
|
||||
for (variable in variables) {
|
||||
typeParameterDescriptors.put(myDeclarations.getParameterDescriptor(variable), Variance.INVARIANT)
|
||||
}
|
||||
constraintSystem.registerTypeVariables(typeParameterDescriptors)
|
||||
|
||||
val constraints = parseConstraints(fileText)
|
||||
for (constraint in constraints) {
|
||||
val firstType = myDeclarations.getType(constraint.firstType)
|
||||
val secondType = myDeclarations.getType(constraint.secondType)
|
||||
val position = if (constraint.isWeak) ConstraintPosition.getTypeBoundPosition(0)!! else ConstraintPosition.SPECIAL
|
||||
when (constraint.kind) {
|
||||
MyConstraintKind.SUBTYPE -> constraintSystem.addSubtypeConstraint(firstType, secondType, position)
|
||||
MyConstraintKind.SUPERTYPE -> constraintSystem.addSupertypeConstraint(firstType, secondType, position)
|
||||
}
|
||||
}
|
||||
|
||||
val expectedStatus = parseStatus(fileText)
|
||||
val resultingStatus = Renderers.RENDER_CONSTRAINT_SYSTEM.render(constraintSystem)
|
||||
Assert.assertEquals("Constraint system status mismatch", expectedStatus, resultingStatus)
|
||||
|
||||
val resultingSubstitutor = constraintSystem.getResultingSubstitutor()
|
||||
val result = StringBuilder() append "result:\n"
|
||||
for ((typeParameter, variance) in typeParameterDescriptors) {
|
||||
val resultForTypeParameter = resultingSubstitutor.substitute(myDeclarations.getType(typeParameter.getName().asString()), variance)
|
||||
result append "${typeParameter.getName()}=${resultForTypeParameter}"
|
||||
}
|
||||
|
||||
val expectedResult = parseResult(fileText)
|
||||
Assert.assertEquals("Constraint system substitution mismatch", expectedResult, result.toString())
|
||||
}
|
||||
|
||||
class MyConstraint(val kind: MyConstraintKind, val firstType: String, val secondType: String, val isWeak: Boolean)
|
||||
enum class MyConstraintKind {
|
||||
SUBTYPE SUPERTYPE
|
||||
}
|
||||
|
||||
private fun parseVariables(text: String): List<String> {
|
||||
val matcher = variablesPattern.matcher(text)
|
||||
if (matcher.find()) {
|
||||
val variablesText = matcher.group(1)!!
|
||||
val variables = variablesText.split(' ')
|
||||
return variables.toList()
|
||||
}
|
||||
throw AssertionError("Type variable names should be declared")
|
||||
}
|
||||
|
||||
private fun parseConstraints(text: String): List<MyConstraint> {
|
||||
val constraints = ArrayList<MyConstraint>()
|
||||
val matcher = constraintPattern.matcher(text)
|
||||
while (matcher.find()) {
|
||||
val kind = MyConstraintKind.valueOf(matcher.group(1)!!)
|
||||
val firstType = matcher.group(2)!!
|
||||
val secondType = matcher.group(3)!!
|
||||
val isWeak = matcher.groupCount() == 4 && matcher.group(4) == "!"
|
||||
constraints.add(MyConstraint(kind, firstType, secondType, isWeak))
|
||||
}
|
||||
return constraints
|
||||
}
|
||||
|
||||
private fun parseStatus(text: String) = text.substring(text.indexOf("type parameter bounds"), text.indexOf("result")).trim()
|
||||
|
||||
private fun parseResult(text: String) = text.substring(text.indexOf("result"), text.length())
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.resolve.constraintSystem
|
||||
|
||||
import com.google.common.collect.ImmutableMap
|
||||
import com.google.common.collect.Maps
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.jet.ConfigurationKind
|
||||
import org.jetbrains.jet.JetLiteFixture
|
||||
import org.jetbrains.jet.JetTestUtils
|
||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust
|
||||
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment
|
||||
import org.jetbrains.jet.di.InjectorForTests
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory
|
||||
import org.jetbrains.jet.lang.diagnostics.rendering.Renderers
|
||||
import org.jetbrains.jet.lang.psi.*
|
||||
import org.jetbrains.jet.lang.resolve.*
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.types.Variance
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.Collections
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
public class MyDeclarations(
|
||||
private val context: BindingContext,
|
||||
private val project: Project,
|
||||
private val typeResolver: TypeResolver
|
||||
) {
|
||||
private val functionFoo: FunctionDescriptor
|
||||
private val scopeToResolveTypeParameters: JetScope
|
||||
|
||||
{
|
||||
val functions = context.getSliceContents(BindingContext.FUNCTION)
|
||||
functionFoo = functions.values().iterator().next()
|
||||
val function = (BindingContextUtils.descriptorToDeclaration(context, functionFoo) as JetFunction)
|
||||
val fooBody = function.getBodyExpression()
|
||||
scopeToResolveTypeParameters = context.get(BindingContext.RESOLUTION_SCOPE, fooBody)!!
|
||||
}
|
||||
|
||||
fun getParameterDescriptor(name: String): TypeParameterDescriptor {
|
||||
for (typeParameter in functionFoo.getTypeParameters()) {
|
||||
if (typeParameter.getName().asString() == name) {
|
||||
return typeParameter;
|
||||
}
|
||||
}
|
||||
throw AssertionError("Unsupported type parameter name: " + name + ".")
|
||||
}
|
||||
|
||||
fun getType(name: String) = typeResolver.resolveType(
|
||||
scopeToResolveTypeParameters, JetPsiFactory.createType(project, name),
|
||||
JetTestUtils.DUMMY_TRACE, true)
|
||||
}
|
||||
Reference in New Issue
Block a user