[test] Fix test diff document synchronization

Also makes it so the update uses string content replacement instead of PSI literal replacement.

GitOrigin-RevId: 43f8a0b5712e3807e1b0a043e33e2711d99412ef
This commit is contained in:
Bart van Helvert
2022-12-08 15:16:46 +01:00
committed by intellij-monorepo-bot
parent 5f4f432ec3
commit a7a1e540ce
9 changed files with 75 additions and 45 deletions

View File

@@ -2,7 +2,6 @@
package com.intellij.execution.testframework
import com.intellij.codeInsight.CodeInsightUtil
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.util.asSafely
import com.intellij.util.containers.ContainerUtil
@@ -10,10 +9,6 @@ import com.siyeh.ig.testFrameworks.AssertHint.Companion.createAssertEqualsHint
import org.jetbrains.uast.UMethod
class JavaTestDiffProvider : JvmTestDiffProvider<PsiMethodCallExpression>() {
override fun createActual(project: Project, element: PsiElement, actual: String): PsiElement {
return PsiElementFactory.getInstance(project).createExpressionFromText("\"$actual\"", element)
}
override fun getParamIndex(param: PsiElement): Int? {
if (param is PsiParameter) {
return param.parent.asSafely<PsiParameterList>()?.parameters?.indexOf<PsiElement>(param)

View File

@@ -43,5 +43,4 @@ default.package.presentable.name=<default>
test.config.first.pattern.and.few.more={0} and {1} more
all.tests.scope.presentable.text=All Tests
failed.to.start.message=Failed to start ''{0}''
notification.group.test.runner=Test execution finished
test.diff.update.command=Update Expected With Actual
notification.group.test.runner=Test execution finished

View File

@@ -6,12 +6,11 @@ import com.intellij.diff.actions.DocumentsSynchronizer
import com.intellij.diff.actions.SynchronizedDocumentContent
import com.intellij.diff.contents.DocumentContent
import com.intellij.diff.util.DiffUserDataKeysEx
import com.intellij.execution.testframework.TestRunnerBundle
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.event.DocumentEvent
import com.intellij.openapi.fileTypes.FileType
import com.intellij.openapi.fileTypes.FileTypes
import com.intellij.openapi.project.Project
import com.intellij.psi.ElementManipulators
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.SmartPsiElementPointer
@@ -22,24 +21,24 @@ class TestDiffContent(
private val project: Project,
original: DocumentContent,
text: String,
private val elemPtr: SmartPsiElementPointer<PsiElement>,
private val createActual: (Project, PsiElement, String) -> PsiElement
private val elemPtr: SmartPsiElementPointer<PsiElement>
) : SynchronizedDocumentContent(original) {
override fun getContentType(): FileType = FileTypes.PLAIN_TEXT
override val synchronizer: DocumentsSynchronizer = object : DocumentsSynchronizer(project, original.document, fakeDocument) {
override fun onDocumentChanged1(event: DocumentEvent) {
replaceString(myDocument2, 0, myDocument2.textLength, event.newFragment)
PsiDocumentManager.getInstance(project).performForCommittedDocument(document1, Runnable {
val element = elemPtr.element ?: return@Runnable
replaceString(myDocument2, 0, myDocument2.textLength, ElementManipulators.getValueText(element))
})
}
override fun onDocumentChanged2(event: DocumentEvent) {
if (!myDocument1.isWritable) return
val element = elemPtr.element ?: return
try {
myDuringModification = true
WriteCommandAction.runWriteCommandAction(project, TestRunnerBundle.message("test.diff.update.command"), null, Runnable {
element.replace(createActual(project, element, event.newFragment.toString()))
})
val element = elemPtr.element ?: return
ElementManipulators.handleContentChange(element, event.document.text)
} finally {
myDuringModification = false
}
@@ -55,13 +54,12 @@ class TestDiffContent(
fun create(
project: Project,
text: String,
elemPtr: SmartPsiElementPointer<PsiElement>,
replacement: (Project, PsiElement, String) -> PsiElement
elemPtr: SmartPsiElementPointer<PsiElement>
): TestDiffContent? {
val element = elemPtr.element ?: return null
val document = PsiDocumentManager.getInstance(project).getDocument(element.containingFile) ?: return null
val diffContent = DiffContentFactory.getInstance().create(project, document)
return TestDiffContent(project, diffContent, text, elemPtr, replacement).apply {
return TestDiffContent(project, diffContent, text, elemPtr).apply {
val originalLineConvertor = original.getUserData(DiffUserDataKeysEx.LINE_NUMBER_CONVERTOR)
putUserData(DiffUserDataKeysEx.LINE_NUMBER_CONVERTOR, IntUnaryOperator { value ->
if (!element.isValid) return@IntUnaryOperator - 1

View File

@@ -5,7 +5,6 @@ import com.intellij.lang.LanguageExtension;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.util.concurrency.annotations.RequiresReadLock;
import com.intellij.util.concurrency.annotations.RequiresWriteLock;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -23,13 +22,4 @@ public interface TestDiffProvider {
@Nullable
@RequiresReadLock
PsiElement findExpected(@NotNull Project project, @NotNull String stackTrace);
/**
* Creates the actual literal from text for replacement
* @param element The string literal element to replace
* @param actual The text used for the replacement
*/
@NotNull
@RequiresWriteLock
PsiElement createActual(@NotNull Project project, @NotNull PsiElement element, @NotNull String actual);
}

View File

@@ -89,7 +89,7 @@ public class TestDiffRequestProcessor {
PsiElement expected = ReadAction.compute(() -> getExpected(provider, testProxy));
if (expected != null) {
file1 = ReadAction.compute(() -> PsiUtilCore.getVirtualFile(expected));
content1 = ReadAction.compute(() -> createPsiDiffContent(provider, expected, text1));
content1 = ReadAction.compute(() -> createPsiDiffContent(expected, text1));
}
}
}
@@ -118,11 +118,9 @@ public class TestDiffRequestProcessor {
return provider.findExpected(myProject, testProxy.getStacktrace());
}
private @Nullable DiffContent createPsiDiffContent(@NotNull TestDiffProvider provider,
@NotNull PsiElement element,
@NotNull String text) {
private @Nullable DiffContent createPsiDiffContent(@NotNull PsiElement element, @NotNull String text) {
SmartPsiElementPointer<PsiElement> elemPtr = SmartPointerManager.createPointer(element);
return TestDiffContent.Companion.create(myProject, text, elemPtr, provider::createActual);
return TestDiffContent.Companion.create(myProject, text, elemPtr);
}
@Override

View File

@@ -4,7 +4,6 @@ package com.intellij.execution.junit
import org.intellij.lang.annotations.Language
class JavaTestDiffUpdateTest : JvmTestDiffUpdateTest() {
@Suppress("SameParameterValue")
private fun checkAcceptDiff(
@Language("Java") before: String,
@@ -103,6 +102,34 @@ class JavaTestDiffUpdateTest : JvmTestDiffUpdateTest() {
""".trimIndent())
}
fun `test string literal diff with escape`() {
checkAcceptDiff("""
import org.junit.Assert;
import org.junit.Test;
public class MyJUnitTest {
@Test
public void testFoo() {
Assert.assertEquals("expected", "actual\"");
}
}
""".trimIndent(), """
import org.junit.Assert;
import org.junit.Test;
public class MyJUnitTest {
@Test
public void testFoo() {
Assert.assertEquals("actual\"", "actual\"");
}
}
""".trimIndent(), "MyJUnitTest", "testFoo", "expected", "actual\"", """
at org.junit.Assert.assertEquals(Assert.java:117)
at org.junit.Assert.assertEquals(Assert.java:146)
at MyJUnitTest.testFoo(MyJUnitTest.java:7)
""".trimIndent())
}
fun `test parameter reference diff`() {
checkAcceptDiff("""
import org.junit.Assert;

View File

@@ -52,7 +52,7 @@ abstract class JvmTestDiffUpdateTest : JavaCodeInsightFixtureTestCase() {
request.onAssigned(true)
val document = request.contents.firstOrNull().asSafely<DocumentContent>()?.document!!
document.setReadOnly(false)
WriteCommandAction.runWriteCommandAction(myFixture.project, Runnable { document.replaceString(0, 0, actual) })
WriteCommandAction.runWriteCommandAction(myFixture.project, Runnable { document.replaceString(0, document.textLength, actual) })
assertEquals(after, myFixture.file.text)
}
}

View File

@@ -2,7 +2,6 @@
package org.jetbrains.kotlin.idea.testIntegration
import com.intellij.execution.testframework.JvmTestDiffProvider
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.util.asSafely
@@ -16,12 +15,6 @@ import org.jetbrains.uast.UMethod
import org.jetbrains.uast.toUElementOfType
class KotlinTestDiffProvider : JvmTestDiffProvider<KtCallExpression>() {
override fun createActual(project: Project, element: PsiElement, actual: String): PsiElement {
val factory = KtPsiFactory(project)
if (element is KtStringTemplateEntry) return factory.createLiteralStringTemplateEntry(actual)
return factory.createStringTemplate(actual)
}
override fun getParamIndex(param: PsiElement): Int? {
if (param is KtParameter) {
return param.parent.asSafely<KtParameterList>()?.parameters?.indexOf<PsiElement>(param)
@@ -45,8 +38,8 @@ class KotlinTestDiffProvider : JvmTestDiffProvider<KtCallExpression>() {
} else {
call.valueArguments.getOrNull(argIndex)?.getArgumentExpression() ?: return null
}
if (expr is KtStringTemplateExpression && expr.entries.size == 1) return expr.entries.first()
if (expr is KtStringTemplateEntry) return expr
if (expr is KtStringTemplateExpression && expr.entries.size == 1) return expr
if (expr is KtStringTemplateEntry) return expr.parent
if (expr is KtNameReferenceExpression) {
val resolved = expr.reference?.resolve()
if (resolved is KtVariableDeclaration) {

View File

@@ -46,6 +46,36 @@ class KotlinTestDiffUpdateTest : JvmTestDiffUpdateTest() {
)
}
fun `test string literal diff with escape`() {
checkAcceptDiff(
"""
import org.junit.Assert
import org.junit.Test
class MyJUnitTest {
@Test
fun testFoo() {
Assert.assertEquals("expected", "actual\"")
}
}
""".trimIndent(), """
import org.junit.Assert
import org.junit.Test
class MyJUnitTest {
@Test
fun testFoo() {
Assert.assertEquals("actual\"", "actual\"")
}
}
""".trimIndent(), "MyJUnitTest", "testFoo", "expected", "actual\"", """
at org.junit.Assert.assertEquals(Assert.java:117)
at org.junit.Assert.assertEquals(Assert.java:146)
at MyJUnitTest.testFoo(MyJUnitTest.kt:7)
""".trimIndent()
)
}
fun `test parameter reference diff`() {
checkAcceptDiff(
"""