Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix line prompt managment #356

Conversation

arksap2002
Copy link
Collaborator

Description of changes made

In case of lackness of method, add code of class.

Other notes

Closes #351
Closes #247

  • I have checked that I am merging into correct branch

Copy link
Collaborator

@pderakhshanfar pderakhshanfar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It still fails when asking to generate test for the package line in Kotlin :(

java.lang.NullPointerException
	at org.jetbrains.research.testspark.tools.llm.generation.PromptManager.getMethodDescriptor(PromptManager.kt:294)
	at org.jetbrains.research.testspark.tools.llm.generation.PromptManager.generatePrompt$lambda$6(PromptManager.kt:128)
	at com.intellij.openapi.application.impl.RwLockHolder.runReadAction(RwLockHolder.kt:271)
	at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:845)
	at org.jetbrains.research.testspark.tools.llm.generation.PromptManager.generatePrompt(PromptManager.kt:69)
	at org.jetbrains.research.testspark.tools.llm.generation.LLMProcessManager.runTestGenerator(LLMProcessManager.kt:105)
	at org.jetbrains.research.testspark.tools.Pipeline$runTestGeneration$1.run(Pipeline.kt:96)
	at com.intellij.openapi.progress.impl.CoreProgressManager.startTask(CoreProgressManager.java:477)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.startTask(ProgressManagerImpl.java:133)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcessWithProgressAsynchronously$6(CoreProgressManager.java:528)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$4(ProgressRunner.java:250)
	at com.intellij.openapi.progress.ProgressManager.lambda$runProcess$0(ProgressManager.java:100)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$1(CoreProgressManager.java:221)
	at com.intellij.platform.diagnostic.telemetry.helpers.TraceKt.use(trace.kt:46)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:220)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$13(CoreProgressManager.java:660)
	at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:735)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:691)
	at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:659)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:79)
	at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:202)
	at com.intellij.openapi.progress.ProgressManager.runProcess(ProgressManager.java:100)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$5(ProgressRunner.java:250)
	at com.intellij.openapi.progress.impl.ProgressRunner$ProgressRunnable.run(ProgressRunner.java:500)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:702)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:699)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:699)
	at java.base/java.lang.Thread.run(Thread.java:840)

Comment on lines 74 to +77
fun generatePromptForLine(
lineUnderTest: String,
method: MethodRepresentation,
interestingClassesFromMethod: List<ClassRepresentation>,
method: MethodRepresentation?,
interestingClassesFromMethod: List<ClassRepresentation>?,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deeper you get on the method calling chain, more places there will be where you'll need to replace T with T?. It is generally better to have as few T? params as possible; otherwise, your Kotlin code turns into Java.

I recommend resolving all of these problems inside PromptManager before calling methods of PromptGenerator:

CodeType.LINE -> {
	val lineNumber = codeType.objectIndex

	// get code of line under test
	val document = psiHelper.getDocumentFromPsiFile()
	val lineStartOffset = document!!.getLineStartOffset(lineNumber - 1)
	val lineEndOffset = document.getLineEndOffset(lineNumber - 1)

	val lineUnderTest = document.getText(TextRange.create(lineStartOffset, lineEndOffset))

	val psiMethod = getPsiMethod(cut, getMethodDescriptor(cut, lineNumber))

	val context = if (psiMethod != null) createMethodRepresentation(psiMethod) else cut!!.fullText
	val interestingClassesFromMethod = if (psiMethod != null) {
		psiHelper.getInterestingPsiClassesWithQualifiedNames(cut, psiMethod)
			?.map(this::createClassRepresentation)
			?.toList()
	}
	else {
		emptyList()
	}

	promptGenerator.generatePromptForLine(
		lineUnderTest,
		context,
		interestingClassesFromMethod,
		testSamplesCode,
	)
}

And rename the method parameter of promptGenerator.generatePromptForLine to context.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is to minimize the number of places where you need to replace T with T?. Check all the places where you did the change; likely you will manage to avoid it by having a simple if in the caller's code.

Comment on lines +72 to +74
fun insertMethodsSignatures(interestingClasses: List<ClassRepresentation>?) = apply {
interestingClasses ?: return@apply

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to have this "if" check inside the caller part.

@@ -125,19 +125,19 @@ class PromptManager(

CodeType.LINE -> {
val lineNumber = codeType.objectIndex
val psiMethod = getPsiMethod(cut, getMethodDescriptor(cut, lineNumber))!!
val psiMethod = getPsiMethod(cut, getMethodDescriptor(cut, lineNumber))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail if I start generation for the following Kotlin code on a line (*):

class CalcKotlin {
    val a = 10;

    fun add(a: Int, b: Int) = a + b
}


val a = 10; // (*)

Here is the stack trace:

2024-09-24 17:32:24,807 [  83815] SEVERE - #c.i.o.p.Task - null
java.lang.NullPointerException
	at org.jetbrains.research.testspark.tools.llm.generation.PromptManager.getMethodDescriptor(PromptManager.kt:294)
	at org.jetbrains.research.testspark.tools.llm.generation.PromptManager.generatePrompt$lambda$6(PromptManager.kt:128)
	at com.intellij.openapi.application.impl.RwLockHolder.runReadAction(RwLockHolder.kt:271)
	at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:845)
	at org.jetbrains.research.testspark.tools.llm.generation.PromptManager.generatePrompt(PromptManager.kt:69)
	at org.jetbrains.research.testspark.tools.llm.generation.LLMProcessManager.runTestGenerator(LLMProcessManager.kt:105)
	at org.jetbrains.research.testspark.tools.Pipeline$runTestGeneration$1.run(Pipeline.kt:96)
	at com.intellij.openapi.progress.impl.CoreProgressManager.startTask(CoreProgressManager.java:477)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.startTask(ProgressManagerImpl.java:133)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcessWithProgressAsynchronously$6(CoreProgressManager.java:528)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$4(ProgressRunner.java:250)
	at com.intellij.openapi.progress.ProgressManager.lambda$runProcess$0(ProgressManager.java:100)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$1(CoreProgressManager.java:221)
	at com.intellij.platform.diagnostic.telemetry.helpers.TraceKt.use(trace.kt:46)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:220)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$13(CoreProgressManager.java:660)
	at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:735)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:691)
	at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:659)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:79)
	at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:202)
	at com.intellij.openapi.progress.ProgressManager.runProcess(ProgressManager.java:100)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$5(ProgressRunner.java:250)
	at com.intellij.openapi.progress.impl.ProgressRunner$ProgressRunnable.run(ProgressRunner.java:500)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:702)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:699)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:699)
	at java.base/java.lang.Thread.run(Thread.java:840)

When we generate tests for a line, PromptManager::getMethodDescriptor method asserts that there will always be a method surrounding the selected line (i.e., currentPsiMethod = psiHelper.getSurroundingMethod(caret)!!), which is false in this scenario:

 private fun getMethodDescriptor(
        psiClass: PsiClassWrapper?,
        lineNumber: Int,
    ): String {
        // Processing function outside the class
        if (psiClass == null) {
            /* problem here -> */ val currentPsiMethod = psiHelper.getSurroundingMethod(caret)!!
            return psiHelper.generateMethodDescriptor(currentPsiMethod)
        }

Comment on lines +156 to +157
private fun createMethodRepresentation(psiMethod: PsiMethodWrapper?): MethodRepresentation? {
psiMethod ?: return null
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest moving the nullness check of psiMethod to the caller.

@Vladislav0Art Vladislav0Art force-pushed the arksap2002/bugs/fix-anaction-update branch from b40a077 to 3079173 Compare October 4, 2024 14:39
@Vladislav0Art
Copy link
Collaborator

I will address the closed issues in #344. Afterward, we can close this PR in favor of #344.

@Vladislav0Art Vladislav0Art added the duplicate This issue or pull request already exists label Oct 7, 2024
@Vladislav0Art
Copy link
Collaborator

The issues are addressed in #344.

@arksap2002 arksap2002 deleted the arksap2002/bugs/fix-line-prompt-creation branch October 15, 2024 21:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working duplicate This issue or pull request already exists
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Incorrect prompt creation for a line outside of method but within class [Java] Wrong enum class parsing
3 participants