From d38d5f3d9b4438951b48da89d32df6ccc23f2daf Mon Sep 17 00:00:00 2001 From: i582 <51853996+i582@users.noreply.github.com> Date: Fri, 24 Jun 2022 16:22:48 +0300 Subject: [PATCH] added test base for type tests --- .../testing/infrastructure/TypeTestBase.kt | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/test/kotlin/com/vk/kphpstorm/testing/infrastructure/TypeTestBase.kt diff --git a/src/test/kotlin/com/vk/kphpstorm/testing/infrastructure/TypeTestBase.kt b/src/test/kotlin/com/vk/kphpstorm/testing/infrastructure/TypeTestBase.kt new file mode 100644 index 00000000..4aee7ce2 --- /dev/null +++ b/src/test/kotlin/com/vk/kphpstorm/testing/infrastructure/TypeTestBase.kt @@ -0,0 +1,98 @@ +package com.vk.kphpstorm.testing.infrastructure + +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiElement +import com.intellij.testFramework.fixtures.BasePlatformTestCase +import com.jetbrains.php.lang.psi.elements.FunctionReference +import com.jetbrains.php.lang.psi.elements.PhpPsiElement +import com.jetbrains.php.lang.psi.elements.PhpTypedElement +import com.jetbrains.php.lang.psi.elements.StringLiteralExpression +import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor +import com.vk.kphpstorm.configuration.KphpStormConfiguration +import com.vk.kphpstorm.exphptype.ExPhpTypePipe +import com.vk.kphpstorm.helpers.toExPhpType + +abstract class TypeTestBase : BasePlatformTestCase() { + override fun getTestDataPath() = "src/test/fixtures" + + protected open fun runFixture(vararg fixtureFiles: String) { + KphpStormConfiguration.saveThatSetupForProjectDone(project) + myFixture.configureByFiles(*fixtureFiles) + + runTypeTest(fixtureFiles) + } + + protected fun runTypeTest(fixtureFiles: Array) { + findExprTypeCalls(fixtureFiles).forEach { call -> + checkExprTypeCall(call) + } + } + + private inline fun PsiElement.findChildren(crossinline condition: (PsiElement) -> Boolean): List { + val result = mutableListOf() + accept(object : PhpElementVisitor() { + override fun visitElement(element: PsiElement) { + if (condition(element) && element is T) { + result.add(element) + } + + var child = element.firstChild + while (child != null) { + child.accept(this) + child = child.nextSibling + } + } + }) + return result + } + + private fun checkExprTypeCall(call: FunctionReference) { + val file = call.containingFile + val expr = call.parameters.first() as? PhpTypedElement ?: return + val expectedTypePsi = call.parameters.last() as? StringLiteralExpression ?: return + val expectedTypeString = expectedTypePsi.contents + val gotType = expr.type.global(myFixture.project).toExPhpType() + + val sortedGotType = if (gotType is ExPhpTypePipe) { + ExPhpTypePipe(gotType.items.sortedBy { it.toString() }) + } else { + gotType + } + + val gotTypeString = sortedGotType.toString().ifEmpty { "" } + + check(gotTypeString == expectedTypeString) { + """ + In file ${file.name}:${call.line()} + + Type mismatch. + Expected: $expectedTypeString + Found: $gotTypeString + + + """.trimIndent() + } + } + + private fun findExprTypeCalls(fixtureFiles: Array): List { + return fixtureFiles.map { + val file = myFixture.findFileInTempDir(it) ?: return@map emptyList() + myFixture.openFileInEditor(file) + + myFixture.file.findChildren { el -> + el is FunctionReference && el.name == "expr_type" && el.parameters.size == 2 && + el.parameters.last() is StringLiteralExpression && el.parameters.first() is PhpTypedElement + } + }.flatten() + } + + private fun PhpPsiElement.line(): Int { + val document = PsiDocumentManager.getInstance(project).getDocument(containingFile) + val lineNumber = if (document != null) { + document.getLineNumber(textRange.startOffset) + 1 + } else { + 0 + } + return lineNumber + } +}