Minor: fix warnings

This commit is contained in:
Natalia Ukhorskaya
2015-10-23 16:47:29 +03:00
parent cacc50dc32
commit 05dbb875a9
4 changed files with 225 additions and 246 deletions
@@ -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
@@ -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
}
@@ -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)
@@ -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
}
}