diff --git a/plugins/devkit/devkit-core/resources/inspectionDescriptions/UseIntelliJVirtualThreads.html b/plugins/devkit/devkit-core/resources/inspectionDescriptions/UseIntelliJVirtualThreads.html new file mode 100644 index 000000000000..b4d4bc3aaa8c --- /dev/null +++ b/plugins/devkit/devkit-core/resources/inspectionDescriptions/UseIntelliJVirtualThreads.html @@ -0,0 +1,21 @@ + + +Reports usages of Thread.ofVirtual instead of IntelliJVirtualThreads.ofVirtual. +

+ Thread.ofVirtual is a generic Java API for creation of virtual threads that is not suitable for IntelliJ Platform needs. +

+

+ Quick fix performs replacement with IntelliJVirtualThreads.ofVirtual. +

+

+ Example: +

+

+// bad:
+Thread thread = Thread.ofVirtual().start();
+
+//good
+Thread thread = IntelliJVirtualThreads.ofVirtual().start();
+
+ + \ No newline at end of file diff --git a/plugins/devkit/devkit-core/resources/messages/DevKitBundle.properties b/plugins/devkit/devkit-core/resources/messages/DevKitBundle.properties index da4ced62ffae..3aeae681c044 100644 --- a/plugins/devkit/devkit-core/resources/messages/DevKitBundle.properties +++ b/plugins/devkit/devkit-core/resources/messages/DevKitBundle.properties @@ -784,6 +784,6 @@ compose.hot.reload.hot.reload.agent.has.been.saved=Restart your run configuratio usage.type.module.in.content=In content usage.type.module.in.dependencies=In dependencies -inspection.use.intellij.virtual.threads.display.name=Use IntelliJVirtualThreads.ofVirtual +inspection.use.intellij.virtual.threads.display.name=Use 'IntelliJVirtualThreads.ofVirtual' inspection.use.intellij.virtual.threads.message=Use 'IntelliJVirtualThreads.ofVirtual()' instead of 'Thread.ofVirtual()' inspection.use.intellij.virtual.threads.fix.family.name=Replace with 'IntelliJVirtualThreads.ofVirtual()' diff --git a/plugins/devkit/devkit-core/src/inspections/UseIntelliJVirtualThreadsInspection.kt b/plugins/devkit/devkit-core/src/inspections/UseIntelliJVirtualThreadsInspection.kt index 370bd0f66851..8ce91df64f70 100644 --- a/plugins/devkit/devkit-core/src/inspections/UseIntelliJVirtualThreadsInspection.kt +++ b/plugins/devkit/devkit-core/src/inspections/UseIntelliJVirtualThreadsInspection.kt @@ -1,102 +1,84 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package org.jetbrains.idea.devkit.inspections; +package org.jetbrains.idea.devkit.inspections -import com.intellij.codeInspection.CleanupLocalInspectionTool; -import com.intellij.codeInspection.LocalQuickFix; -import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.codeInspection.ProblemsHolder; -import com.intellij.codeInspection.util.IntentionFamilyName; -import com.intellij.lang.java.JavaLanguage; -import com.intellij.openapi.project.Project; -import com.intellij.psi.*; -import com.intellij.psi.codeStyle.JavaCodeStyleManager; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.uast.UastHintedVisitorAdapter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.devkit.DevKitBundle; -import org.jetbrains.uast.UCallExpression; -import org.jetbrains.uast.UElement; -import org.jetbrains.uast.UastContextKt; -import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor; +import com.intellij.codeInspection.LocalQuickFix +import com.intellij.codeInspection.ProblemDescriptor +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.codeInspection.util.IntentionFamilyName +import com.intellij.lang.java.JavaLanguage +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElementVisitor +import com.intellij.uast.UastHintedVisitorAdapter +import org.jetbrains.idea.devkit.DevKitBundle +import org.jetbrains.uast.* +import org.jetbrains.uast.generate.getUastElementFactory +import org.jetbrains.uast.generate.replace +import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor /** * Suggest using IntelliJVirtualThreads.ofVirtual instead of Thread.ofVirtual */ -public final class UseIntelliJVirtualThreadsInspection extends DevKitUastInspectionBase implements CleanupLocalInspectionTool { - - private static final String THREAD_CLASS = "java.lang.Thread"; - private static final String INTELLIJ_VIRTUAL_THREADS_FQN = "com.intellij.virtualThreads.IntelliJVirtualThreads"; - - @SuppressWarnings("unchecked") - private static final Class[] HINTS = new Class[]{UCallExpression.class}; - - @Override - protected boolean isAllowed(@NotNull ProblemsHolder holder) { - return DevKitInspectionUtil.isAllowed(holder.getFile()) && - DevKitInspectionUtil.isClassAvailable(holder, INTELLIJ_VIRTUAL_THREADS_FQN); +class UseIntelliJVirtualThreadsInspection : DevKitUastInspectionBase() { + override fun isAllowed(holder: ProblemsHolder): Boolean { + return DevKitInspectionUtil.isAllowed(holder.file) && + DevKitInspectionUtil.isClassAvailable(holder, INTELLIJ_VIRTUAL_THREADS_FQN) } - @Override - public @NotNull PsiElementVisitor buildInternalVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) { - return UastHintedVisitorAdapter.create(holder.getFile().getLanguage(), new AbstractUastNonRecursiveVisitor() { - @Override - public boolean visitCallExpression(@NotNull UCallExpression node) { - if (!"ofVirtual".equals(node.getMethodName())) return super.visitCallExpression(node); - PsiMethod method = node.resolve(); - boolean isThreadOfVirtual = false; - if (method != null) { - if (!method.hasModifierProperty(PsiModifier.STATIC)) return super.visitCallExpression(node); - PsiClass containingClass = method.getContainingClass(); - if (containingClass == null) return super.visitCallExpression(node); - String qName = containingClass.getQualifiedName(); - isThreadOfVirtual = THREAD_CLASS.equals(qName) || "Thread".equals(containingClass.getName()); + public override fun buildInternalVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { + return UastHintedVisitorAdapter.create(holder.file.getLanguage(), object : AbstractUastNonRecursiveVisitor() { + override fun visitCallExpression(node: UCallExpression): Boolean { + val method = node.takeIf { + it.methodName == "ofVirtual" + }?.resolve() ?: return super.visitCallExpression(node) + val clazz = method.containingClass ?: return super.visitCallExpression(node) + if (clazz.qualifiedName != THREAD_FQN) { + return super.visitCallExpression(node) } - else { - // Fallback for environments where JDK doesn't provide Thread.ofVirtual (e.g., tests on older JDK): - PsiElement sp = node.getSourcePsi(); - if (sp instanceof PsiMethodCallExpression) { - PsiExpression qualifier = ((PsiMethodCallExpression)sp).getMethodExpression().getQualifierExpression(); - String qualifierText = qualifier == null ? null : qualifier.getText(); - isThreadOfVirtual = THREAD_CLASS.equals(qualifierText) || "Thread".equals(qualifierText); - } - } - if (!isThreadOfVirtual) return super.visitCallExpression(node); - PsiElement psi = node.getSourcePsi(); + val psi = node.sourcePsi if (psi != null) { - LocalQuickFix[] fixes = psi.getLanguage().is(JavaLanguage.INSTANCE) - ? new LocalQuickFix[]{new ReplaceWithIntelliJVirtualThreadsFix()} - : LocalQuickFix.EMPTY_ARRAY; - holder.registerProblem(psi, DevKitBundle.message("inspection.use.intellij.virtual.threads.message"), fixes); + val fixes: Array = if (psi.getLanguage().`is`(JavaLanguage.INSTANCE) || psi.language.id == "kotlin") { + arrayOf(ReplaceWithIntelliJVirtualThreadsFix()) + } + else { + LocalQuickFix.EMPTY_ARRAY + } + holder.registerProblem(psi, DevKitBundle.message("inspection.use.intellij.virtual.threads.message"), *fixes) } - return super.visitCallExpression(node); + return super.visitCallExpression(node) } - }, HINTS); + }, HINTS) } - private static class ReplaceWithIntelliJVirtualThreadsFix implements LocalQuickFix { - - @Override - public @IntentionFamilyName @NotNull String getFamilyName() { - return DevKitBundle.message("inspection.use.intellij.virtual.threads.fix.family.name"); + private class ReplaceWithIntelliJVirtualThreadsFix : LocalQuickFix { + @IntentionFamilyName + override fun getFamilyName(): @IntentionFamilyName String { + return DevKitBundle.message("inspection.use.intellij.virtual.threads.fix.family.name") } - @Override - public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - PsiElement element = descriptor.getPsiElement(); - PsiMethodCallExpression call = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class, false); - if (call == null && element instanceof PsiMethodCallExpression) { - call = (PsiMethodCallExpression) element; - } - if (call == null) return; - - PsiReferenceExpression methodExpression = call.getMethodExpression(); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); - PsiExpression newMethodRef = factory.createExpressionFromText( - INTELLIJ_VIRTUAL_THREADS_FQN + ".ofVirtual", call - ); - PsiElement replaced = methodExpression.replace(newMethodRef); - JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced); + override fun applyFix(project: Project, descriptor: ProblemDescriptor) { + val element = descriptor.psiElement + val uCall = element.toUElement() ?: return + val factory = uCall.getUastElementFactory(project) ?: return + val newReceiver = factory.createQualifiedReference(INTELLIJ_VIRTUAL_THREADS_FQN, uCall.sourcePsi) ?: return + val newCall = factory.createCallExpression( + receiver = newReceiver, + methodName = "ofVirtual", + parameters = emptyList(), + expectedReturnType = null, + kind = UastCallKind.METHOD_CALL, + context = uCall.sourcePsi + ) ?: return + val parent = uCall.uastParent + // we check for parent in case of `Thread.ofVirtual()` calls in Kotlin + val replacementUastElement = parent as? UQualifiedReferenceExpression ?: uCall + replacementUastElement.replace(newCall) } } } + +private const val THREAD_FQN = "java.lang.Thread" +private const val INTELLIJ_VIRTUAL_THREADS_FQN = "com.intellij.concurrency.virtualThreads.IntelliJVirtualThreads" + +private val HINTS: Array> = arrayOf(UCallExpression::class.java) + diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads.java b/plugins/devkit/devkit-java-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads.java index a572de3427f4..391da2c7e0ca 100644 --- a/plugins/devkit/devkit-java-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads.java +++ b/plugins/devkit/devkit-java-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads.java @@ -1,11 +1,7 @@ -import com.intellij.virtualThreads.IntelliJVirtualThreads; import java.lang.Thread; class UseIntelliJVirtualThreads { - java.lang.Thread.Builder m() { - return java.lang.Thread.ofVirtual(); - } - void ok() { - IntelliJVirtualThreads.ofVirtual(); + public static void main(String[] args) { + Thread.ofVirtual(); } } diff --git a/plugins/devkit/devkit-java-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads_after.java b/plugins/devkit/devkit-java-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads_after.java index 88e2baff4835..f58409c8aa71 100644 --- a/plugins/devkit/devkit-java-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads_after.java +++ b/plugins/devkit/devkit-java-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads_after.java @@ -1,11 +1,9 @@ -import com.intellij.virtualThreads.IntelliJVirtualThreads; +import com.intellij.concurrency.virtualThreads.IntelliJVirtualThreads; + import java.lang.Thread; class UseIntelliJVirtualThreads { - java.lang.Thread.Builder m() { - return IntelliJVirtualThreads.ofVirtual(); - } - void ok() { - IntelliJVirtualThreads.ofVirtual(); + public static void main(String[] args) { + IntelliJVirtualThreads.ofVirtual(); } } diff --git a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/DevkitInspectionsRegistrationCheckTest.java b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/DevkitInspectionsRegistrationCheckTest.java index 23a3d491b341..c4f8152152d5 100644 --- a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/DevkitInspectionsRegistrationCheckTest.java +++ b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/DevkitInspectionsRegistrationCheckTest.java @@ -12,7 +12,7 @@ import java.util.stream.Stream; public class DevkitInspectionsRegistrationCheckTest extends BasePlatformTestCase { - private static final int EXPECTED_INSPECTIONS_NUMBER = 83; + private static final int EXPECTED_INSPECTIONS_NUMBER = 84; /** * Inspections that are finished and intentionally disabled. diff --git a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/UseIntelliJVirtualThreadsInspectionFixTest.java b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/UseIntelliJVirtualThreadsInspectionFixTest.java deleted file mode 100644 index c080b5cbe2a8..000000000000 --- a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/UseIntelliJVirtualThreadsInspectionFixTest.java +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package org.jetbrains.idea.devkit.inspections; - -import com.intellij.testFramework.TestDataPath; -import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor; -import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase; -import com.intellij.testFramework.IdeaTestUtil; -import com.intellij.util.lang.JavaVersion; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.devkit.DevkitJavaTestsUtil; - -@TestDataPath("$CONTENT_ROOT/testData/inspections/useIntelliJVirtualThreads") -public class UseIntelliJVirtualThreadsInspectionFixTest extends org.jetbrains.idea.devkit.inspections.quickfix.LightDevKitInspectionFixTestBase { - - @Override - protected String getBasePath() { - return DevkitJavaTestsUtil.TESTDATA_PATH + "inspections/useIntelliJVirtualThreads"; - } - - @Override - protected @NotNull String getFileExtension() { - return "java"; - } - - @Override - protected com.intellij.testFramework.LightProjectDescriptor getProjectDescriptor() { - return new DefaultLightProjectDescriptor(() -> IdeaTestUtil.getMockJdk(JavaVersion.compose(21))); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - myFixture.enableInspections(new UseIntelliJVirtualThreadsInspection()); - - // Provide IntelliJVirtualThreads class used by the inspection - myFixture.addClass( - "package com.intellij.virtualThreads;" + - "public final class IntelliJVirtualThreads {" + - " private IntelliJVirtualThreads() {}" + - " public static java.lang.Thread.Builder ofVirtual() { return null; }" + - "}" - ); - } - - public void testUseIntelliJVirtualThreads() { - doTest(org.jetbrains.idea.devkit.DevKitBundle.message("inspection.use.intellij.virtual.threads.fix.family.name")); - } -} diff --git a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/UseIntelliJVirtualThreadsInspectionTest.kt b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/UseIntelliJVirtualThreadsInspectionTest.kt index 61547c7ac12c..0614544ff659 100644 --- a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/UseIntelliJVirtualThreadsInspectionTest.kt +++ b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/inspections/UseIntelliJVirtualThreadsInspectionTest.kt @@ -1,41 +1,25 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package org.jetbrains.idea.devkit.inspections; +package org.jetbrains.idea.devkit.inspections -import com.intellij.testFramework.TestDataPath; -import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase; -import org.jetbrains.idea.devkit.DevkitJavaTestsUtil; +import com.intellij.testFramework.IdeaTestUtil +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.TestDataPath +import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor +import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase +import org.jetbrains.idea.devkit.DevkitJavaTestsUtil +import org.jetbrains.idea.devkit.inspections.quickfix.LightDevKitInspectionFixTestBase +import org.jetbrains.idea.devkit.inspections.quickfix.UseIntelliJVirtualThreadsInspectionTestBase +import java.util.function.Supplier -@TestDataPath("$CONTENT_ROOT/testData/inspections/useIntelliJVirtualThreads") -public class UseIntelliJVirtualThreadsInspectionTest extends LightJavaCodeInsightFixtureTestCase { - - @Override - protected String getBasePath() { - return DevkitJavaTestsUtil.TESTDATA_PATH + "inspections/useIntelliJVirtualThreads"; - } - - @Override - protected com.intellij.testFramework.LightProjectDescriptor getProjectDescriptor() { - return new com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor(() -> - com.intellij.testFramework.IdeaTestUtil.getMockJdk(com.intellij.util.lang.JavaVersion.compose(21)) - ); +@TestDataPath($$"$CONTENT_ROOT/testData/inspections/useIntelliJVirtualThreads") +class UseIntelliJVirtualThreadsInspectionTest : UseIntelliJVirtualThreadsInspectionTestBase() { + override fun getBasePath(): String { + return DevkitJavaTestsUtil.TESTDATA_PATH + "inspections/useIntelliJVirtualThreads" } - @Override - protected void setUp() throws Exception { - super.setUp(); - myFixture.enableInspections(new UseIntelliJVirtualThreadsInspection()); - - // Provide IntelliJVirtualThreads class used by the inspection - myFixture.addClass( - "package com.intellij.virtualThreads;" + - "public final class IntelliJVirtualThreads {" + - " private IntelliJVirtualThreads() {}" + - " public static java.lang.Thread.Builder ofVirtual() { return null; }" + - "}" - ); + fun testUseIntelliJVirtualThreads() { + doTest("Replace with 'IntelliJVirtualThreads.ofVirtual()'") } - public void testUseIntelliJVirtualThreads() { - myFixture.testHighlighting(getTestName(false) + ".java"); - } + override fun getFileExtension(): String = "java" } diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads.kt new file mode 100644 index 000000000000..01445bf4483b --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads.kt @@ -0,0 +1,7 @@ +import java.lang.Thread + +class UseIntelliJVirtualThreadsKotlin { + fun foo() { + Thread.ofVirtual() + } +} diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreadsKotlin.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreadsKotlin.kt deleted file mode 100644 index c8a273b3bc5b..000000000000 --- a/plugins/devkit/devkit-kotlin-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreadsKotlin.kt +++ /dev/null @@ -1,10 +0,0 @@ -import com.intellij.virtualThreads.IntelliJVirtualThreads - -class UseIntelliJVirtualThreadsKotlin { - fun m(): Thread.Builder { - return java.lang.Thread.ofVirtual() - } - fun ok() { - IntelliJVirtualThreads.ofVirtual() - } -} diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads_after.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads_after.kt new file mode 100644 index 000000000000..1c7ad05c70ed --- /dev/null +++ b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads_after.kt @@ -0,0 +1,8 @@ +import com.intellij.concurrency.virtualThreads.IntelliJVirtualThreads +import java.lang.Thread + +class UseIntelliJVirtualThreadsKotlin { + fun foo() { + IntelliJVirtualThreads.ofVirtual() + } +} diff --git a/plugins/devkit/devkit-kotlin-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads_kotlin.kt b/plugins/devkit/devkit-kotlin-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads_kotlin.kt deleted file mode 100644 index c8a273b3bc5b..000000000000 --- a/plugins/devkit/devkit-kotlin-tests/testData/inspections/useIntelliJVirtualThreads/UseIntelliJVirtualThreads_kotlin.kt +++ /dev/null @@ -1,10 +0,0 @@ -import com.intellij.virtualThreads.IntelliJVirtualThreads - -class UseIntelliJVirtualThreadsKotlin { - fun m(): Thread.Builder { - return java.lang.Thread.ofVirtual() - } - fun ok() { - IntelliJVirtualThreads.ofVirtual() - } -} diff --git a/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/inspections/KtUseIntelliJVirtualThreadsInspectionTest.kt b/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/inspections/KtUseIntelliJVirtualThreadsInspectionTest.kt index 58efa7e48bc3..2afa08d30ea5 100644 --- a/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/inspections/KtUseIntelliJVirtualThreadsInspectionTest.kt +++ b/plugins/devkit/devkit-kotlin-tests/testSrc/org/jetbrains/idea/devkit/kotlin/inspections/KtUseIntelliJVirtualThreadsInspectionTest.kt @@ -1,50 +1,19 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package org.jetbrains.idea.devkit.kotlin.inspections; +package org.jetbrains.idea.devkit.kotlin.inspections -import com.intellij.testFramework.TestDataPath; -import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor; -import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase; -import com.intellij.testFramework.IdeaTestUtil; -import com.intellij.util.lang.JavaVersion; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.devkit.kotlin.DevkitKtTestsUtil; -import org.jetbrains.idea.devkit.inspections.UseIntelliJVirtualThreadsInspection; +import com.intellij.testFramework.TestDataPath +import org.jetbrains.idea.devkit.inspections.quickfix.UseIntelliJVirtualThreadsInspectionTestBase +import org.jetbrains.idea.devkit.kotlin.DevkitKtTestsUtil -@TestDataPath("$CONTENT_ROOT/testData/inspections/useIntelliJVirtualThreads") -public class KtUseIntelliJVirtualThreadsInspectionTest extends LightJavaCodeInsightFixtureTestCase { - - @Override - protected String getBasePath() { - return DevkitKtTestsUtil.TESTDATA_PATH + "inspections/useIntelliJVirtualThreads"; +@TestDataPath($$"$CONTENT_ROOT/testData/inspections/useIntelliJVirtualThreads") +class KtUseIntelliJVirtualThreadsInspectionTest : UseIntelliJVirtualThreadsInspectionTestBase() { + override fun getBasePath(): String { + return DevkitKtTestsUtil.TESTDATA_PATH + "inspections/useIntelliJVirtualThreads" } - @Override - protected com.intellij.testFramework.LightProjectDescriptor getProjectDescriptor() { - return new DefaultLightProjectDescriptor(() -> IdeaTestUtil.getMockJdk(JavaVersion.compose(21))); + fun testUseIntelliJVirtualThreads() { + doTest("Replace with 'IntelliJVirtualThreads.ofVirtual()'") } - @Override - protected void setUp() throws Exception { - super.setUp(); - myFixture.enableInspections(new UseIntelliJVirtualThreadsInspection()); - - // Provide IntelliJVirtualThreads class used by the inspection - myFixture.addClass( - "package com.intellij.virtualThreads;" + - "public final class IntelliJVirtualThreads {" + - " private IntelliJVirtualThreads() {}" + - " public static java.lang.Thread.Builder ofVirtual() { return null; }" + - "}" - ); - } - - @NotNull - @Override - protected String getTestName(boolean lowercaseFirstLetter) { - return super.getTestName(lowercaseFirstLetter).replace("_", ""); - } - - public void testUseIntelliJVirtualThreadsKotlin() { - myFixture.testHighlighting(getTestName(false) + ".kt"); - } + override fun getFileExtension(): String = "kt" } diff --git a/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/inspections/quickfix/UseIntelliJVirtualThreadsInspectionTestBase.kt b/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/inspections/quickfix/UseIntelliJVirtualThreadsInspectionTestBase.kt new file mode 100644 index 000000000000..67889dd1b930 --- /dev/null +++ b/plugins/devkit/devkit-tests/testSrc/org/jetbrains/idea/devkit/inspections/quickfix/UseIntelliJVirtualThreadsInspectionTestBase.kt @@ -0,0 +1,30 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.idea.devkit.inspections.quickfix + +import com.intellij.testFramework.IdeaTestUtil +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor +import org.jetbrains.idea.devkit.inspections.UseIntelliJVirtualThreadsInspection +import java.util.function.Supplier + +abstract class UseIntelliJVirtualThreadsInspectionTestBase : LightDevKitInspectionFixTestBase() { + + override fun getProjectDescriptor(): LightProjectDescriptor { + return DefaultLightProjectDescriptor(Supplier { IdeaTestUtil.getMockJdk21() }) + } + + @Throws(Exception::class) + override fun setUp() { + super.setUp() + myFixture.enableInspections(UseIntelliJVirtualThreadsInspection()) + myFixture.addClass( + """package com.intellij.concurrency.virtualThreads; + |public final class IntelliJVirtualThreads { + | private IntelliJVirtualThreads() {} + | public static java.lang.Thread.Builder ofVirtual() { + | return null; + | } + |}""".trimMargin() + ) + } +} \ No newline at end of file