diff --git a/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml b/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml
index 43a137e106fa..afc6a940cbf9 100644
--- a/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml
+++ b/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml
@@ -13,8 +13,6 @@
-
-
messages.DevKitBundle
diff --git a/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsAnalyzer.kt b/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsAnalyzer.kt
deleted file mode 100644
index c875d59f345b..000000000000
--- a/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsAnalyzer.kt
+++ /dev/null
@@ -1,129 +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.threadingModelHelper
-
-import com.intellij.psi.*
-import com.intellij.psi.search.searches.OverridingMethodsSearch
-import com.intellij.psi.search.searches.ClassInheritorsSearch
-
-
-class LockReqsAnalyzer(private val detector: LockReqsDetector = LockReqsDetector()) {
-
- private data class TraversalContext(
- val config: AnalysisConfig,
- val currentPath: MutableList = mutableListOf(),
- val visited: MutableSet = mutableSetOf(),
- val paths: MutableSet = mutableSetOf(),
- val messageBusTopics: MutableSet = mutableSetOf(),
- val swingComponents: MutableSet = mutableSetOf(),
- )
-
- fun analyzeMethod(method: PsiMethod, config: AnalysisConfig = AnalysisConfig.forProject(method.project)): AnalysisResult {
- val context = TraversalContext(config)
- traverseMethod(method, context)
- return AnalysisResult(method, context.paths, context.messageBusTopics, context.swingComponents)
- }
-
- private fun traverseMethod(method: PsiMethod, context: TraversalContext, isPolymorphic: Boolean = false) {
- if (context.currentPath.size >= context.config.maxDepth) return
- val signature = MethodSignature.fromMethod(method)
- if (signature in context.visited) return
- context.visited.add(signature)
- context.currentPath.add(MethodCall(method, isPolymorphic))
-
- val annotationRequirements = detector.findAnnotationRequirements(method)
- annotationRequirements.forEach { context.paths.add(ExecutionPath(context.currentPath.toList(), it)) }
- processMethodBody(method, context)
- context.currentPath.removeLast()
- }
-
-
- private fun processMethodBody(method: PsiMethod, context: TraversalContext) {
- val body = method.body ?: return
- val localRequirements = mutableListOf()
-
- body.accept(object : JavaRecursiveElementVisitor() {
- override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
- super.visitMethodCallExpression(expression)
-
- val resolvedMethod = expression.resolveMethod() ?: return
- localRequirements += detector.findBodyRequirements(resolvedMethod)
- if (localRequirements.any { it.requirementReason == RequirementReason.SWING_COMPONENT }) {
- context.swingComponents.add(MethodSignature.fromMethod(resolvedMethod))
- }
- handleMethodCall(resolvedMethod, expression, context)
- }
-
- override fun visitMethodReferenceExpression(expression: PsiMethodReferenceExpression) {
- super.visitMethodReferenceExpression(expression)
- (expression.resolve() as? PsiMethod)?.let { resolvedMethod ->
- localRequirements += detector.findBodyRequirements(resolvedMethod)
- if (!detector.isAsyncBoundary(resolvedMethod)) traverseMethod(resolvedMethod, context)
- }
- }
-
- override fun visitNewExpression(expression: PsiNewExpression) {
- super.visitNewExpression(expression)
- expression.resolveMethod()?.let { resolvedMethod ->
- if (!detector.isAsyncBoundary(resolvedMethod)) traverseMethod(resolvedMethod, context)
- }
- }
- })
-
- localRequirements.forEach { requirement ->
- val path = ExecutionPath(context.currentPath.toList(), requirement,
- context.currentPath.any { it.isPolymorphic || it.isMessageBusCall })
- context.paths.add(path)
- }
- }
-
- private fun handleMethodCall(method: PsiMethod, expression: PsiMethodCallExpression, context: TraversalContext) {
- when {
- context.config.includeMessageBus && detector.isMessageBusCall(expression) -> handleMessageBusCall(method, expression, context)
- context.config.includePolymorphic && detector.isPolymorphicCall(method) -> handlePolymorphicCall(method, context)
- else -> traverseMethod(method, context)
- }
- }
-
- private fun handleMessageBusCall(method: PsiMethod, expression: PsiMethodCallExpression, context: TraversalContext) {
- detector.extractMessageBusTopic(expression)?.let { context.messageBusTopics.add(it) }
- if (method.name != "syncPublisher") return
-
- val topicType = method.returnType as? PsiClassType ?: return
- val topicInterface = topicType.resolve() ?: return
- if (!topicInterface.isInterface) return
-
- findTopicListeners(topicInterface, context.config).forEach { listener ->
- listener.methods.forEach { method -> traverseMethod(method, context) }
- }
- }
-
-
- private fun handlePolymorphicCall(method: PsiMethod, context: TraversalContext) {
- val implementations = findImplementations(method, context.config)
-
- if (implementations.size > context.config.maxImplementations) {
- val requirement = LockRequirement(method, LockType.READ, RequirementReason.IMPLICIT)
- context.currentPath.add(MethodCall(method, isPolymorphic = true))
- context.paths.add(ExecutionPath(context.currentPath.toList(), requirement, true))
- return
- }
- implementations.forEach { traverseMethod(it, context) }
- }
-
- private fun findImplementations(method: PsiMethod, config: AnalysisConfig): List {
- val implementations = mutableListOf()
- if (method.body != null) implementations.add(method)
-
- if (method.hasModifierProperty(PsiModifier.ABSTRACT) || method.containingClass?.isInterface == true) {
- val query = OverridingMethodsSearch.search(method, config.scope, true)
- implementations.addAll(query.findAll().take(config.maxImplementations))
- }
- return implementations
- }
-
-
- private fun findTopicListeners(topicInterface: PsiClass, config: AnalysisConfig): List {
- val query = ClassInheritorsSearch.search(topicInterface, config.scope, true)
- return query.findAll().take(config.maxImplementations).toList()
- }
-}
\ No newline at end of file
diff --git a/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsAnalyzerDFS.kt b/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsAnalyzerDFS.kt
new file mode 100644
index 000000000000..ef5384a1b8ac
--- /dev/null
+++ b/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsAnalyzerDFS.kt
@@ -0,0 +1,114 @@
+// 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.threadingModelHelper
+
+import com.intellij.psi.PsiMethod
+import com.intellij.psi.JavaRecursiveElementVisitor
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiClassType
+import com.intellij.psi.PsiMethodCallExpression
+import com.intellij.psi.PsiMethodReferenceExpression
+import com.intellij.psi.PsiModifier
+import com.intellij.psi.PsiNewExpression
+import com.intellij.psi.search.searches.OverridingMethodsSearch
+import com.intellij.util.Processor
+
+
+class LockReqsAnalyzerDFS(private val detector: LockReqsDetector = LockReqsDetector()) {
+
+ private data class TraversalContext(
+ val config: AnalysisConfig,
+ val currentPath: MutableList = mutableListOf(),
+ val visited: MutableSet = mutableSetOf(),
+ val paths: MutableSet = mutableSetOf(),
+ val messageBusTopics: MutableSet = mutableSetOf(),
+ val swingComponents: MutableSet = mutableSetOf(),
+ )
+
+ fun analyzeMethod(method: PsiMethod, config: AnalysisConfig = AnalysisConfig.forProject(method.project)): AnalysisResult {
+ val context = TraversalContext(config)
+ traverseMethod(method, context)
+ return AnalysisResult(method, context.paths, context.messageBusTopics, context.swingComponents)
+ }
+
+ private fun traverseMethod(method: PsiMethod, context: TraversalContext) {
+ println("Traversing ${method.containingClass?.qualifiedName}.${method.name}")
+ val signature = MethodSignature.fromMethod(method)
+ if (context.currentPath.size >= context.config.maxDepth || signature in context.visited) return
+ context.visited.add(signature)
+ context.currentPath.add(MethodCall(method))
+
+ val annotationRequirement = detector.findAnnotationRequirements(method)
+ annotationRequirement.forEach { context.paths.add(ExecutionPath(context.currentPath.toList(), it)) }
+ getMethodCallees(method).forEach { processCallee(it, context) }
+
+ context.currentPath.removeLast()
+ }
+
+ private fun getMethodCallees(method: PsiMethod): List {
+ val callees = mutableListOf()
+
+ method.body?.accept(object : JavaRecursiveElementVisitor() {
+ override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
+ super.visitMethodCallExpression(expression)
+ expression.resolveMethod()?.let { callees.add(it) }
+ }
+
+ override fun visitMethodReferenceExpression(expression: PsiMethodReferenceExpression) {
+ super.visitMethodReferenceExpression(expression)
+ (expression.resolve() as? PsiMethod)?.let { callees.add(it) }
+ }
+
+ override fun visitNewExpression(expression: PsiNewExpression) {
+ super.visitNewExpression(expression)
+ expression.resolveMethod()?.let { callees.add(it) }
+ }
+ })
+
+ return callees
+ }
+
+ private fun processCallee(callee: PsiMethod, context: TraversalContext) {
+ detector.findBodyRequirements(callee).forEach { requirement ->
+ context.paths.add(ExecutionPath(context.currentPath.toList(), requirement))
+ }
+ if (!detector.isAsyncDispatch(callee)) {
+ when {
+ detector.isMessageBusCall(callee) -> handleMessageBusCall(callee, context)
+ detector.isPolymorphicCall(callee) -> handlePolymorphic(callee, context)
+ else -> traverseMethod(callee, context)
+ }
+ }
+ }
+
+ private fun handlePolymorphic(method: PsiMethod, context: TraversalContext) {
+ val implementations = findImplementations(method, context.config)
+ implementations.forEach { traverseMethod(it, context) }
+ }
+
+ private fun findImplementations(method: PsiMethod, config: AnalysisConfig): List {
+ val implementations = mutableListOf()
+ if (method.body != null) {
+ implementations.add(method)
+ }
+ if (method.hasModifierProperty(PsiModifier.ABSTRACT) || method.containingClass?.isInterface == true) {
+ val query = OverridingMethodsSearch.search(method, config.scope, true)
+ query.forEach(Processor {
+ if (implementations.size >= config.maxImplementations) return@Processor false
+ implementations.add(it)
+ })
+ }
+ return implementations
+ }
+
+ private fun handleMessageBusCall(method: PsiMethod, context: TraversalContext) {
+ detector.extractMessageBusTopic(method)?.let { context.messageBusTopics.add(it) }
+
+ val topicType = method.returnType as? PsiClassType ?: return
+ val topicInterface = topicType.resolve() ?: return
+ if (!topicInterface.isInterface) return
+
+ detector.findTopicListeners(topicInterface, context.config).forEach { listener ->
+ listener.methods.forEach { method -> traverseMethod(method, context) }
+ }
+ }
+}
diff --git a/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsDetector.kt b/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsDetector.kt
index d450049e0607..816b68461000 100644
--- a/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsDetector.kt
+++ b/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsDetector.kt
@@ -1,12 +1,14 @@
// 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.threadingModelHelper
+import com.intellij.psi.PsiClass
import com.intellij.psi.PsiClassType
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiMethodCallExpression
-import com.intellij.psi.PsiElement
import com.intellij.psi.PsiModifier
+import com.intellij.psi.search.searches.ClassInheritorsSearch
import com.intellij.psi.util.InheritanceUtil
+import com.intellij.util.Processor
class LockReqsDetector(private val patterns: LockReqsPatterns = DefaultLockReqsPatterns()) {
@@ -27,15 +29,12 @@ class LockReqsDetector(private val patterns: LockReqsPatterns = DefaultLockReqsP
patterns.assertionMethods[className]?.get(methodName)?.let { lockType ->
requirements.add(LockRequirement(method, lockType, RequirementReason.ASSERTION))
}
- if (isSwingMethod(method)) requirements.add(LockRequirement(method, LockType.EDT, RequirementReason.SWING_COMPONENT))
+ if (isSwingMethod(method)) {
+ requirements.add(LockRequirement(method, LockType.EDT, RequirementReason.SWING_COMPONENT))
+ }
return requirements
}
- private fun isSwingComponent(className: String): Boolean {
- return patterns.edtRequiredClasses.contains(className) ||
- patterns.edtRequiredPackages.any { className.startsWith("$it.") }
- }
-
private fun isSwingMethod(method: PsiMethod): Boolean {
val containingClass = method.containingClass ?: return false
val className = containingClass.qualifiedName ?: return false
@@ -45,24 +44,13 @@ class LockReqsDetector(private val patterns: LockReqsPatterns = DefaultLockReqsP
}
}
- fun isAsyncBoundary(method: PsiMethod): Boolean {
- return method.name in patterns.asyncMethods || method.containingClass?.qualifiedName in patterns.asyncClasses
+ private fun isSwingComponent(className: String): Boolean {
+ return patterns.edtRequiredClasses.contains(className) ||
+ patterns.edtRequiredPackages.any { className.startsWith("$it.") }
}
- fun isMessageBusCall(expression: PsiMethodCallExpression): Boolean {
- val method = expression.resolveMethod() ?: return false
- val containingClass = method.containingClass?.qualifiedName ?: return false
- return patterns.messageBusClasses.contains(containingClass) && method.name in patterns.messageBusMethods
- }
-
- fun extractMessageBusTopic(expression: PsiMethodCallExpression): String? {
- val method = expression.resolveMethod() ?: return null
- if (method.name == "syncPublisher") {
- val returnType = method.returnType as? PsiClassType ?: return null
- val resolvedTopicInterface = returnType.resolve() ?: return null
- return resolvedTopicInterface.qualifiedName
- }
- return null
+ fun isAsyncDispatch(method: PsiMethod): Boolean {
+ return method.name in patterns.asyncMethods && method.containingClass?.qualifiedName in patterns.asyncClasses
}
fun isPolymorphicCall(method: PsiMethod): Boolean {
@@ -72,4 +60,28 @@ class LockReqsDetector(private val patterns: LockReqsPatterns = DefaultLockReqsP
val containingClass = method.containingClass ?: return false
return !containingClass.hasModifierProperty(PsiModifier.FINAL)
}
+
+ fun isMessageBusCall(method: PsiMethod): Boolean {
+ val containingClass = method.containingClass?.qualifiedName ?: return false
+ return patterns.messageBusClasses.contains(containingClass) && method.name in patterns.messageBusSyncMethods
+ }
+
+ fun extractMessageBusTopic(method: PsiMethod): PsiClass? {
+ if (method.name in patterns.messageBusSyncMethods) {
+ val returnType = method.returnType as? PsiClassType ?: return null
+ val resolvedTopicInterface = returnType.resolve() ?: return null
+ return resolvedTopicInterface
+ }
+ return null
+ }
+
+ fun findTopicListeners(topicInterface: PsiClass, config: AnalysisConfig): List {
+ val listeners = mutableListOf()
+ val query = ClassInheritorsSearch.search(topicInterface, config.scope, true)
+ query.forEach(Processor {
+ if (listeners.size > config.maxImplementations) return@Processor false
+ listeners.add(it)
+ })
+ return listeners
+ }
}
\ No newline at end of file
diff --git a/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsModel.kt b/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsModel.kt
index 50f1a7e8ada5..750da6a3a774 100644
--- a/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsModel.kt
+++ b/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsModel.kt
@@ -2,6 +2,7 @@
package org.jetbrains.idea.devkit.threadingModelHelper
import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.search.GlobalSearchScope
@@ -47,7 +48,7 @@ data class ExecutionPath(
data class AnalysisResult(
val method: PsiMethod,
val paths: Set,
- val messageBusTopics: Set = emptySet(),
+ val messageBusTopics: Set = emptySet(),
val swingComponents: Set = emptySet(),
)
diff --git a/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsPatterns.kt b/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsPatterns.kt
index c5a2d418d237..a0eb6e3f76e7 100644
--- a/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsPatterns.kt
+++ b/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsPatterns.kt
@@ -9,7 +9,7 @@ interface LockReqsPatterns {
val asyncClasses: Set
val asyncMethods: Set
val messageBusClasses: Set
- val messageBusMethods: Set
+ val messageBusSyncMethods: Set
val safeSwingMethods: Set
}
@@ -66,12 +66,11 @@ class DefaultLockReqsPatterns : LockReqsPatterns {
)
override val messageBusClasses: Set = setOf(
- "com.intellij.util.messages.MessageBus",
- "com.intellij.util.messages.MessageBusConnection"
+ "com.intellij.util.messages.MessageBus"
)
- override val messageBusMethods: Set = setOf(
- "syncPublisher", "connect", "simpleConnect"
+ override val messageBusSyncMethods: Set = setOf(
+ "syncPublisher"
)
override val safeSwingMethods: Set = setOf()
diff --git a/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsService.kt b/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsService.kt
index 87609d7f1610..978dd177f737 100644
--- a/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsService.kt
+++ b/plugins/devkit/devkit-core/src/threadingModelHelper/LockReqsService.kt
@@ -20,7 +20,7 @@ class LockReqsService(private val project: Project) {
var onResultsUpdated: ((AnalysisResult?) -> Unit)? = null
fun updateResults(method: PsiMethod) {
- val analyzer = LockReqsAnalyzer()
+ val analyzer = LockReqsAnalyzerDFS()
_currentResult = analyzer.analyzeMethod(method)
onResultsUpdated?.invoke(_currentResult)
diff --git a/plugins/devkit/devkit-java-tests/testData/threadingModelHelper/DifferentClassesMethods.java b/plugins/devkit/devkit-java-tests/testData/threadingModelHelper/DifferentClassesMethods.java
index 0c242c35ab2a..7489e090ba8b 100644
--- a/plugins/devkit/devkit-java-tests/testData/threadingModelHelper/DifferentClassesMethods.java
+++ b/plugins/devkit/devkit-java-tests/testData/threadingModelHelper/DifferentClassesMethods.java
@@ -11,14 +11,13 @@ class DifferentClassesMethods {
void helperMethod() {
Service service = new Service();
service.serviceMethod();
+ ThreadingAssertions.assertWriteAccess();
}
}
class Service {
@RequiresEdt
- void serviceMethod() {
- ThreadingAssertions.assertWriteAccess();
- }
+ void serviceMethod() {}
}
}
diff --git a/plugins/devkit/devkit-java-tests/testData/threadingModelHelper/SubtypingPolymorphism.java b/plugins/devkit/devkit-java-tests/testData/threadingModelHelper/SubtypingPolymorphism.java
index b86cc429970f..1b648e66033c 100644
--- a/plugins/devkit/devkit-java-tests/testData/threadingModelHelper/SubtypingPolymorphism.java
+++ b/plugins/devkit/devkit-java-tests/testData/threadingModelHelper/SubtypingPolymorphism.java
@@ -3,7 +3,7 @@ import com.intellij.util.concurrency.ThreadingAssertions;
public class SubtypingPolymorphism {
public void testMethod() {
- Service[] services = {new FileService(), new NetworkService(), new DatabaseService()};
+ Service[] services = {new FileService(), new UIService(), new DatabaseService()};
for (Service service : services) {
service.execute();
}
diff --git a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/threadingModelHelper/LockReqsUnitTest.kt b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/threadingModelHelper/LockReqsUnitTest.kt
index c34041ff8fed..d8c45be68121 100644
--- a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/threadingModelHelper/LockReqsUnitTest.kt
+++ b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/threadingModelHelper/LockReqsUnitTest.kt
@@ -10,11 +10,11 @@ import org.jetbrains.idea.devkit.DevkitJavaTestsUtil
@TestDataPath($$"$CONTENT_ROOT/testData/threadingModelHelper/")
class LockReqsUnitTest : BasePlatformTestCase() {
- private lateinit var analyzer: LockReqsAnalyzer
+ private lateinit var analyzer: LockReqsAnalyzerDFS
override fun setUp() {
super.setUp()
- analyzer = LockReqsAnalyzer()
+ analyzer = LockReqsAnalyzerDFS()
myFixture.addFileToProject("com/intellij/util/concurrency/annotations.java", """
package com.intellij.util.concurrency.annotations;
public @interface RequiresReadLock {}
@@ -44,20 +44,20 @@ class LockReqsUnitTest : BasePlatformTestCase() {
override fun getBasePath() = DevkitJavaTestsUtil.TESTDATA_PATH + "threadingModelHelper/"
fun testNoLockRequirements() {
- val result = doTest("NoLockRequirements", "testMethod")
+ val result = doTest("NoLockRequirements")
val actualPaths = formatResult(result)
assertTrue(actualPaths.isEmpty())
}
fun testAssertionInNestedBlock() {
- val result = doTest("AssertionInNestedBlock", "testMethod")
+ val result = doTest("AssertionInNestedBlock")
val expectedPaths = listOf("AssertionInNestedBlock.testMethod => READ.ASSERTION")
val actualPaths = formatResult(result)
assertEquals(expectedPaths.sorted(), actualPaths.sorted())
}
fun testAnnotationInChain() {
- val result = doTest("AnnotationInChain", "testMethod")
+ val result = doTest("AnnotationInChain")
val expectedPaths = listOf("AnnotationInChain.testMethod -> AnnotationInChain.intermediateMethod" +
" -> AnnotationInChain.targetMethod => READ.ANNOTATION")
val actualPaths = formatResult(result)
@@ -65,7 +65,7 @@ class LockReqsUnitTest : BasePlatformTestCase() {
}
fun testBothAnnotationAndAssertion() {
- val result = doTest("BothAnnotationAndAssertion", "testMethod")
+ val result = doTest("BothAnnotationAndAssertion")
val expectedPaths = listOf("BothAnnotationAndAssertion.testMethod => WRITE.ANNOTATION",
"BothAnnotationAndAssertion.testMethod => BGT.ASSERTION")
val actualPaths = formatResult(result)
@@ -73,22 +73,22 @@ class LockReqsUnitTest : BasePlatformTestCase() {
}
fun testCyclicRecursiveCalls() {
- val result = doTest("CyclicRecursiveCalls", "testMethod")
+ val result = doTest("CyclicRecursiveCalls")
val expectedPaths = listOf("CyclicRecursiveCalls.testMethod -> CyclicRecursiveCalls.methodB => READ.ANNOTATION")
val actualPaths = formatResult(result)
assertEquals(expectedPaths.sorted(), actualPaths.sorted())
}
fun testDifferentClassesMethods() {
- val result = doTest("DifferentClassesMethods", "testMethod")
+ val result = doTest("DifferentClassesMethods")
val expectedPaths = listOf("DifferentClassesMethods.testMethod -> Helper.helperMethod -> Service.serviceMethod => EDT.ANNOTATION",
- "DifferentClassesMethods.testMethod -> Helper.helperMethod -> Service.serviceMethod => WRITE.ASSERTION")
+ "DifferentClassesMethods.testMethod -> Helper.helperMethod => WRITE.ASSERTION")
val actualPaths = formatResult(result)
assertEquals(expectedPaths.sorted(), actualPaths.sorted())
}
fun testMultipleAssertionsInMethod() {
- val result = doTest("MultipleAssertionsInMethod", "testMethod")
+ val result = doTest("MultipleAssertionsInMethod")
val expectedPaths = listOf("MultipleAssertionsInMethod.testMethod => READ.ASSERTION")
val actualPaths = formatResult(result)
assertEquals(1, actualPaths.size)
@@ -97,7 +97,7 @@ class LockReqsUnitTest : BasePlatformTestCase() {
fun testLambdaWithMethodReference() {
- val result = doTest("LambdaWithMethodReference", "testMethod")
+ val result = doTest("LambdaWithMethodReference")
val expectedPaths = listOf("LambdaWithMethodReference.testMethod -> LambdaWithMethodReference.processItem => READ.ASSERTION")
val actualPaths = formatResult(result)
assertEquals(expectedPaths.sorted(), actualPaths.sorted())
@@ -105,7 +105,7 @@ class LockReqsUnitTest : BasePlatformTestCase() {
}
fun testSubtypingPolymorphism() {
- val result = doTest("SubtypingPolymorphism", "testMethod")
+ val result = doTest("SubtypingPolymorphism")
val expectedPaths = listOf(
"SubtypingPolymorphism.testMethod -> FileService.execute => READ.ANNOTATION",
"SubtypingPolymorphism.testMethod -> UIService.execute => EDT.ASSERTION",
@@ -115,11 +115,11 @@ class LockReqsUnitTest : BasePlatformTestCase() {
assertEquals(expectedPaths.sorted(), actualPaths.sorted())
}
- private fun doTest(className: String, methodName: String): AnalysisResult {
+ private fun doTest(className: String): AnalysisResult {
val fileName = "${getTestName(false)}.java"
val psiJavaFile = myFixture.configureByFile(fileName) as PsiJavaFile
val targetClass = psiJavaFile.classes.find { it.name == className } ?: error("Could not find class $className")
- val targetMethod = targetClass.methods.find { it.name == methodName } ?: error("Could not find method $methodName")
+ val targetMethod = targetClass.methods.find { it.name == testMethodName } ?: error("Could not find method $testMethodName")
return analyzer.analyzeMethod(targetMethod)
}
@@ -131,4 +131,8 @@ class LockReqsUnitTest : BasePlatformTestCase() {
}
return actualPaths
}
+
+ companion object {
+ private const val testMethodName = "testMethod"
+ }
}