Debugger: Dispose ExtractionData/ExtractionResult when necessary
This fixes memory leak due to extensive use of "Evaluate expression"
This commit is contained in:
+6
-2
@@ -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 })
|
||||
|
||||
+18
-12
@@ -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() }
|
||||
|
||||
+5
-2
@@ -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 }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user