Minor: fix warnings
This commit is contained in:
@@ -40,7 +40,6 @@ import com.intellij.util.ExceptionUtil
|
||||
import com.sun.jdi.InvocationException
|
||||
import com.sun.jdi.ObjectReference
|
||||
import com.sun.jdi.VMDisconnectedException
|
||||
import com.sun.jdi.VirtualMachine
|
||||
import com.sun.jdi.request.EventRequest
|
||||
import org.jetbrains.eval4j.*
|
||||
import org.jetbrains.eval4j.jdi.JDIEval
|
||||
@@ -66,8 +65,6 @@ import org.jetbrains.kotlin.idea.util.DebuggerUtils
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.idea.util.attachment.attachmentByPsiFile
|
||||
import org.jetbrains.kotlin.idea.util.attachment.mergeAttachments
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.debugTypeInfo
|
||||
@@ -84,6 +81,7 @@ import java.util.*
|
||||
|
||||
internal val RECEIVER_NAME = "\$receiver"
|
||||
internal val THIS_NAME = "this"
|
||||
val logger = Logger.getInstance(KotlinEvaluator::class.java)
|
||||
|
||||
object KotlinEvaluationBuilder: EvaluatorBuilder {
|
||||
override fun build(codeFragment: PsiElement, position: SourcePosition?): ExpressionEvaluator {
|
||||
@@ -120,14 +118,10 @@ object KotlinEvaluationBuilder: EvaluatorBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
val logger = Logger.getInstance(javaClass<KotlinEvaluator>())
|
||||
|
||||
class KotlinEvaluator(val codeFragment: KtCodeFragment,
|
||||
val sourcePosition: SourcePosition
|
||||
) : Evaluator {
|
||||
class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: SourcePosition): Evaluator {
|
||||
override fun evaluate(context: EvaluationContextImpl): Any? {
|
||||
if (codeFragment.text.isEmpty()) {
|
||||
return context.debugProcess.virtualMachineProxy.mirrorOf()
|
||||
return context.debugProcess.virtualMachineProxy.mirrorOfVoid()
|
||||
}
|
||||
|
||||
var isCompiledDataFromCache = true
|
||||
@@ -164,7 +158,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment,
|
||||
ExceptionUtil.getThrowableText(e),
|
||||
mergeAttachments(*attachments)))
|
||||
|
||||
val cause = if (e.getMessage() != null) ": ${e.getMessage()}" else ""
|
||||
val cause = if (e.message != null) ": ${e.message}" else ""
|
||||
exception("An exception occurs during Evaluate Expression Action $cause")
|
||||
}
|
||||
}
|
||||
@@ -178,24 +172,20 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment,
|
||||
codeFragment.checkForErrors(false)
|
||||
|
||||
val extractionResult = getFunctionForExtractedFragment(codeFragment, sourcePosition.file, sourcePosition.line)
|
||||
if (extractionResult == null) {
|
||||
throw IllegalStateException("Code fragment cannot be extracted to function")
|
||||
}
|
||||
?: throw IllegalStateException("Code fragment cannot be extracted to function")
|
||||
val parametersDescriptor = extractionResult.getParametersForDebugger(codeFragment)
|
||||
val extractedFunction = extractionResult.declaration as KtNamedFunction
|
||||
|
||||
val classFileFactory = createClassFileFactory(codeFragment, extractedFunction, context, parametersDescriptor)
|
||||
|
||||
val outputFiles = classFileFactory.asList().filterClassFiles()
|
||||
.sortedBy { it.relativePath.length() }
|
||||
.sortedBy { it.relativePath.length }
|
||||
|
||||
val funName = runReadAction { extractedFunction.name }
|
||||
if (funName == null) {
|
||||
throw IllegalStateException("Extracted function should have a name: ${extractedFunction.text}")
|
||||
}
|
||||
?: throw IllegalStateException("Extracted function should have a name: ${extractedFunction.text}")
|
||||
|
||||
val additionalFiles = if (outputFiles.size() < 2) emptyList()
|
||||
else outputFiles.subList(1, outputFiles.size()).map { getClassName(it.relativePath) to it.asByteArray() }
|
||||
val additionalFiles = if (outputFiles.size < 2) emptyList()
|
||||
else outputFiles.subList(1, outputFiles.size).map { getClassName(it.relativePath) to it.asByteArray() }
|
||||
|
||||
return CompiledDataDescriptor(
|
||||
outputFiles.first().asByteArray(),
|
||||
@@ -353,7 +343,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment,
|
||||
val (bindingContext, moduleDescriptor, files) = jetFile.checkForErrors(true)
|
||||
|
||||
val generateClassFilter = object : GenerationState.GenerateClassFilter() {
|
||||
override fun shouldGeneratePackagePart(file: KtFile) = file == jetFile
|
||||
override fun shouldGeneratePackagePart(jetFile: KtFile) = jetFile == jetFile
|
||||
override fun shouldAnnotateClass(classOrObject: KtClassOrObject) = true
|
||||
override fun shouldGenerateClass(classOrObject: KtClassOrObject) = classOrObject.getContainingJetFile() == jetFile
|
||||
override fun shouldGenerateScript(script: KtScript) = false
|
||||
@@ -405,9 +395,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment,
|
||||
val declarationDescriptor = paramAnonymousType.constructor.declarationDescriptor
|
||||
if (declarationDescriptor is ClassDescriptor) {
|
||||
val localVariable = visitor.findValue(localVariableName, asmType = null, checkType = false, failIfNotFound = false)
|
||||
if (localVariable == null) {
|
||||
exception("Couldn't find local variable this in current frame to get classType for anonymous type ${paramAnonymousType}}")
|
||||
}
|
||||
?: exception("Couldn't find local variable this in current frame to get classType for anonymous type $paramAnonymousType}")
|
||||
record(CodegenBinding.ASM_TYPE, declarationDescriptor, localVariable.asmType)
|
||||
}
|
||||
}
|
||||
@@ -416,7 +404,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment,
|
||||
private fun exception(msg: String) = throw EvaluateExceptionUtil.createEvaluateException(msg)
|
||||
|
||||
private fun exception(e: Throwable): Nothing {
|
||||
val message = e.getMessage()
|
||||
val message = e.message
|
||||
if (message != null) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(message, e)
|
||||
}
|
||||
@@ -429,7 +417,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment,
|
||||
AnalyzingUtils.checkForSyntacticErrors(this)
|
||||
}
|
||||
catch (e: IllegalArgumentException) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(e.getMessage())
|
||||
throw EvaluateExceptionUtil.createEvaluateException(e.message)
|
||||
}
|
||||
|
||||
val resolutionFacade = KotlinCacheService.getInstance(project).getResolutionFacade(listOf(this, createFlexibleTypesFile()))
|
||||
@@ -489,7 +477,7 @@ private fun createFileForDebugger(codeFragment: KtCodeFragment,
|
||||
jetFile.suppressDiagnosticsInDebugMode = true
|
||||
|
||||
val list = jetFile.declarations
|
||||
val function = list.get(0) as KtNamedFunction
|
||||
val function = list[0] as KtNamedFunction
|
||||
|
||||
function.receiverTypeReference?.debugTypeInfo = extractedFunction.receiverTypeReference?.debugTypeInfo
|
||||
|
||||
|
||||
+50
-57
@@ -44,17 +44,17 @@ fun getFunctionForExtractedFragment(
|
||||
fun getErrorMessageForExtractFunctionResult(analysisResult: AnalysisResult, tmpFile: KtFile): String {
|
||||
if (KotlinInternalMode.enabled) {
|
||||
logger.error("Couldn't extract function for debugger:\n" +
|
||||
"FILE NAME: ${breakpointFile.getName()}\n" +
|
||||
"BREAKPOINT LINE: ${breakpointLine}\n" +
|
||||
"CODE FRAGMENT:\n${codeFragment.getText()}\n" +
|
||||
"FILE NAME: ${breakpointFile.name}\n" +
|
||||
"BREAKPOINT LINE: $breakpointLine\n" +
|
||||
"CODE FRAGMENT:\n${codeFragment.text}\n" +
|
||||
"ERRORS:\n${analysisResult.messages.map { "$it: ${it.renderMessage()}" }.joinToString("\n")}\n" +
|
||||
"TMPFILE_TEXT:\n${tmpFile.text}\n" +
|
||||
"FILE TEXT: \n${breakpointFile.getText()}\n")
|
||||
"FILE TEXT: \n${breakpointFile.text}\n")
|
||||
}
|
||||
return analysisResult.messages.map { errorMessage ->
|
||||
val message = when(errorMessage) {
|
||||
ErrorMessage.NO_EXPRESSION -> "Cannot perform an action without an expression"
|
||||
ErrorMessage.NO_CONTAINER -> "Cannot perform an action at this breakpoint ${breakpointFile.getName()}:${breakpointLine}"
|
||||
ErrorMessage.NO_CONTAINER -> "Cannot perform an action at this breakpoint ${breakpointFile.name}:$breakpointLine"
|
||||
ErrorMessage.SUPER_CALL -> "Cannot perform an action for expression with super call"
|
||||
ErrorMessage.DENOTABLE_TYPES -> "Cannot perform an action because following types are unavailable from debugger scope"
|
||||
ErrorMessage.ERROR_TYPES -> "Cannot perform an action because this code fragment contains erroneous types"
|
||||
@@ -74,16 +74,14 @@ fun getFunctionForExtractedFragment(
|
||||
val tmpFile = originalFile.createTempCopy { it }
|
||||
tmpFile.suppressDiagnosticsInDebugMode = true
|
||||
|
||||
val contextElement = getExpressionToAddDebugExpressionBefore(tmpFile, codeFragment.getContext(), breakpointLine)
|
||||
if (contextElement == null) return null
|
||||
val contextElement = getExpressionToAddDebugExpressionBefore(tmpFile, codeFragment.context, breakpointLine) ?: return null
|
||||
|
||||
addImportsToFile(codeFragment.importsAsImportList(), tmpFile)
|
||||
|
||||
val newDebugExpressions = addDebugExpressionBeforeContextElement(codeFragment, contextElement)
|
||||
if (newDebugExpressions.isEmpty()) return null
|
||||
|
||||
val targetSibling = tmpFile.getDeclarations().firstOrNull()
|
||||
if (targetSibling == null) return null
|
||||
val targetSibling = tmpFile.declarations.firstOrNull() ?: return null
|
||||
|
||||
val options = ExtractionOptions(inferUnitTypeForUnusedValues = false,
|
||||
enableListBoxing = true,
|
||||
@@ -95,8 +93,8 @@ fun getFunctionForExtractedFragment(
|
||||
}
|
||||
|
||||
val validationResult = analysisResult.descriptor!!.validate()
|
||||
if (!validationResult.conflicts.isEmpty()) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException("Following declarations are unavailable in debug scope: ${validationResult.conflicts.keySet().map { it.getText() }.joinToString(",")}")
|
||||
if (!validationResult.conflicts.isEmpty) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException("Following declarations are unavailable in debug scope: ${validationResult.conflicts.keySet().map { it.text }.joinToString(",")}")
|
||||
}
|
||||
|
||||
val generatorOptions = ExtractionGeneratorOptions(inTempFile = true,
|
||||
@@ -111,12 +109,12 @@ fun getFunctionForExtractedFragment(
|
||||
|
||||
private fun addImportsToFile(newImportList: KtImportList?, tmpFile: KtFile) {
|
||||
if (newImportList != null) {
|
||||
val tmpFileImportList = tmpFile.getImportList()
|
||||
val packageDirective = tmpFile.getPackageDirective()
|
||||
val tmpFileImportList = tmpFile.importList
|
||||
val packageDirective = tmpFile.packageDirective
|
||||
val psiFactory = KtPsiFactory(tmpFile)
|
||||
if (tmpFileImportList == null) {
|
||||
tmpFile.addAfter(psiFactory.createNewLine(), packageDirective)
|
||||
tmpFile.addAfter(newImportList, tmpFile.getPackageDirective())
|
||||
tmpFile.addAfter(newImportList, tmpFile.packageDirective)
|
||||
}
|
||||
else {
|
||||
val tmpFileImports = tmpFileImportList.imports
|
||||
@@ -136,51 +134,46 @@ private fun addImportsToFile(newImportList: KtImportList?, tmpFile: KtFile) {
|
||||
}
|
||||
|
||||
private fun KtFile.getElementInCopy(e: PsiElement): PsiElement? {
|
||||
val offset = e.getTextRange()?.getStartOffset()
|
||||
if (offset == null) {
|
||||
return null
|
||||
}
|
||||
val offset = e.textRange?.startOffset ?: return null
|
||||
var elementAt = this.findElementAt(offset)
|
||||
while (elementAt == null || elementAt.getTextRange()?.getEndOffset() != e.getTextRange()?.getEndOffset()) {
|
||||
elementAt = elementAt?.getParent()
|
||||
while (elementAt == null || elementAt.textRange?.endOffset != e.textRange?.endOffset) {
|
||||
elementAt = elementAt?.parent
|
||||
}
|
||||
return elementAt
|
||||
}
|
||||
|
||||
private fun getExpressionToAddDebugExpressionBefore(tmpFile: KtFile, contextElement: PsiElement?, line: Int): PsiElement? {
|
||||
if (contextElement == null) {
|
||||
val lineStart = CodeInsightUtils.getStartLineOffset(tmpFile, line)
|
||||
if (lineStart == null) return null
|
||||
val lineStart = CodeInsightUtils.getStartLineOffset(tmpFile, line) ?: return null
|
||||
|
||||
val elementAtOffset = tmpFile.findElementAt(lineStart)
|
||||
if (elementAtOffset == null) return null
|
||||
val elementAtOffset = tmpFile.findElementAt(lineStart) ?: return null
|
||||
|
||||
return CodeInsightUtils.getTopmostElementAtOffset(elementAtOffset, lineStart) ?: elementAtOffset
|
||||
}
|
||||
|
||||
val containingFile = contextElement.getContainingFile()
|
||||
val containingFile = contextElement.containingFile
|
||||
if (containingFile is KtCodeFragment) {
|
||||
return getExpressionToAddDebugExpressionBefore(tmpFile, containingFile.getContext(), line)
|
||||
return getExpressionToAddDebugExpressionBefore(tmpFile, containingFile.context, line)
|
||||
}
|
||||
|
||||
fun shouldStop(el: PsiElement?, p: PsiElement?) = p is KtBlockExpression || el is KtDeclaration || el is KtFile
|
||||
|
||||
var elementAt = tmpFile.getElementInCopy(contextElement)
|
||||
|
||||
var parent = elementAt?.getParent()
|
||||
var parent = elementAt?.parent
|
||||
if (shouldStop(elementAt, parent)) {
|
||||
return elementAt
|
||||
}
|
||||
|
||||
var parentOfParent = parent?.getParent()
|
||||
var parentOfParent = parent?.parent
|
||||
|
||||
while (parent != null && parentOfParent != null) {
|
||||
if (shouldStop(parent, parentOfParent)) {
|
||||
break
|
||||
}
|
||||
|
||||
parent = parent.getParent()
|
||||
parentOfParent = parent?.getParent()
|
||||
parent = parent.parent
|
||||
parentOfParent = parent?.parent
|
||||
}
|
||||
|
||||
return parent
|
||||
@@ -191,9 +184,9 @@ private fun addDebugExpressionBeforeContextElement(codeFragment: KtCodeFragment,
|
||||
|
||||
fun insertNewInitializer(classBody: KtClassBody): PsiElement? {
|
||||
val initializer = psiFactory.createAnonymousInitializer()
|
||||
val newInitializer = (classBody.addAfter(initializer, classBody.getFirstChild()) as KtClassInitializer)
|
||||
val block = newInitializer.getBody() as KtBlockExpression?
|
||||
return block?.getLastChild()
|
||||
val newInitializer = (classBody.addAfter(initializer, classBody.firstChild) as KtClassInitializer)
|
||||
val block = newInitializer.body as KtBlockExpression?
|
||||
return block?.lastChild
|
||||
}
|
||||
|
||||
val elementBefore = when {
|
||||
@@ -201,20 +194,20 @@ private fun addDebugExpressionBeforeContextElement(codeFragment: KtCodeFragment,
|
||||
val fakeFunction = psiFactory.createFunction("fun _debug_fun_() {}")
|
||||
contextElement.add(psiFactory.createNewLine())
|
||||
val newFakeFun = contextElement.add(fakeFunction) as KtNamedFunction
|
||||
newFakeFun.getBodyExpression()!!.getLastChild()
|
||||
newFakeFun.bodyExpression!!.lastChild
|
||||
}
|
||||
contextElement is KtProperty && !contextElement.isLocal() -> {
|
||||
val delegateExpressionOrInitializer = contextElement.getDelegateExpressionOrInitializer()
|
||||
contextElement is KtProperty && !contextElement.isLocal -> {
|
||||
val delegateExpressionOrInitializer = contextElement.delegateExpressionOrInitializer
|
||||
if (delegateExpressionOrInitializer != null) {
|
||||
wrapInRunFun(delegateExpressionOrInitializer)
|
||||
}
|
||||
else {
|
||||
val getter = contextElement.getGetter()!!
|
||||
val getter = contextElement.getter!!
|
||||
if (!getter.hasBlockBody()) {
|
||||
wrapInRunFun(getter.getBodyExpression()!!)
|
||||
wrapInRunFun(getter.bodyExpression!!)
|
||||
}
|
||||
else {
|
||||
(getter.getBodyExpression() as KtBlockExpression).getStatements().first()
|
||||
(getter.bodyExpression as KtBlockExpression).statements.first()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,29 +219,29 @@ private fun addDebugExpressionBeforeContextElement(codeFragment: KtCodeFragment,
|
||||
insertNewInitializer(contextElement.getBody()!!)
|
||||
}
|
||||
contextElement is KtFunctionLiteral -> {
|
||||
val block = contextElement.getBodyExpression()!!
|
||||
block.getStatements().firstOrNull() ?: block.getLastChild()
|
||||
val block = contextElement.bodyExpression!!
|
||||
block.statements.firstOrNull() ?: block.lastChild
|
||||
}
|
||||
contextElement is KtDeclarationWithBody && !contextElement.hasBody()-> {
|
||||
val block = psiFactory.createBlock("")
|
||||
val newBlock = contextElement.add(block) as KtBlockExpression
|
||||
newBlock.getRBrace()
|
||||
newBlock.rBrace
|
||||
}
|
||||
contextElement is KtDeclarationWithBody && !contextElement.hasBlockBody()-> {
|
||||
wrapInRunFun(contextElement.getBodyExpression()!!)
|
||||
wrapInRunFun(contextElement.bodyExpression!!)
|
||||
}
|
||||
contextElement is KtDeclarationWithBody && contextElement.hasBlockBody()-> {
|
||||
val block = contextElement.getBodyExpression() as KtBlockExpression
|
||||
val last = block.getStatements().lastOrNull()
|
||||
val block = contextElement.bodyExpression as KtBlockExpression
|
||||
val last = block.statements.lastOrNull()
|
||||
if (last is KtReturnExpression)
|
||||
last
|
||||
else
|
||||
block.getRBrace()
|
||||
block.rBrace
|
||||
}
|
||||
contextElement is KtWhenEntry -> {
|
||||
val entryExpression = contextElement.getExpression()
|
||||
val entryExpression = contextElement.expression
|
||||
if (entryExpression is KtBlockExpression) {
|
||||
entryExpression.getStatements().firstOrNull() ?: entryExpression.getLastChild()
|
||||
entryExpression.statements.firstOrNull() ?: entryExpression.lastChild
|
||||
}
|
||||
else {
|
||||
wrapInRunFun(entryExpression!!)
|
||||
@@ -259,18 +252,18 @@ private fun addDebugExpressionBeforeContextElement(codeFragment: KtCodeFragment,
|
||||
}
|
||||
}
|
||||
|
||||
val parent = elementBefore?.getParent()
|
||||
val parent = elementBefore?.parent
|
||||
if (parent == null || elementBefore == null) return emptyList()
|
||||
|
||||
parent.addBefore(psiFactory.createNewLine(), elementBefore)
|
||||
|
||||
fun insertExpression(expr: KtElement?): List<KtExpression> {
|
||||
when (expr) {
|
||||
is KtBlockExpression -> return expr.getStatements().flatMap { insertExpression(it) }
|
||||
is KtBlockExpression -> return expr.statements.flatMap { insertExpression(it) }
|
||||
is KtExpression -> {
|
||||
val newDebugExpression = parent.addBefore(expr, elementBefore)
|
||||
if (newDebugExpression == null) {
|
||||
logger.error("Couldn't insert debug expression ${expr.getText()} to context file before ${elementBefore.getText()}")
|
||||
logger.error("Couldn't insert debug expression ${expr.text} to context file before ${elementBefore.text}")
|
||||
return emptyList()
|
||||
}
|
||||
parent.addBefore(psiFactory.createNewLine(), elementBefore)
|
||||
@@ -280,7 +273,7 @@ private fun addDebugExpressionBeforeContextElement(codeFragment: KtCodeFragment,
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val containingFile = codeFragment.getContext()?.getContainingFile()
|
||||
val containingFile = codeFragment.context?.containingFile
|
||||
if (containingFile is KtCodeFragment) {
|
||||
insertExpression(containingFile.getContentElement() as? KtExpression)
|
||||
}
|
||||
@@ -290,11 +283,11 @@ private fun addDebugExpressionBeforeContextElement(codeFragment: KtCodeFragment,
|
||||
}
|
||||
|
||||
private fun replaceByRunFunction(expression: KtExpression): KtCallExpression {
|
||||
val callExpression = KtPsiFactory(expression).createExpression("run { \n${expression.getText()} \n}") as KtCallExpression
|
||||
val callExpression = KtPsiFactory(expression).createExpression("run { \n${expression.text} \n}") as KtCallExpression
|
||||
val replaced = expression.replaced(callExpression)
|
||||
val typeArguments = InsertExplicitTypeArgumentsIntention.createTypeArguments(replaced, replaced.analyze())
|
||||
if (typeArguments?.getArguments()?.isNotEmpty() ?: false) {
|
||||
val calleeExpression = replaced.getCalleeExpression()
|
||||
if (typeArguments?.arguments?.isNotEmpty() ?: false) {
|
||||
val calleeExpression = replaced.calleeExpression
|
||||
replaced.addAfter(typeArguments!!, calleeExpression)
|
||||
}
|
||||
return replaced
|
||||
@@ -304,7 +297,7 @@ private fun wrapInRunFun(expression: KtExpression): PsiElement? {
|
||||
val replacedBody = replaceByRunFunction(expression)
|
||||
|
||||
// Increment modification tracker to clear ResolveCache after changes in function body
|
||||
(PsiManager.getInstance(expression.getProject()).getModificationTracker() as PsiModificationTrackerImpl).incCounter()
|
||||
(PsiManager.getInstance(expression.project).modificationTracker as PsiModificationTrackerImpl).incCounter()
|
||||
|
||||
return replacedBody.getFunctionLiteralArguments().first().getFunctionLiteral().getBodyExpression()?.getFirstChild()
|
||||
return replacedBody.functionLiteralArguments.first().getFunctionLiteral().bodyExpression?.firstChild
|
||||
}
|
||||
|
||||
+105
-108
@@ -124,7 +124,7 @@ private fun List<Instruction>.getVarDescriptorsAccessedAfterwards(bindingContext
|
||||
PseudocodeUtil.extractVariableDescriptorIfAny(it, false, bindingContext)?.let { accessedAfterwards.add(it) }
|
||||
|
||||
it is LocalFunctionDeclarationInstruction ->
|
||||
doTraversal(it.body.getEnterInstruction())
|
||||
doTraversal(it.body.enterInstruction)
|
||||
}
|
||||
|
||||
true
|
||||
@@ -155,14 +155,13 @@ private fun List<Instruction>.getResultTypeAndExpressions(
|
||||
}
|
||||
|
||||
fun instructionToType(instruction: Instruction): KotlinType? {
|
||||
val expression = instructionToExpression(instruction, true)
|
||||
val expression = instructionToExpression(instruction, true) ?: return null
|
||||
|
||||
if (expression == null) return null
|
||||
if (options.inferUnitTypeForUnusedValues && expression.isUsedAsStatement(bindingContext)) return null
|
||||
|
||||
return bindingContext.getType(expression)
|
||||
?: (expression as? KtReferenceExpression)?.let {
|
||||
(bindingContext[BindingContext.REFERENCE_TARGET, it] as? CallableDescriptor)?.getReturnType()
|
||||
(bindingContext[BindingContext.REFERENCE_TARGET, it] as? CallableDescriptor)?.returnType
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +204,7 @@ private fun getCommonNonTrivialSuccessorIfAny(instructions: List<Instruction>):
|
||||
}
|
||||
|
||||
if (instructions.flatMap { it.nextInstructions }.any { !it.accept(singleSuccessorCheckingVisitor) }) return null
|
||||
return singleSuccessorCheckingVisitor.target ?: instructions.firstOrNull()?.owner?.getSinkInstruction()
|
||||
return singleSuccessorCheckingVisitor.target ?: instructions.firstOrNull()?.owner?.sinkInstruction
|
||||
}
|
||||
|
||||
private fun KotlinType.isMeaningful(): Boolean {
|
||||
@@ -228,7 +227,7 @@ private fun ExtractionData.getLocalDeclarationsWithNonLocalUsages(
|
||||
}
|
||||
}
|
||||
}
|
||||
return declarations.sortedBy { it.getTextRange()!!.getStartOffset() }
|
||||
return declarations.sortedBy { it.textRange!!.startOffset }
|
||||
}
|
||||
|
||||
private fun ExtractionData.analyzeControlFlow(
|
||||
@@ -248,7 +247,7 @@ private fun ExtractionData.analyzeControlFlow(
|
||||
val jumpExits = ArrayList<AbstractJumpInstruction>()
|
||||
exitPoints.forEach {
|
||||
val e = (it as? UnconditionalJumpInstruction)?.element
|
||||
val insn =
|
||||
val inst =
|
||||
when {
|
||||
it !is ReturnValueInstruction && it !is ReturnNoValueInstruction && it.owner != pseudocode ->
|
||||
null
|
||||
@@ -258,38 +257,38 @@ private fun ExtractionData.analyzeControlFlow(
|
||||
it
|
||||
}
|
||||
|
||||
when (insn) {
|
||||
when (inst) {
|
||||
is ReturnValueInstruction -> {
|
||||
if (insn.owner == pseudocode) {
|
||||
if (insn.returnExpressionIfAny == null) {
|
||||
defaultExits.add(insn)
|
||||
if (inst.owner == pseudocode) {
|
||||
if (inst.returnExpressionIfAny == null) {
|
||||
defaultExits.add(inst)
|
||||
}
|
||||
else {
|
||||
valuedReturnExits.add(insn)
|
||||
valuedReturnExits.add(inst)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AbstractJumpInstruction -> {
|
||||
val element = insn.element
|
||||
if ((element is KtReturnExpression && insn.owner == pseudocode)
|
||||
val element = inst.element
|
||||
if ((element is KtReturnExpression && inst.owner == pseudocode)
|
||||
|| element is KtBreakExpression
|
||||
|| element is KtContinueExpression) {
|
||||
jumpExits.add(insn)
|
||||
jumpExits.add(inst)
|
||||
}
|
||||
else if (element !is KtThrowExpression) {
|
||||
defaultExits.add(insn)
|
||||
defaultExits.add(inst)
|
||||
}
|
||||
}
|
||||
|
||||
else -> if (insn != null && insn !is LocalFunctionDeclarationInstruction) {
|
||||
defaultExits.add(insn)
|
||||
else -> if (inst != null && inst !is LocalFunctionDeclarationInstruction) {
|
||||
defaultExits.add(inst)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val nonLocallyUsedDeclarations = getLocalDeclarationsWithNonLocalUsages(pseudocode, localInstructions, bindingContext)
|
||||
val (declarationsToCopy, declarationsToReport) = nonLocallyUsedDeclarations.partition { it is KtProperty && it.isLocal() }
|
||||
val (declarationsToCopy, declarationsToReport) = nonLocallyUsedDeclarations.partition { it is KtProperty && it.isLocal }
|
||||
|
||||
val (typeOfDefaultFlow, defaultResultExpressions) = defaultExits.getResultTypeAndExpressions(bindingContext, targetScope, options, module)
|
||||
val (returnValueType, valuedReturnExpressions) = valuedReturnExits.getResultTypeAndExpressions(bindingContext, targetScope, options, module)
|
||||
@@ -298,7 +297,7 @@ private fun ExtractionData.analyzeControlFlow(
|
||||
ControlFlow(Collections.emptyList(), { OutputValueBoxer.AsTuple(it, module) }, declarationsToCopy)
|
||||
|
||||
val defaultReturnType = if (returnValueType.isMeaningful()) returnValueType else typeOfDefaultFlow
|
||||
if (defaultReturnType.isError()) return emptyControlFlow to ErrorMessage.ERROR_TYPES
|
||||
if (defaultReturnType.isError) return emptyControlFlow to ErrorMessage.ERROR_TYPES
|
||||
|
||||
val controlFlow = if (defaultReturnType.isMeaningful()) {
|
||||
emptyControlFlow.copy(outputValues = Collections.singletonList(ExpressionValue(false, defaultResultExpressions, defaultReturnType)))
|
||||
@@ -313,10 +312,10 @@ private fun ExtractionData.analyzeControlFlow(
|
||||
}
|
||||
|
||||
val outParameters =
|
||||
parameters.filter { it.mirrorVarName != null && modifiedVarDescriptors[it.originalDescriptor] != null }.sortedBy { it.nameForRef }
|
||||
parameters.filter { it.mirrorVarName != null && modifiedVarDescriptors.getRaw(it.originalDescriptor) != null }.sortedBy { it.nameForRef }
|
||||
val outDeclarations =
|
||||
declarationsToCopy.filter { modifiedVarDescriptors[bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it]] != null }
|
||||
val modifiedValueCount = outParameters.size() + outDeclarations.size()
|
||||
declarationsToCopy.filter { modifiedVarDescriptors.getRaw(bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it]) != null }
|
||||
val modifiedValueCount = outParameters.size + outDeclarations.size
|
||||
|
||||
val outputValues = ArrayList<OutputValue>()
|
||||
|
||||
@@ -333,7 +332,7 @@ private fun ExtractionData.analyzeControlFlow(
|
||||
|
||||
if (defaultExits.isNotEmpty()) {
|
||||
if (modifiedValueCount != 0) return outputAndExitsError
|
||||
if (valuedReturnExits.size() != 1) return multipleExitsError
|
||||
if (valuedReturnExits.size != 1) return multipleExitsError
|
||||
|
||||
val element = valuedReturnExits.first().element as KtExpression
|
||||
return controlFlow.copy(outputValues = Collections.singletonList(Jump(listOf(element), element, true, module.builtIns))) to null
|
||||
@@ -345,15 +344,15 @@ private fun ExtractionData.analyzeControlFlow(
|
||||
|
||||
outDeclarations.mapTo(outputValues) {
|
||||
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it] as? CallableDescriptor
|
||||
Initializer(it as KtProperty, descriptor?.getReturnType() ?: module.builtIns.defaultParameterType)
|
||||
Initializer(it as KtProperty, descriptor?.returnType ?: module.builtIns.defaultParameterType)
|
||||
}
|
||||
outParameters.mapTo(outputValues) { ParameterUpdate(it, modifiedVarDescriptors[it.originalDescriptor]!!) }
|
||||
outParameters.mapTo(outputValues) { ParameterUpdate(it, modifiedVarDescriptors.getRaw(it.originalDescriptor)!!) }
|
||||
|
||||
if (outputValues.isNotEmpty()) {
|
||||
if (jumpExits.isNotEmpty()) return outputAndExitsError
|
||||
|
||||
val boxerFactory: (List<OutputValue>) -> OutputValueBoxer = when {
|
||||
outputValues.size() > 3 -> {
|
||||
outputValues.size > 3 -> {
|
||||
if (!options.enableListBoxing) {
|
||||
val outValuesStr =
|
||||
(outParameters.map { it.originalDescriptor.renderForMessage() }
|
||||
@@ -370,8 +369,7 @@ private fun ExtractionData.analyzeControlFlow(
|
||||
}
|
||||
|
||||
if (jumpExits.isNotEmpty()) {
|
||||
val jumpTarget = getCommonNonTrivialSuccessorIfAny(jumpExits)
|
||||
if (jumpTarget == null) return multipleExitsError
|
||||
val jumpTarget = getCommonNonTrivialSuccessorIfAny(jumpExits) ?: return multipleExitsError
|
||||
|
||||
val singleExit = getCommonNonTrivialSuccessorIfAny(defaultExits) == jumpTarget
|
||||
val conditional = !singleExit && defaultExits.isNotEmpty()
|
||||
@@ -384,18 +382,18 @@ private fun ExtractionData.analyzeControlFlow(
|
||||
}
|
||||
|
||||
fun ExtractionData.createTemporaryDeclaration(functionText: String): KtNamedDeclaration {
|
||||
val textRange = targetSibling.getTextRange()!!
|
||||
val textRange = targetSibling.textRange!!
|
||||
|
||||
val insertText: String
|
||||
val insertPosition: Int
|
||||
val lookupPosition: Int
|
||||
if (insertBefore) {
|
||||
insertPosition = textRange.getStartOffset()
|
||||
insertPosition = textRange.startOffset
|
||||
lookupPosition = insertPosition
|
||||
insertText = functionText
|
||||
}
|
||||
else {
|
||||
insertPosition = textRange.getEndOffset()
|
||||
insertPosition = textRange.endOffset
|
||||
lookupPosition = insertPosition + 1
|
||||
insertText = "\n$functionText"
|
||||
}
|
||||
@@ -407,14 +405,14 @@ fun ExtractionData.createTemporaryDeclaration(functionText: String): KtNamedDecl
|
||||
}
|
||||
|
||||
private fun ExtractionData.createTemporaryCodeBlock(): KtBlockExpression =
|
||||
(createTemporaryDeclaration("fun() {\n$codeFragmentText\n}\n") as KtNamedFunction).getBodyExpression() as KtBlockExpression
|
||||
(createTemporaryDeclaration("fun() {\n$codeFragmentText\n}\n") as KtNamedFunction).bodyExpression as KtBlockExpression
|
||||
|
||||
private fun KotlinType.collectReferencedTypes(processTypeArguments: Boolean): List<KotlinType> {
|
||||
if (!processTypeArguments) return Collections.singletonList(this)
|
||||
return DFS.dfsFromNode(
|
||||
this,
|
||||
object: Neighbors<KotlinType> {
|
||||
override fun getNeighbors(current: KotlinType): Iterable<KotlinType> = current.getArguments().map { it.getType() }
|
||||
override fun getNeighbors(current: KotlinType): Iterable<KotlinType> = current.arguments.map { it.type }
|
||||
},
|
||||
VisitedWithSet(),
|
||||
object: CollectingNodeHandler<KotlinType, KotlinType, ArrayList<KotlinType>>(ArrayList()) {
|
||||
@@ -426,16 +424,15 @@ private fun KotlinType.collectReferencedTypes(processTypeArguments: Boolean): Li
|
||||
}
|
||||
|
||||
fun KtTypeParameter.collectRelevantConstraints(): List<KtTypeConstraint> {
|
||||
val typeConstraints = getNonStrictParentOfType<KtTypeParameterListOwner>()?.getTypeConstraints()
|
||||
if (typeConstraints == null) return Collections.emptyList()
|
||||
return typeConstraints.filter { it.getSubjectTypeParameterName()?.mainReference?.resolve() == this}
|
||||
val typeConstraints = getNonStrictParentOfType<KtTypeParameterListOwner>()?.typeConstraints ?: return Collections.emptyList()
|
||||
return typeConstraints.filter { it.subjectTypeParameterName?.mainReference?.resolve() == this}
|
||||
}
|
||||
|
||||
fun TypeParameter.collectReferencedTypes(bindingContext: BindingContext): List<KotlinType> {
|
||||
val typeRefs = ArrayList<KtTypeReference>()
|
||||
originalDeclaration.getExtendsBound()?.let { typeRefs.add(it) }
|
||||
originalDeclaration.extendsBound?.let { typeRefs.add(it) }
|
||||
originalConstraints
|
||||
.map { it.getBoundTypeReference() }
|
||||
.map { it.boundTypeReference }
|
||||
.filterNotNullTo(typeRefs)
|
||||
|
||||
return typeRefs
|
||||
@@ -445,7 +442,7 @@ fun TypeParameter.collectReferencedTypes(bindingContext: BindingContext): List<K
|
||||
|
||||
private fun KotlinType.isExtractable(targetScope: LexicalScope?): Boolean {
|
||||
return collectReferencedTypes(true).fold(true) { extractable, typeToCheck ->
|
||||
val parameterTypeDescriptor = typeToCheck.getConstructor().getDeclarationDescriptor() as? TypeParameterDescriptor
|
||||
val parameterTypeDescriptor = typeToCheck.constructor.declarationDescriptor as? TypeParameterDescriptor
|
||||
val typeParameter = parameterTypeDescriptor?.let {
|
||||
DescriptorToSourceUtils.descriptorToDeclaration(it)
|
||||
} as? KtTypeParameter
|
||||
@@ -462,7 +459,7 @@ private fun KotlinType.processTypeIfExtractable(
|
||||
processTypeArguments: Boolean = true
|
||||
): Boolean {
|
||||
return collectReferencedTypes(processTypeArguments).fold(true) { extractable, typeToCheck ->
|
||||
val parameterTypeDescriptor = typeToCheck.getConstructor().getDeclarationDescriptor() as? TypeParameterDescriptor
|
||||
val parameterTypeDescriptor = typeToCheck.constructor.declarationDescriptor as? TypeParameterDescriptor
|
||||
val typeParameter = parameterTypeDescriptor?.let {
|
||||
DescriptorToSourceUtils.descriptorToDeclaration(it)
|
||||
} as? KtTypeParameter
|
||||
@@ -479,7 +476,7 @@ private fun KotlinType.processTypeIfExtractable(
|
||||
options.allowSpecialClassNames && typeToCheck.isSpecial() ->
|
||||
extractable
|
||||
|
||||
typeToCheck.isError() ->
|
||||
typeToCheck.isError ->
|
||||
false
|
||||
|
||||
else -> {
|
||||
@@ -537,7 +534,7 @@ private class MutableParameter(
|
||||
val typePredicate = and(typePredicates)
|
||||
|
||||
val typeSet = if (defaultType.isFlexible()) {
|
||||
val bounds = defaultType.getCapability(javaClass<Flexibility>())!!
|
||||
val bounds = defaultType.getCapability(Flexibility::class.java)!!
|
||||
LinkedHashSet<KotlinType>().apply {
|
||||
if (typePredicate(bounds.upperBound)) add(bounds.upperBound)
|
||||
if (typePredicate(bounds.lowerBound)) add(bounds.lowerBound)
|
||||
@@ -545,7 +542,7 @@ private class MutableParameter(
|
||||
}
|
||||
else linkedSetOf(defaultType)
|
||||
|
||||
val addNullableTypes = defaultType.isNullabilityFlexible() && typeSet.size() > 1
|
||||
val addNullableTypes = defaultType.isNullabilityFlexible() && typeSet.size > 1
|
||||
val superTypes = TypeUtils.getAllSupertypes(defaultType).filter(typePredicate)
|
||||
|
||||
for (superType in superTypes) {
|
||||
@@ -615,28 +612,28 @@ private fun ExtractionData.inferParametersInfo(
|
||||
extractFunctionRef -> {
|
||||
originalDescriptor as FunctionDescriptor
|
||||
builtIns.getFunctionType(Annotations.EMPTY,
|
||||
originalDescriptor.getExtensionReceiverParameter()?.getType(),
|
||||
originalDescriptor.getValueParameters().map { it.getType() },
|
||||
originalDescriptor.getReturnType() ?: builtIns.defaultReturnType)
|
||||
originalDescriptor.extensionReceiverParameter?.type,
|
||||
originalDescriptor.valueParameters.map { it.type },
|
||||
originalDescriptor.returnType ?: builtIns.defaultReturnType)
|
||||
}
|
||||
parameterExpression != null ->
|
||||
(if (useSmartCastsIfPossible) bindingContext[BindingContext.SMARTCAST, parameterExpression] else null)
|
||||
?: bindingContext.getType(parameterExpression)
|
||||
?: (parameterExpression as? KtReferenceExpression)?.let {
|
||||
(bindingContext[BindingContext.REFERENCE_TARGET, it] as? CallableDescriptor)?.getReturnType()
|
||||
(bindingContext[BindingContext.REFERENCE_TARGET, it] as? CallableDescriptor)?.returnType
|
||||
}
|
||||
?: if (receiverToExtract.exists()) receiverToExtract.getType() else null
|
||||
?: if (receiverToExtract.exists()) receiverToExtract.type else null
|
||||
receiverToExtract is ThisReceiver -> {
|
||||
val calleeExpression = resolvedCall!!.getCall().getCalleeExpression()
|
||||
val calleeExpression = resolvedCall!!.call.calleeExpression
|
||||
val typeByDataFlowInfo = if (useSmartCastsIfPossible) {
|
||||
bindingContext[BindingContext.EXPRESSION_TYPE_INFO, calleeExpression]?.dataFlowInfo?.let { dataFlowInfo ->
|
||||
val possibleTypes = dataFlowInfo.getPossibleTypes(DataFlowValueFactory.createDataFlowValue(receiverToExtract))
|
||||
if (possibleTypes.isNotEmpty()) CommonSupertypes.commonSupertype(possibleTypes) else null
|
||||
}
|
||||
} else null
|
||||
typeByDataFlowInfo ?: receiverToExtract.getType()
|
||||
typeByDataFlowInfo ?: receiverToExtract.type
|
||||
}
|
||||
receiverToExtract.exists() -> receiverToExtract.getType()
|
||||
receiverToExtract.exists() -> receiverToExtract.type
|
||||
else -> null
|
||||
} ?: builtIns.defaultParameterType
|
||||
}
|
||||
@@ -645,23 +642,23 @@ private fun ExtractionData.inferParametersInfo(
|
||||
val (originalRef, originalDeclaration, originalDescriptor, resolvedCall) = refInfo.resolveResult
|
||||
val ref = refInfo.refExpr
|
||||
|
||||
val selector = (ref.getParent() as? KtCallExpression) ?: ref
|
||||
val superExpr = (selector.getParent() as? KtQualifiedExpression)?.getReceiverExpression() as? KtSuperExpression
|
||||
val selector = (ref.parent as? KtCallExpression) ?: ref
|
||||
val superExpr = (selector.parent as? KtQualifiedExpression)?.receiverExpression as? KtSuperExpression
|
||||
if (superExpr != null) {
|
||||
info.errorMessage = ErrorMessage.SUPER_CALL
|
||||
return info
|
||||
}
|
||||
|
||||
val extensionReceiver = resolvedCall?.getExtensionReceiver()
|
||||
val extensionReceiver = resolvedCall?.extensionReceiver
|
||||
val receiverToExtract = when {
|
||||
extensionReceiver == ReceiverValue.NO_RECEIVER,
|
||||
isSynthesizedInvoke(originalDescriptor) -> resolvedCall?.getDispatchReceiver()
|
||||
isSynthesizedInvoke(originalDescriptor) -> resolvedCall?.dispatchReceiver
|
||||
else -> extensionReceiver
|
||||
} ?: ReceiverValue.NO_RECEIVER
|
||||
|
||||
val thisDescriptor = (receiverToExtract as? ThisReceiver)?.getDeclarationDescriptor()
|
||||
val thisDescriptor = (receiverToExtract as? ThisReceiver)?.declarationDescriptor
|
||||
val hasThisReceiver = thisDescriptor != null
|
||||
val thisExpr = ref.getParent() as? KtThisExpression
|
||||
val thisExpr = ref.parent as? KtThisExpression
|
||||
|
||||
if (hasThisReceiver
|
||||
&& DescriptorToSourceUtilsIde.getAllDeclarations(project, thisDescriptor!!).all { it.isInsideOf(originalElements) }) {
|
||||
@@ -671,22 +668,22 @@ private fun ExtractionData.inferParametersInfo(
|
||||
val referencedClassifierDescriptor: ClassifierDescriptor? = (thisDescriptor ?: originalDescriptor).let {
|
||||
when (it) {
|
||||
is ClassDescriptor ->
|
||||
when(it.getKind()) {
|
||||
ClassKind.OBJECT, ClassKind.ENUM_CLASS -> it as ClassifierDescriptor
|
||||
ClassKind.ENUM_ENTRY -> it.getContainingDeclaration() as? ClassDescriptor
|
||||
else -> if (ref.getNonStrictParentOfType<KtTypeReference>() != null) it as ClassifierDescriptor else null
|
||||
when(it.kind) {
|
||||
ClassKind.OBJECT, ClassKind.ENUM_CLASS -> it
|
||||
ClassKind.ENUM_ENTRY -> it.containingDeclaration as? ClassDescriptor
|
||||
else -> if (ref.getNonStrictParentOfType<KtTypeReference>() != null) it else null
|
||||
}
|
||||
|
||||
is TypeParameterDescriptor -> it as ClassifierDescriptor
|
||||
is TypeParameterDescriptor -> it
|
||||
|
||||
is ConstructorDescriptor -> it.getContainingDeclaration()
|
||||
is ConstructorDescriptor -> it.containingDeclaration
|
||||
|
||||
else -> null
|
||||
}
|
||||
} as? ClassifierDescriptor
|
||||
}
|
||||
|
||||
if (referencedClassifierDescriptor != null) {
|
||||
if (!referencedClassifierDescriptor.getDefaultType().processTypeIfExtractable(
|
||||
if (!referencedClassifierDescriptor.defaultType.processTypeIfExtractable(
|
||||
info.typeParameters, info.nonDenotableTypes, options, targetScope, referencedClassifierDescriptor is TypeParameterDescriptor
|
||||
)) continue
|
||||
|
||||
@@ -703,8 +700,8 @@ private fun ExtractionData.inferParametersInfo(
|
||||
|
||||
val extractFunctionRef =
|
||||
options.captureLocalFunctions
|
||||
&& originalRef.getReferencedName() == originalDescriptor.getName().asString() // to forbid calls by convention
|
||||
&& originalDeclaration is KtNamedFunction && originalDeclaration.isLocal()
|
||||
&& originalRef.getReferencedName() == originalDescriptor.name.asString() // to forbid calls by convention
|
||||
&& originalDeclaration is KtNamedFunction && originalDeclaration.isLocal
|
||||
&& targetScope.findFunction(originalDescriptor.name, NoLookupLocation.FROM_IDE) { it == originalDescriptor } == null
|
||||
|
||||
val descriptorToExtract = (if (extractThis) thisDescriptor else null) ?: originalDescriptor
|
||||
@@ -713,12 +710,12 @@ private fun ExtractionData.inferParametersInfo(
|
||||
if (extractParameter) {
|
||||
val parameterExpression = when {
|
||||
receiverToExtract is ExpressionReceiver -> {
|
||||
val receiverExpression = receiverToExtract.getExpression()
|
||||
val receiverExpression = receiverToExtract.expression
|
||||
// If p.q has a smart-cast, then extract entire qualified expression
|
||||
if (refInfo.smartCast != null) receiverExpression.getParent() as KtExpression else receiverExpression
|
||||
if (refInfo.smartCast != null) receiverExpression.parent as KtExpression else receiverExpression
|
||||
}
|
||||
receiverToExtract.exists() && refInfo.smartCast == null -> null
|
||||
else -> (originalRef.getParent() as? KtThisExpression) ?: originalRef
|
||||
else -> (originalRef.parent as? KtThisExpression) ?: originalRef
|
||||
}
|
||||
|
||||
val parameterType = suggestParameterType(extractFunctionRef, originalDescriptor, parameterExpression, receiverToExtract, resolvedCall, true)
|
||||
@@ -726,7 +723,7 @@ private fun ExtractionData.inferParametersInfo(
|
||||
val parameter = extractedDescriptorToParameter.getOrPut(descriptorToExtract) {
|
||||
var argumentText =
|
||||
if (hasThisReceiver && extractThis) {
|
||||
val label = if (descriptorToExtract is ClassDescriptor) "@${descriptorToExtract.getName().asString()}" else ""
|
||||
val label = if (descriptorToExtract is ClassDescriptor) "@${descriptorToExtract.name.asString()}" else ""
|
||||
"this$label"
|
||||
}
|
||||
else {
|
||||
@@ -736,13 +733,13 @@ private fun ExtractionData.inferParametersInfo(
|
||||
val nameElementType = nameElement.node.elementType
|
||||
(nameElementType as? KtToken)?.let {
|
||||
OperatorConventions.getNameForOperationSymbol(it)?.asString()
|
||||
} ?: nameElement.getText()
|
||||
} ?: nameElement.text
|
||||
}
|
||||
else argumentExpr.getText()
|
||||
else argumentExpr.text
|
||||
?: throw AssertionError("reference shouldn't be empty: code fragment = $codeFragmentText")
|
||||
}
|
||||
if (extractFunctionRef) {
|
||||
val receiverTypeText = (originalDeclaration as KtCallableDeclaration).getReceiverTypeReference()?.getText() ?: ""
|
||||
val receiverTypeText = (originalDeclaration as KtCallableDeclaration).receiverTypeReference?.text ?: ""
|
||||
argumentText = "$receiverTypeText::$argumentText"
|
||||
}
|
||||
|
||||
@@ -752,7 +749,7 @@ private fun ExtractionData.inferParametersInfo(
|
||||
}
|
||||
|
||||
if (!extractThis) {
|
||||
parameter.currentName = originalDeclaration.getNameIdentifier()?.getText()
|
||||
parameter.currentName = originalDeclaration.nameIdentifier?.text
|
||||
}
|
||||
|
||||
parameter.refCount++
|
||||
@@ -761,9 +758,9 @@ private fun ExtractionData.inferParametersInfo(
|
||||
parameter.addDefaultType(parameterType)
|
||||
|
||||
if (extractThis && thisExpr == null) {
|
||||
val callElement = resolvedCall!!.getCall().getCallElement()
|
||||
val callElement = resolvedCall!!.call.callElement
|
||||
val instruction = pseudocode.getElementValue(callElement)?.createdAt as? InstructionWithReceivers
|
||||
val receiverValue = instruction?.receiverValues?.entrySet()?.singleOrNull { it.getValue() == receiverToExtract }?.getKey()
|
||||
val receiverValue = instruction?.receiverValues?.entries?.singleOrNull { it.value == receiverToExtract }?.key
|
||||
if (receiverValue != null) {
|
||||
parameter.addTypePredicate(getExpectedTypePredicate(receiverValue, bindingContext, targetScope.ownerDescriptor.builtIns))
|
||||
}
|
||||
@@ -798,7 +795,7 @@ private fun ExtractionData.inferParametersInfo(
|
||||
if (currentName == null) {
|
||||
currentName = KotlinNameSuggester.suggestNamesByType(getParameterType(options.allowSpecialClassNames), varNameValidator, "p").first()
|
||||
}
|
||||
mirrorVarName = if (descriptorToExtract in modifiedVarDescriptors) KotlinNameSuggester.suggestNameByName(name, varNameValidator) else null
|
||||
mirrorVarName = if (modifiedVarDescriptors.containsRaw(descriptorToExtract)) KotlinNameSuggester.suggestNameByName(name, varNameValidator) else null
|
||||
info.parameters.add(this)
|
||||
}
|
||||
}
|
||||
@@ -849,7 +846,7 @@ private fun ExtractionData.getLocalInstructions(pseudocode: Pseudocode): List<In
|
||||
}
|
||||
|
||||
fun ExtractionData.isVisibilityApplicable(): Boolean {
|
||||
return when (targetSibling.getParent()) {
|
||||
return when (targetSibling.parent) {
|
||||
is KtClassBody, is KtFile -> true
|
||||
else -> false
|
||||
}
|
||||
@@ -880,7 +877,7 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
|
||||
val modifiedVarDescriptorsWithExpressions = localInstructions.getModifiedVarDescriptors(bindingContext)
|
||||
|
||||
val targetScope = targetSibling.getResolutionScope(bindingContext, commonParent.getResolutionFacade())
|
||||
val paramsInfo = inferParametersInfo(commonParent, pseudocode, bindingContext, targetScope, modifiedVarDescriptorsWithExpressions.keySet())
|
||||
val paramsInfo = inferParametersInfo(commonParent, pseudocode, bindingContext, targetScope, modifiedVarDescriptorsWithExpressions.keys)
|
||||
if (paramsInfo.errorMessage != null) {
|
||||
return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(paramsInfo.errorMessage!!))
|
||||
}
|
||||
@@ -888,7 +885,7 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
|
||||
val messages = ArrayList<ErrorMessage>()
|
||||
|
||||
val modifiedVarDescriptorsForControlFlow = HashMap(modifiedVarDescriptorsWithExpressions)
|
||||
modifiedVarDescriptorsForControlFlow.keySet().retainAll(localInstructions.getVarDescriptorsAccessedAfterwards(bindingContext))
|
||||
modifiedVarDescriptorsForControlFlow.keys.retainAll(localInstructions.getVarDescriptorsAccessedAfterwards(bindingContext))
|
||||
val (controlFlow, controlFlowMessage) =
|
||||
analyzeControlFlow(
|
||||
localInstructions,
|
||||
@@ -927,7 +924,7 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
|
||||
val adjustedParameters = paramsInfo.parameters.filterTo(HashSet<Parameter>()) { it.refCount > 0 }
|
||||
|
||||
val receiverCandidates = adjustedParameters.filterTo(HashSet<Parameter>()) { it.receiverCandidate }
|
||||
val receiverParameter = if (receiverCandidates.size() == 1) receiverCandidates.first() else null
|
||||
val receiverParameter = if (receiverCandidates.size == 1) receiverCandidates.first() else null
|
||||
receiverParameter?.let { adjustedParameters.remove(it) }
|
||||
|
||||
return AnalysisResult(
|
||||
@@ -938,7 +935,7 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
|
||||
getDefaultVisibility(),
|
||||
adjustedParameters.sortedBy { it.name },
|
||||
receiverParameter,
|
||||
paramsInfo.typeParameters.sortedBy { it.originalDeclaration.getName()!! },
|
||||
paramsInfo.typeParameters.sortedBy { it.originalDeclaration.name!! },
|
||||
paramsInfo.replacementMap,
|
||||
if (messages.isEmpty()) controlFlow else controlFlow.toDefault(),
|
||||
returnType
|
||||
@@ -953,8 +950,8 @@ private fun ExtractionData.suggestFunctionNames(returnType: KotlinType): List<St
|
||||
|
||||
val validator =
|
||||
NewDeclarationNameValidator(
|
||||
targetSibling.getParent(),
|
||||
if (targetSibling is KtClassInitializer) targetSibling.getParent() else targetSibling,
|
||||
targetSibling.parent,
|
||||
if (targetSibling is KtClassInitializer) targetSibling.parent else targetSibling,
|
||||
if (options.extractAsProperty) NewDeclarationNameValidator.Target.VARIABLES else NewDeclarationNameValidator.Target.FUNCTIONS_AND_CLASSES
|
||||
)
|
||||
if (!returnType.isDefault()) {
|
||||
@@ -963,8 +960,8 @@ private fun ExtractionData.suggestFunctionNames(returnType: KotlinType): List<St
|
||||
|
||||
getExpressions().singleOrNull()?.let { expr ->
|
||||
val property = expr.getStrictParentOfType<KtProperty>()
|
||||
if (property?.getInitializer() == expr) {
|
||||
property?.getName()?.let { functionNames.add(KotlinNameSuggester.suggestNameByName("get" + it.capitalize(), validator)) }
|
||||
if (property?.initializer == expr) {
|
||||
property?.name?.let { functionNames.add(KotlinNameSuggester.suggestNameByName("get" + it.capitalize(), validator)) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -973,16 +970,16 @@ private fun ExtractionData.suggestFunctionNames(returnType: KotlinType): List<St
|
||||
|
||||
internal fun KtNamedDeclaration.getGeneratedBody() =
|
||||
when (this) {
|
||||
is KtNamedFunction -> getBodyExpression()
|
||||
is KtNamedFunction -> bodyExpression
|
||||
else -> {
|
||||
val property = this as KtProperty
|
||||
|
||||
property.getGetter()?.getBodyExpression()?.let { return it }
|
||||
property.getInitializer()?.let { return it }
|
||||
property.getter?.bodyExpression?.let { return it }
|
||||
property.initializer?.let { return it }
|
||||
// We assume lazy property here with delegate expression 'by Delegates.lazy { body }'
|
||||
property.getDelegateExpression()?.let {
|
||||
val call = it.getCalleeExpressionIfAny()?.getParent() as? KtCallExpression
|
||||
call?.getFunctionLiteralArguments()?.singleOrNull()?.getFunctionLiteral()?.getBodyExpression()
|
||||
property.delegateExpression?.let {
|
||||
val call = it.getCalleeExpressionIfAny()?.parent as? KtCallExpression
|
||||
call?.functionLiteralArguments?.singleOrNull()?.getFunctionLiteral()?.bodyExpression
|
||||
}
|
||||
}
|
||||
} ?: throw AssertionError("Couldn't get block body for this declaration: ${getElementTextWithContext()}")
|
||||
@@ -1000,8 +997,8 @@ fun ExtractableCodeDescriptor.validate(): ExtractableCodeDescriptorWithConflicts
|
||||
ExtractionGeneratorOptions(inTempFile = true, allowExpressionBody = false)
|
||||
).generateDeclaration()
|
||||
|
||||
val valueParameterList = (result.declaration as? KtNamedFunction)?.getValueParameterList()
|
||||
val typeParameterList = (result.declaration as? KtNamedFunction)?.getTypeParameterList()
|
||||
val valueParameterList = (result.declaration as? KtNamedFunction)?.valueParameterList
|
||||
val typeParameterList = (result.declaration as? KtNamedFunction)?.typeParameterList
|
||||
val body = result.declaration.getGeneratedBody()
|
||||
val bindingContext = body.analyzeFully()
|
||||
|
||||
@@ -1013,19 +1010,19 @@ fun ExtractableCodeDescriptor.validate(): ExtractableCodeDescriptorWithConflicts
|
||||
(it as? KtThisExpression)?.instanceReference ?: it as? KtSimpleNameExpression
|
||||
} ?: continue
|
||||
|
||||
if (currentRefExpr.getParent() is KtThisExpression) continue
|
||||
if (currentRefExpr.parent is KtThisExpression) continue
|
||||
|
||||
val diagnostics = bindingContext.getDiagnostics().forElement(currentRefExpr)
|
||||
val diagnostics = bindingContext.diagnostics.forElement(currentRefExpr)
|
||||
|
||||
val currentDescriptor = bindingContext[BindingContext.REFERENCE_TARGET, currentRefExpr]
|
||||
val currentTarget =
|
||||
currentDescriptor?.let { DescriptorToSourceUtilsIde.getAnyDeclaration(extractionData.project, it) } as? PsiNamedElement
|
||||
if (currentTarget is KtParameter && currentTarget.getParent() == valueParameterList) continue
|
||||
if (currentTarget is KtTypeParameter && currentTarget.getParent() == typeParameterList) continue
|
||||
if (currentTarget is KtParameter && currentTarget.parent == valueParameterList) continue
|
||||
if (currentTarget is KtTypeParameter && currentTarget.parent == typeParameterList) continue
|
||||
if (currentDescriptor is LocalVariableDescriptor
|
||||
&& parameters.any { it.mirrorVarName == currentDescriptor.getName().asString() }) continue
|
||||
&& parameters.any { it.mirrorVarName == currentDescriptor.name.asString() }) continue
|
||||
|
||||
if (diagnostics.any { it.getFactory() in Errors.UNRESOLVED_REFERENCE_DIAGNOSTICS }
|
||||
if (diagnostics.any { it.factory in Errors.UNRESOLVED_REFERENCE_DIAGNOSTICS }
|
||||
|| (currentDescriptor != null
|
||||
&& !ErrorUtils.isError(currentDescriptor)
|
||||
&& !compareDescriptors(extractionData.project, currentDescriptor, resolveResult.descriptor))) {
|
||||
@@ -1036,8 +1033,8 @@ fun ExtractableCodeDescriptor.validate(): ExtractableCodeDescriptorWithConflicts
|
||||
continue
|
||||
}
|
||||
|
||||
diagnostics.firstOrNull { it.getFactory() in Errors.INVISIBLE_REFERENCE_DIAGNOSTICS }?.let {
|
||||
val message = when (it.getFactory()) {
|
||||
diagnostics.firstOrNull { it.factory in Errors.INVISIBLE_REFERENCE_DIAGNOSTICS }?.let {
|
||||
val message = when (it.factory) {
|
||||
Errors.INVISIBLE_SETTER ->
|
||||
getDeclarationMessage(resolveResult.declaration, "setter.of.0.will.become.invisible.after.extraction", false)
|
||||
else ->
|
||||
@@ -1051,10 +1048,10 @@ fun ExtractableCodeDescriptor.validate(): ExtractableCodeDescriptorWithConflicts
|
||||
result.declaration.accept(
|
||||
object : KtTreeVisitorVoid() {
|
||||
override fun visitUserType(userType: KtUserType) {
|
||||
val refExpr = userType.getReferenceExpression() ?: return
|
||||
val refExpr = userType.referenceExpression ?: return
|
||||
val declaration = refExpr.mainReference.resolve() as? PsiNamedElement ?: return
|
||||
val diagnostics = bindingContext.getDiagnostics().forElement(refExpr)
|
||||
diagnostics.firstOrNull { it.getFactory() == Errors.INVISIBLE_REFERENCE }?.let {
|
||||
val diagnostics = bindingContext.diagnostics.forElement(refExpr)
|
||||
diagnostics.firstOrNull { it.factory == Errors.INVISIBLE_REFERENCE }?.let {
|
||||
conflicts.putValue(declaration, getDeclarationMessage(declaration, "0.will.become.invisible.after.extraction"))
|
||||
}
|
||||
}
|
||||
@@ -1072,4 +1069,4 @@ fun ExtractableCodeDescriptor.validate(): ExtractableCodeDescriptorWithConflicts
|
||||
return ExtractableCodeDescriptorWithConflicts(this, conflicts)
|
||||
}
|
||||
|
||||
private val LOG = Logger.getInstance(javaClass<ExtractionEngine>())
|
||||
private val LOG = Logger.getInstance(ExtractionEngine::class.java)
|
||||
|
||||
+56
-55
@@ -98,14 +98,14 @@ fun ExtractionGeneratorConfiguration.getDeclarationText(
|
||||
}
|
||||
|
||||
with(descriptor.returnType) {
|
||||
if (isDefault() || isError() || extractionTarget == ExtractionTarget.PROPERTY_WITH_INITIALIZER) {
|
||||
if (isDefault() || isError || extractionTarget == ExtractionTarget.PROPERTY_WITH_INITIALIZER) {
|
||||
builder.noReturnType()
|
||||
} else {
|
||||
builder.returnType(typeAsString())
|
||||
}
|
||||
}
|
||||
|
||||
builder.typeConstraints(descriptor.typeParameters.flatMap { it.originalConstraints }.map { it.getText()!! })
|
||||
builder.typeConstraints(descriptor.typeParameters.flatMap { it.originalConstraints }.map { it.text!! })
|
||||
|
||||
if (withBody) {
|
||||
val bodyText = descriptor.extractionData.codeFragmentText
|
||||
@@ -130,13 +130,13 @@ fun KotlinType.isSpecial(): Boolean {
|
||||
fun createNameCounterpartMap(from: KtElement, to: KtElement): Map<KtSimpleNameExpression, KtSimpleNameExpression> {
|
||||
val map = HashMap<KtSimpleNameExpression, KtSimpleNameExpression>()
|
||||
|
||||
val fromOffset = from.getTextRange()!!.getStartOffset()
|
||||
val fromOffset = from.textRange!!.startOffset
|
||||
from.accept(
|
||||
object : KtTreeVisitorVoid() {
|
||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
||||
val offset = expression.getTextRange()!!.getStartOffset() - fromOffset
|
||||
val offset = expression.textRange!!.startOffset - fromOffset
|
||||
val newExpression = to.findElementAt(offset)?.getNonStrictParentOfType<KtSimpleNameExpression>()
|
||||
assert(newExpression != null) { "Couldn't find expression at $offset in '${to.getText()}'" }
|
||||
assert(newExpression != null) { "Couldn't find expression at $offset in '${to.text}'" }
|
||||
|
||||
map[expression] = newExpression!!
|
||||
}
|
||||
@@ -154,7 +154,7 @@ class DuplicateInfo(
|
||||
|
||||
fun ExtractableCodeDescriptor.findDuplicates(): List<DuplicateInfo> {
|
||||
fun processWeakMatch(match: Match, newControlFlow: ControlFlow): Boolean {
|
||||
val valueCount = controlFlow.outputValues.size()
|
||||
val valueCount = controlFlow.outputValues.size
|
||||
|
||||
val weakMatches = HashMap((match.result as WeaklyMatched).weakMatches)
|
||||
val currentValuesToNew = HashMap<OutputValue, OutputValue>()
|
||||
@@ -163,7 +163,7 @@ fun ExtractableCodeDescriptor.findDuplicates(): List<DuplicateInfo> {
|
||||
if ((currentValue is Jump) != (newValue is Jump)) return false
|
||||
if (currentValue.originalExpressions.zip(newValue.originalExpressions).all { weakMatches[it.first] == it.second }) {
|
||||
currentValuesToNew[currentValue] = newValue
|
||||
weakMatches.keySet().removeAll(currentValue.originalExpressions)
|
||||
weakMatches.keys.removeAll(currentValue.originalExpressions)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -180,7 +180,7 @@ fun ExtractableCodeDescriptor.findDuplicates(): List<DuplicateInfo> {
|
||||
}
|
||||
}
|
||||
|
||||
return currentValuesToNew.size() == valueCount && weakMatches.isEmpty()
|
||||
return currentValuesToNew.size == valueCount && weakMatches.isEmpty()
|
||||
}
|
||||
|
||||
fun getControlFlowIfMatched(match: Match): ControlFlow? {
|
||||
@@ -189,7 +189,7 @@ fun ExtractableCodeDescriptor.findDuplicates(): List<DuplicateInfo> {
|
||||
|
||||
val newControlFlow = analysisResult.descriptor!!.controlFlow
|
||||
if (newControlFlow.outputValues.isEmpty()) return newControlFlow
|
||||
if (controlFlow.outputValues.size() != newControlFlow.outputValues.size()) return null
|
||||
if (controlFlow.outputValues.size != newControlFlow.outputValues.size) return null
|
||||
|
||||
val matched = when (match.result) {
|
||||
is StronglyMatched -> true
|
||||
@@ -213,14 +213,14 @@ fun ExtractableCodeDescriptor.findDuplicates(): List<DuplicateInfo> {
|
||||
.filter { !(it.range.getTextRange() intersects originalTextRange) }
|
||||
.map { match ->
|
||||
val controlFlow = getControlFlowIfMatched(match)
|
||||
controlFlow?.let { DuplicateInfo(match.range, it, unifierParameters.map { match.result.substitution[it]!!.getText()!! }) }
|
||||
controlFlow?.let { DuplicateInfo(match.range, it, unifierParameters.map { match.result.substitution[it]!!.text!! }) }
|
||||
}
|
||||
.filterNotNull()
|
||||
.toList()
|
||||
}
|
||||
|
||||
private fun ExtractableCodeDescriptor.getOccurrenceContainer(): PsiElement? {
|
||||
return extractionData.duplicateContainer ?: extractionData.targetSibling.getParent()
|
||||
return extractionData.duplicateContainer ?: extractionData.targetSibling.parent
|
||||
}
|
||||
|
||||
private fun makeCall(
|
||||
@@ -256,16 +256,16 @@ private fun makeCall(
|
||||
if (rangeToReplace !is KotlinPsiRange.ListRange) return
|
||||
|
||||
val anchor = rangeToReplace.startElement
|
||||
val anchorParent = anchor.getParent()!!
|
||||
val anchorParent = anchor.parent!!
|
||||
|
||||
anchor.getNextSibling()?.let { from ->
|
||||
anchor.nextSibling?.let { from ->
|
||||
val to = rangeToReplace.endElement
|
||||
if (to != anchor) {
|
||||
anchorParent.deleteChildRange(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
val calleeName = declaration.getName()
|
||||
val calleeName = declaration.name
|
||||
val callText = when (declaration) {
|
||||
is KtNamedFunction -> {
|
||||
val argumentsText = arguments.joinToString(separator = ", ", prefix = "(", postfix = ")")
|
||||
@@ -278,22 +278,22 @@ private fun makeCall(
|
||||
else -> calleeName
|
||||
}
|
||||
|
||||
val anchorInBlock = sequence(anchor) { it.getParent() }.firstOrNull { it.getParent() is KtBlockExpression }
|
||||
val block = (anchorInBlock?.getParent() as? KtBlockExpression) ?: anchorParent
|
||||
val anchorInBlock = sequence(anchor) { it.parent }.firstOrNull { it.parent is KtBlockExpression }
|
||||
val block = (anchorInBlock?.parent as? KtBlockExpression) ?: anchorParent
|
||||
|
||||
val psiFactory = KtPsiFactory(anchor.getProject())
|
||||
val psiFactory = KtPsiFactory(anchor.project)
|
||||
val newLine = psiFactory.createNewLine()
|
||||
|
||||
if (controlFlow.outputValueBoxer is AsTuple && controlFlow.outputValues.size() > 1 && controlFlow.outputValues.all { it is Initializer }) {
|
||||
if (controlFlow.outputValueBoxer is AsTuple && controlFlow.outputValues.size > 1 && controlFlow.outputValues.all { it is Initializer }) {
|
||||
val declarationsToMerge = controlFlow.outputValues.map { (it as Initializer).initializedDeclaration }
|
||||
val isVar = declarationsToMerge.first().isVar()
|
||||
if (declarationsToMerge.all { it.isVar() == isVar }) {
|
||||
val isVar = declarationsToMerge.first().isVar
|
||||
if (declarationsToMerge.all { it.isVar == isVar }) {
|
||||
controlFlow.declarationsToCopy.subtract(declarationsToMerge).forEach {
|
||||
block.addBefore(psiFactory.createDeclaration<KtDeclaration>(it.getText()!!), anchorInBlock) as KtDeclaration
|
||||
block.addBefore(psiFactory.createDeclaration<KtDeclaration>(it.text!!), anchorInBlock) as KtDeclaration
|
||||
block.addBefore(newLine, anchorInBlock)
|
||||
}
|
||||
|
||||
val entries = declarationsToMerge.map { p -> p.getName() + (p.getTypeReference()?.let { ": ${it.getText()}" } ?: "") }
|
||||
val entries = declarationsToMerge.map { p -> p.name + (p.typeReference?.let { ": ${it.text}" } ?: "") }
|
||||
anchorInBlock?.replace(
|
||||
psiFactory.createDeclaration("${if (isVar) "var" else "val"} (${entries.joinToString()}) = $callText")
|
||||
)
|
||||
@@ -302,7 +302,7 @@ private fun makeCall(
|
||||
}
|
||||
}
|
||||
|
||||
val inlinableCall = controlFlow.outputValues.size() <= 1
|
||||
val inlinableCall = controlFlow.outputValues.size <= 1
|
||||
val unboxingExpressions =
|
||||
if (inlinableCall) {
|
||||
controlFlow.outputValueBoxer.getUnboxingExpressions(callText!!)
|
||||
@@ -317,7 +317,7 @@ private fun makeCall(
|
||||
|
||||
val copiedDeclarations = HashMap<KtDeclaration, KtDeclaration>()
|
||||
for (decl in controlFlow.declarationsToCopy) {
|
||||
val declCopy = psiFactory.createDeclaration<KtDeclaration>(decl.getText()!!)
|
||||
val declCopy = psiFactory.createDeclaration<KtDeclaration>(decl.text!!)
|
||||
copiedDeclarations[decl] = block.addBefore(declCopy, anchorInBlock) as KtDeclaration
|
||||
block.addBefore(newLine, anchorInBlock)
|
||||
}
|
||||
@@ -332,7 +332,7 @@ private fun makeCall(
|
||||
is OutputValue.ExpressionValue -> {
|
||||
val exprText = if (outputValue.callSiteReturn) {
|
||||
val firstReturn = outputValue.originalExpressions.filterIsInstance<KtReturnExpression>().firstOrNull()
|
||||
val label = firstReturn?.getTargetLabel()?.getText() ?: ""
|
||||
val label = firstReturn?.getTargetLabel()?.text ?: ""
|
||||
"return$label $callText"
|
||||
}
|
||||
else {
|
||||
@@ -352,14 +352,14 @@ private fun makeCall(
|
||||
}
|
||||
else if (outputValue.conditional) {
|
||||
Collections.singletonList(
|
||||
psiFactory.createExpression("if ($callText) ${outputValue.elementToInsertAfterCall.getText()}")
|
||||
psiFactory.createExpression("if ($callText) ${outputValue.elementToInsertAfterCall.text}")
|
||||
)
|
||||
}
|
||||
else {
|
||||
listOf(
|
||||
psiFactory.createExpression(callText),
|
||||
newLine,
|
||||
psiFactory.createExpression(outputValue.elementToInsertAfterCall.getText()!!)
|
||||
psiFactory.createExpression(outputValue.elementToInsertAfterCall.text!!)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -396,7 +396,7 @@ private fun makeCall(
|
||||
insertCall(anchor, wrapCall(it, unboxingExpressions[it]!!).first() as KtExpression)
|
||||
}
|
||||
|
||||
if (anchor.isValid()) {
|
||||
if (anchor.isValid) {
|
||||
anchor.delete()
|
||||
}
|
||||
}
|
||||
@@ -422,10 +422,10 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
|
||||
return descriptor.controlFlow.outputValues
|
||||
.map {
|
||||
when (it) {
|
||||
is ExpressionValue -> resultExpression?.getText()
|
||||
is ExpressionValue -> resultExpression?.text
|
||||
is Jump -> if (it.conditional) "false" else null
|
||||
is ParameterUpdate -> it.parameter.nameForRef
|
||||
is Initializer -> it.initializedDeclaration.getName()
|
||||
is Initializer -> it.initializedDeclaration.name
|
||||
else -> throw IllegalArgumentException("Unknown output value: $it")
|
||||
}
|
||||
}
|
||||
@@ -438,19 +438,20 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
|
||||
expressionToUnifyWith: KtExpression?
|
||||
) {
|
||||
val currentResultExpression =
|
||||
if (originalExpression is KtReturnExpression) originalExpression.getReturnedExpression() else originalExpression
|
||||
if (currentResultExpression == null) return
|
||||
(if (originalExpression is KtReturnExpression) originalExpression.returnedExpression else originalExpression) ?: return
|
||||
|
||||
val newResultExpression = descriptor.controlFlow.defaultOutputValue?.let {
|
||||
val boxedExpression = originalExpression.replaced(replacingExpression).getReturnedExpression()!!
|
||||
val boxedExpression = originalExpression.replaced(replacingExpression).returnedExpression!!
|
||||
descriptor.controlFlow.outputValueBoxer.extractExpressionByValue(boxedExpression, it)
|
||||
}
|
||||
|
||||
@Suppress
|
||||
if (newResultExpression == null) {
|
||||
throw AssertionError("Can' replace '${originalExpression.getText()}' with '${replacingExpression.getText()}'")
|
||||
throw AssertionError("Can' replace '${originalExpression.text}' with '${replacingExpression.text}'")
|
||||
}
|
||||
|
||||
val counterpartMap = createNameCounterpartMap(currentResultExpression, expressionToUnifyWith ?: newResultExpression)
|
||||
nameByOffset.entrySet().forEach { e -> counterpartMap[e.getValue()]?.let { e.setValue(it) } }
|
||||
nameByOffset.entries.forEach { e -> counterpartMap.getRaw(e.value)?.let { e.setValue(it) } }
|
||||
}
|
||||
|
||||
fun getCounterparts<T : KtExpression>(originalExpressions: Collection<T>,
|
||||
@@ -458,9 +459,9 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
|
||||
bodyOffset: Int,
|
||||
file: PsiFile): List<T> {
|
||||
return originalExpressions.map { originalExpression ->
|
||||
val offsetInBody = originalExpression.getTextRange()!!.getStartOffset() - descriptor.extractionData.originalStartOffset!!
|
||||
val offsetInBody = originalExpression.textRange!!.startOffset - descriptor.extractionData.originalStartOffset!!
|
||||
file.findElementAt(bodyOffset + offsetInBody)?.getNonStrictParentOfType(originalExpression.javaClass)
|
||||
?: throw AssertionError("Couldn't find expression at $offsetInBody in '${body.getText()}'")
|
||||
?: throw AssertionError("Couldn't find expression at $offsetInBody in '${body.text}'")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,15 +472,15 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
|
||||
val originalOffsetByExpr = LinkedHashMap<KtElement, Int>()
|
||||
|
||||
val bodyOffset = body.getBlockContentOffset()
|
||||
val file = body.getContainingFile()!!
|
||||
val file = body.containingFile!!
|
||||
|
||||
/*
|
||||
* Sort by descending position so that internals of value/type arguments in calls and qualified types are replaced
|
||||
* before calls/types themselves
|
||||
*/
|
||||
for ((offsetInBody, resolveResult) in descriptor.extractionData.refOffsetToDeclaration.entrySet().sortedByDescending { it.key }) {
|
||||
for ((offsetInBody, resolveResult) in descriptor.extractionData.refOffsetToDeclaration.entries.sortedByDescending { it.key }) {
|
||||
val expr = file.findElementAt(bodyOffset + offsetInBody)?.getNonStrictParentOfType<KtSimpleNameExpression>()
|
||||
assert(expr != null) { "Couldn't find expression at $offsetInBody in '${body.getText()}'" }
|
||||
assert(expr != null) { "Couldn't find expression at $offsetInBody in '${body.text}'" }
|
||||
|
||||
originalOffsetByExpr[expr!!] = offsetInBody
|
||||
|
||||
@@ -497,7 +498,7 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
|
||||
val jumpValue = descriptor.controlFlow.jumpOutputValue
|
||||
if (jumpValue != null) {
|
||||
replacingReturn = psiFactory.createExpression(if (jumpValue.conditional) "return true" else "return")
|
||||
returnsForLabelRemoval.removeAll(jumpValue.elementsToReplace)
|
||||
returnsForLabelRemoval.removeAllRaw(jumpValue.elementsToReplace)
|
||||
expressionsToReplaceWithReturn = getCounterparts(jumpValue.elementsToReplace, body, bodyOffset, file)
|
||||
}
|
||||
else {
|
||||
@@ -514,7 +515,7 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
|
||||
getCounterparts(returnsForLabelRemoval, body, bodyOffset, file).forEach { it.getTargetLabel()?.delete() }
|
||||
|
||||
for ((expr, originalOffset) in originalOffsetByExpr) {
|
||||
if (expr.isValid()) {
|
||||
if (expr.isValid) {
|
||||
nameByOffset.put(originalOffset, exprReplacementMap[expr]?.invoke(descriptor, expr) ?: expr)
|
||||
}
|
||||
}
|
||||
@@ -523,7 +524,7 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
|
||||
|
||||
if (body !is KtBlockExpression) throw AssertionError("Block body expected: ${descriptor.extractionData.codeFragmentText}")
|
||||
|
||||
val firstExpression = body.getStatements().firstOrNull()
|
||||
val firstExpression = body.statements.firstOrNull()
|
||||
if (firstExpression != null) {
|
||||
for (param in descriptor.parameters) {
|
||||
param.mirrorVarName?.let { varName ->
|
||||
@@ -535,16 +536,16 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
|
||||
|
||||
val defaultValue = descriptor.controlFlow.defaultOutputValue
|
||||
|
||||
val lastExpression = body.getStatements().lastOrNull()
|
||||
val lastExpression = body.statements.lastOrNull()
|
||||
if (lastExpression is KtReturnExpression) return
|
||||
|
||||
val (defaultExpression, expressionToUnifyWith) =
|
||||
if (!generatorOptions.inTempFile && defaultValue != null && descriptor.controlFlow.outputValueBoxer.boxingRequired && lastExpression!!.isMultiLine()) {
|
||||
val varNameValidator = NewDeclarationNameValidator(body, lastExpression, NewDeclarationNameValidator.Target.VARIABLES)
|
||||
val resultVal = KotlinNameSuggester.suggestNamesByType(defaultValue.valueType, varNameValidator, null).first()
|
||||
val newDecl = body.addBefore(psiFactory.createDeclaration("val $resultVal = ${lastExpression!!.getText()}"), lastExpression) as KtProperty
|
||||
val newDecl = body.addBefore(psiFactory.createDeclaration("val $resultVal = ${lastExpression!!.text}"), lastExpression) as KtProperty
|
||||
body.addBefore(psiFactory.createNewLine(), lastExpression)
|
||||
psiFactory.createExpression(resultVal) to newDecl.getInitializer()!!
|
||||
psiFactory.createExpression(resultVal) to newDecl.initializer!!
|
||||
}
|
||||
else {
|
||||
lastExpression to null
|
||||
@@ -557,7 +558,7 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
|
||||
// In the case of lazy property absence of default value means that output values are of OutputValue.Initializer type
|
||||
// We just add resulting expressions without return, since returns are prohibited in the body of lazy property
|
||||
if (defaultValue == null) {
|
||||
body.appendElement(returnExpression.getReturnedExpression()!!)
|
||||
body.appendElement(returnExpression.returnedExpression!!)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -573,8 +574,8 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
|
||||
|
||||
if (generatorOptions.allowExpressionBody) {
|
||||
val convertToExpressionBody = ConvertToExpressionBodyIntention()
|
||||
val bodyExpression = body.getStatements().singleOrNull()
|
||||
val bodyOwner = body.getParent() as KtDeclarationWithBody
|
||||
val bodyExpression = body.statements.singleOrNull()
|
||||
val bodyOwner = body.parent as KtDeclarationWithBody
|
||||
if (bodyExpression != null && !bodyExpression.isMultiLine() && convertToExpressionBody.isApplicableTo(bodyOwner)) {
|
||||
convertToExpressionBody.applyTo(bodyOwner, !descriptor.returnType.isFlexible())
|
||||
}
|
||||
@@ -585,7 +586,7 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
|
||||
declarationToReplace?.let { return it.replace(declaration) as KtNamedDeclaration }
|
||||
|
||||
return with(descriptor.extractionData) {
|
||||
val targetContainer = anchor.getParent()!!
|
||||
val targetContainer = anchor.parent!!
|
||||
// TODO: Get rid of explicit new-lines in favor of formatter rules
|
||||
val emptyLines = psiFactory.createWhiteSpace("\n\n")
|
||||
if (insertBefore) {
|
||||
@@ -630,14 +631,14 @@ fun ExtractionGeneratorConfiguration.generateDeclaration(
|
||||
adjustDeclarationBody(declaration)
|
||||
|
||||
if (declaration is KtNamedFunction && declaration.getContainingJetFile().suppressDiagnosticsInDebugMode) {
|
||||
declaration.getReceiverTypeReference()?.debugTypeInfo = descriptor.receiverParameter?.getParameterType(true)
|
||||
declaration.receiverTypeReference?.debugTypeInfo = descriptor.receiverParameter?.getParameterType(true)
|
||||
|
||||
for ((i, param) in declaration.getValueParameters().withIndex()) {
|
||||
param.getTypeReference()?.debugTypeInfo = descriptor.parameters[i].getParameterType(true)
|
||||
for ((i, param) in declaration.valueParameters.withIndex()) {
|
||||
param.typeReference?.debugTypeInfo = descriptor.parameters[i].getParameterType(true)
|
||||
}
|
||||
|
||||
if (declaration.getTypeReference() != null) {
|
||||
declaration.getTypeReference()?.debugTypeInfo = descriptor.returnType.builtIns.anyType
|
||||
if (declaration.typeReference != null) {
|
||||
declaration.typeReference?.debugTypeInfo = descriptor.returnType.builtIns.anyType
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user