Extract Function: Extract ParametersInfo class

This commit is contained in:
Alexey Sedunov
2014-07-04 15:05:36 +04:00
parent a6882f6670
commit 7430f10e96
@@ -398,17 +398,23 @@ private class DelegatingParameter(
override fun copy(name: String, parameterType: JetType): Parameter = DelegatingParameter(original, name, parameterType) override fun copy(name: String, parameterType: JetType): Parameter = DelegatingParameter(original, name, parameterType)
} }
private class ParametersInfo {
var errorMessage: ErrorMessage? = null
val replacementMap: MutableMap<Int, Replacement> = HashMap()
val originalRefToParameter: MutableMap<JetSimpleNameExpression, MutableParameter> = HashMap()
val parameters: MutableSet<MutableParameter> = HashSet()
val typeParameters: MutableSet<TypeParameter> = HashSet()
val nonDenotableTypes: MutableSet<JetType> = HashSet()
}
private fun ExtractionData.inferParametersInfo( private fun ExtractionData.inferParametersInfo(
commonParent: PsiElement, commonParent: PsiElement,
pseudocode: Pseudocode, pseudocode: Pseudocode,
bindingContext: BindingContext, bindingContext: BindingContext,
modifiedVarDescriptors: Set<VariableDescriptor>, modifiedVarDescriptors: Set<VariableDescriptor>
replacementMap: MutableMap<Int, Replacement>, ): ParametersInfo {
originalRefToParameter: MutableMap<JetSimpleNameExpression, MutableParameter>, val info = ParametersInfo()
parameters: MutableSet<MutableParameter>,
typeParameters: MutableSet<TypeParameter>,
nonDenotableTypes: MutableSet<JetType>
): ErrorMessage? {
val varNameValidator = JetNameValidatorImpl( val varNameValidator = JetNameValidatorImpl(
commonParent.getParentByType(javaClass<JetExpression>()), commonParent.getParentByType(javaClass<JetExpression>()),
originalElements.first, originalElements.first,
@@ -424,7 +430,8 @@ private fun ExtractionData.inferParametersInfo(
val selector = (ref.getParent() as? JetCallExpression) ?: ref val selector = (ref.getParent() as? JetCallExpression) ?: ref
val superExpr = (selector.getParent() as? JetQualifiedExpression)?.getReceiverExpression() as? JetSuperExpression val superExpr = (selector.getParent() as? JetQualifiedExpression)?.getReceiverExpression() as? JetSuperExpression
if (superExpr != null) { if (superExpr != null) {
return ErrorMessage.SUPER_CALL info.errorMessage = ErrorMessage.SUPER_CALL
return info
} }
val receiverArgument = resolvedCall?.getReceiverArgument() val receiverArgument = resolvedCall?.getReceiverArgument()
@@ -453,10 +460,12 @@ private fun ExtractionData.inferParametersInfo(
} }
if (referencedClassDescriptor != null) { if (referencedClassDescriptor != null) {
if (!referencedClassDescriptor.getDefaultType().processTypeIfExtractable(typeParameters, nonDenotableTypes, false)) continue if (!referencedClassDescriptor.getDefaultType().processTypeIfExtractable(
info.typeParameters, info.nonDenotableTypes, false
)) continue
val replacingDescriptor = (originalDescriptor as? ConstructorDescriptor)?.getContainingDeclaration() ?: originalDescriptor val replacingDescriptor = (originalDescriptor as? ConstructorDescriptor)?.getContainingDeclaration() ?: originalDescriptor
replacementMap[refInfo.offsetInBody] = FqNameReplacement(DescriptorUtils.getFqNameSafe(replacingDescriptor)) info.replacementMap[refInfo.offsetInBody] = FqNameReplacement(DescriptorUtils.getFqNameSafe(replacingDescriptor))
} }
else { else {
val extractThis = hasThisReceiver || thisExpr != null val extractThis = hasThisReceiver || thisExpr != null
@@ -476,7 +485,7 @@ private fun ExtractionData.inferParametersInfo(
?: DEFAULT_PARAMETER_TYPE ?: DEFAULT_PARAMETER_TYPE
} }
if (!parameterType.processTypeIfExtractable(typeParameters, nonDenotableTypes)) continue if (!parameterType.processTypeIfExtractable(info.typeParameters, info.nonDenotableTypes)) continue
val parameterTypePredicate = val parameterTypePredicate =
pseudocode.getElementValue(originalRef)?.let { getExpectedTypePredicate(it, bindingContext) } ?: AllTypes pseudocode.getElementValue(originalRef)?.let { getExpectedTypePredicate(it, bindingContext) } ?: AllTypes
@@ -501,24 +510,24 @@ private fun ExtractionData.inferParametersInfo(
} }
parameter.refCount++ parameter.refCount++
originalRefToParameter[originalRef] = parameter info.originalRefToParameter[originalRef] = parameter
parameter.addDefaultType(parameterType) parameter.addDefaultType(parameterType)
parameter.addTypePredicate(parameterTypePredicate) parameter.addTypePredicate(parameterTypePredicate)
replacementMap[refInfo.offsetInBody] = info.replacementMap[refInfo.offsetInBody] =
if (hasThisReceiver && extractThis) AddPrefixReplacement(parameter) else RenameReplacement(parameter) if (hasThisReceiver && extractThis) AddPrefixReplacement(parameter) else RenameReplacement(parameter)
} }
} }
} }
for (typeToCheck in typeParameters.flatMapTo(HashSet<JetType>()) { it.collectReferencedTypes(bindingContext) }) { for (typeToCheck in info.typeParameters.flatMapTo(HashSet<JetType>()) { it.collectReferencedTypes(bindingContext) }) {
typeToCheck.processTypeIfExtractable(typeParameters, nonDenotableTypes) typeToCheck.processTypeIfExtractable(info.typeParameters, info.nonDenotableTypes)
} }
parameters.addAll(extractedDescriptorToParameter.values()) info.parameters.addAll(extractedDescriptorToParameter.values())
return null return info
} }
private fun ExtractionData.checkDeclarationsMovingOutOfScope( private fun ExtractionData.checkDeclarationsMovingOutOfScope(
@@ -591,28 +600,21 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
val modifiedVarDescriptors = localInstructions.getModifiedVarDescriptors(bindingContext) val modifiedVarDescriptors = localInstructions.getModifiedVarDescriptors(bindingContext)
val replacementMap = HashMap<Int, Replacement>() val paramsInfo = inferParametersInfo(commonParent, pseudocode, bindingContext, modifiedVarDescriptors)
val originalRefToParameter = HashMap<JetSimpleNameExpression, MutableParameter>() if (paramsInfo.errorMessage != null) {
val parameters = HashSet<MutableParameter>() return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(paramsInfo.errorMessage!!))
val typeParameters = HashSet<TypeParameter>()
val nonDenotableTypes = HashSet<JetType>()
val parameterError = inferParametersInfo(
commonParent, pseudocode, bindingContext, modifiedVarDescriptors, replacementMap, originalRefToParameter, parameters, typeParameters, nonDenotableTypes
)
if (parameterError != null) {
return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(parameterError))
} }
val messages = ArrayList<ErrorMessage>() val messages = ArrayList<ErrorMessage>()
val (controlFlow, controlFlowMessage) = val (controlFlow, controlFlowMessage) =
analyzeControlFlow(localInstructions, pseudocode, bindingContext, modifiedVarDescriptors, options, parameters) analyzeControlFlow(localInstructions, pseudocode, bindingContext, modifiedVarDescriptors, options, paramsInfo.parameters)
controlFlowMessage?.let { messages.add(it) } controlFlowMessage?.let { messages.add(it) }
controlFlow.returnType.processTypeIfExtractable(typeParameters, nonDenotableTypes) controlFlow.returnType.processTypeIfExtractable(paramsInfo.typeParameters, paramsInfo.nonDenotableTypes)
if (nonDenotableTypes.isNotEmpty()) { if (paramsInfo.nonDenotableTypes.isNotEmpty()) {
val typeStr = nonDenotableTypes.map {DescriptorRenderer.HTML.renderType(it)}.sort() val typeStr = paramsInfo.nonDenotableTypes.map {DescriptorRenderer.HTML.renderType(it)}.sort()
return AnalysisResult( return AnalysisResult(
null, null,
Status.CRITICAL_ERROR, Status.CRITICAL_ERROR,
@@ -634,12 +636,12 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
controlFlow.elementToInsertAfterCall.accept( controlFlow.elementToInsertAfterCall.accept(
object: JetTreeVisitorVoid() { object: JetTreeVisitorVoid() {
override fun visitSimpleNameExpression(expression: JetSimpleNameExpression) { override fun visitSimpleNameExpression(expression: JetSimpleNameExpression) {
originalRefToParameter[expression]?.let { it.refCount-- } paramsInfo.originalRefToParameter[expression]?.let { it.refCount-- }
} }
} }
) )
} }
val adjustedParameters = parameters.filterTo(HashSet<Parameter>()) { it.refCount > 0 } val adjustedParameters = paramsInfo.parameters.filterTo(HashSet<Parameter>()) { it.refCount > 0 }
val receiverCandidates = adjustedParameters.filterTo(HashSet<Parameter>()) { it.receiverCandidate } 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
@@ -652,8 +654,8 @@ fun ExtractionData.performAnalysis(): AnalysisResult {
"", "",
adjustedParameters.sortBy { it.name }, adjustedParameters.sortBy { it.name },
receiverParameter, receiverParameter,
typeParameters.sortBy { it.originalDeclaration.getName()!! }, paramsInfo.typeParameters.sortBy { it.originalDeclaration.getName()!! },
replacementMap, paramsInfo.replacementMap,
if (messages.empty) controlFlow else controlFlow.toDefault() if (messages.empty) controlFlow else controlFlow.toDefault()
), ),
if (messages.empty) Status.SUCCESS else Status.NON_CRITICAL_ERROR, if (messages.empty) Status.SUCCESS else Status.NON_CRITICAL_ERROR,