Debugger: Dispose ExtractionData/ExtractionResult when necessary

This fixes memory leak due to extensive use of "Evaluate expression"
This commit is contained in:
Alexey Sedunov
2018-06-07 15:26:54 +03:00
parent 16dbc6fb4d
commit 9a3a7fbcca
3 changed files with 29 additions and 16 deletions
@@ -26,6 +26,7 @@ import com.intellij.diagnostic.LogMessageEx
import com.intellij.openapi.diagnostic.Attachment
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiDocumentManager
@@ -214,8 +215,11 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
val extractionResult = getFunctionForExtractedFragment(codeFragment, sourcePosition.file, sourcePosition.line)
?: throw IllegalStateException("Code fragment cannot be extracted to function: ${codeFragment.text}")
val parametersDescriptor = extractionResult.getParametersForDebugger(codeFragment)
val extractedFunction = extractionResult.declaration as KtNamedFunction
val (parametersDescriptor, extractedFunction) = try {
extractionResult.getParametersForDebugger(codeFragment) to extractionResult.declaration as KtNamedFunction
} finally {
Disposer.dispose(extractionResult)
}
if (LOG.isDebugEnabled) {
LOG.debug("Extracted function:\n" + runReadAction { extractedFunction.text })
@@ -20,6 +20,7 @@ import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil
import com.intellij.diagnostic.LogMessageEx
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.Attachment
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.Key
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
@@ -97,20 +98,25 @@ fun getFunctionForExtractedFragment(
allowSpecialClassNames = true,
captureLocalFunctions = true,
canWrapInWith = true)
val analysisResult = ExtractionData(tmpFile, newDebugExpressions.toRange(), targetSibling, null, options).performAnalysis()
if (analysisResult.status != Status.SUCCESS) {
throw EvaluateExceptionUtil.createEvaluateException(getErrorMessageForExtractFunctionResult(analysisResult, tmpFile))
}
val extractionData = ExtractionData(tmpFile, newDebugExpressions.toRange(), targetSibling, null, options)
try {
val analysisResult = extractionData.performAnalysis()
if (analysisResult.status != Status.SUCCESS) {
throw EvaluateExceptionUtil.createEvaluateException(getErrorMessageForExtractFunctionResult(analysisResult, tmpFile))
}
val validationResult = analysisResult.descriptor!!.validate()
if (!validationResult.conflicts.isEmpty) {
throw EvaluateExceptionUtil.createEvaluateException("Following declarations are unavailable in debug scope: ${validationResult.conflicts.keySet().joinToString(",") { it.text }}")
}
val validationResult = analysisResult.descriptor!!.validate()
if (!validationResult.conflicts.isEmpty) {
throw EvaluateExceptionUtil.createEvaluateException("Following declarations are unavailable in debug scope: ${validationResult.conflicts.keySet().joinToString(",") { it.text }}")
}
val generatorOptions = ExtractionGeneratorOptions(inTempFile = true,
dummyName = GENERATED_FUNCTION_NAME,
allowExpressionBody = false)
return ExtractionGeneratorConfiguration(validationResult.descriptor, generatorOptions).generateDeclaration()
val generatorOptions = ExtractionGeneratorOptions(inTempFile = true,
dummyName = GENERATED_FUNCTION_NAME,
allowExpressionBody = false)
return ExtractionGeneratorConfiguration(validationResult.descriptor, generatorOptions).generateDeclaration()
} finally {
Disposer.dispose(extractionData)
}
}
return runReadAction { generateFunction() }
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.idea.refactoring.introduce.ExtractableSubstringInfo
import org.jetbrains.kotlin.idea.refactoring.introduce.extractableSubstringInfo
import org.jetbrains.kotlin.idea.refactoring.introduce.substringContextOrThis
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiRange
import org.jetbrains.kotlin.psi.*
@@ -270,6 +271,8 @@ data class ExtractionData(
}
fun unmarkReferencesInside(root: PsiElement) {
if (!root.isValid) return
root.forEachDescendantOfType<KtSimpleNameExpression> { it.resolveResult = null }
runReadAction {
if (!root.isValid) return@runReadAction
root.forEachDescendantOfType<KtSimpleNameExpression> { it.resolveResult = null }
}
}