added ConstraintSystemTest
This commit is contained in:
@@ -376,7 +376,7 @@ public class Renderers {
|
|||||||
typeBounds.add(constraintSystem.getTypeBounds(variable));
|
typeBounds.add(constraintSystem.getTypeBounds(variable));
|
||||||
}
|
}
|
||||||
Function<TypeBounds, String> renderTypeBounds = rendererToFunction(RENDER_TYPE_BOUNDS);
|
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());
|
"status:\n" + ConstraintsUtil.getDebugMessageForStatus(constraintSystem.getStatus());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+6
@@ -123,6 +123,12 @@ public class ConstraintsUtil {
|
|||||||
interestingMethods.add(method);
|
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(); ) {
|
for (Iterator<Method> iterator = interestingMethods.iterator(); iterator.hasNext(); ) {
|
||||||
Method method = iterator.next();
|
Method method = iterator.next();
|
||||||
try {
|
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