Refactoring

This commit is contained in:
Dmitry Gridin
2019-02-26 16:14:49 +03:00
parent 76e133014b
commit 5d599ee2ff
@@ -78,9 +78,6 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.types.typeUtil.makeNullable
import java.lang.AssertionError
import java.lang.IllegalArgumentException
import java.lang.IllegalStateException
import java.util.* import java.util.*
/** /**
@@ -96,7 +93,7 @@ class TypeCandidate(val theType: KotlinType, scope: HierarchicalScope? = null) {
fun render(typeParameterNameMap: Map<TypeParameterDescriptor, String>, fakeFunction: FunctionDescriptor?) { fun render(typeParameterNameMap: Map<TypeParameterDescriptor, String>, fakeFunction: FunctionDescriptor?) {
renderedTypes = theType.renderShort(typeParameterNameMap) renderedTypes = theType.renderShort(typeParameterNameMap)
renderedTypeParameters = typeParameters.map { renderedTypeParameters = typeParameters.map {
RenderedTypeParameter(it, it.containingDeclaration == fakeFunction, typeParameterNameMap[it]!!) RenderedTypeParameter(it, it.containingDeclaration == fakeFunction, typeParameterNameMap.getValue(it))
} }
} }
@@ -105,8 +102,7 @@ class TypeCandidate(val theType: KotlinType, scope: HierarchicalScope? = null) {
if (scope == null) { if (scope == null) {
typeParameters = typeParametersInType.toTypedArray() typeParameters = typeParametersInType.toTypedArray()
renderedTypes = theType.renderShort(Collections.emptyMap()) renderedTypes = theType.renderShort(Collections.emptyMap())
} } else {
else {
typeParameters = getTypeParameterNamesNotInScope(typeParametersInType, scope).toTypedArray() typeParameters = getTypeParameterNamesNotInScope(typeParametersInType, scope).toTypedArray()
} }
} }
@@ -133,8 +129,8 @@ class CallableBuilderConfiguration(
) )
sealed class CallablePlacement { sealed class CallablePlacement {
class WithReceiver(val receiverTypeCandidate: TypeCandidate): CallablePlacement() class WithReceiver(val receiverTypeCandidate: TypeCandidate) : CallablePlacement()
class NoReceiver(val containingElement: PsiElement): CallablePlacement() class NoReceiver(val containingElement: PsiElement) : CallablePlacement()
} }
class CallableBuilder(val config: CallableBuilderConfiguration) { class CallableBuilder(val config: CallableBuilderConfiguration) {
@@ -173,7 +169,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
private fun computeTypeCandidates( private fun computeTypeCandidates(
typeInfo: TypeInfo, typeInfo: TypeInfo,
substitutions: List<KotlinTypeSubstitution>, substitutions: List<KotlinTypeSubstitution>,
scope: HierarchicalScope): List<TypeCandidate> { scope: HierarchicalScope
): List<TypeCandidate> {
if (!typeInfo.substitutionsAllowed) return computeTypeCandidates(typeInfo) if (!typeInfo.substitutionsAllowed) return computeTypeCandidates(typeInfo)
return typeCandidates.getOrPut(typeInfo) { return typeCandidates.getOrPut(typeInfo) {
val types = typeInfo.getPossibleTypes(this).asReversed() val types = typeInfo.getPossibleTypes(this).asReversed()
@@ -182,6 +179,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
data class EqWrapper(val _type: KotlinType) { data class EqWrapper(val _type: KotlinType) {
override fun equals(other: Any?) = this === other override fun equals(other: Any?) = this === other
|| other is EqWrapper && KotlinTypeChecker.DEFAULT.equalTypes(_type, other._type) || other is EqWrapper && KotlinTypeChecker.DEFAULT.equalTypes(_type, other._type)
override fun hashCode() = 0 // no good way to compute hashCode() that would agree with our equals() override fun hashCode() = 0 // no good way to compute hashCode() that would agree with our equals()
} }
@@ -209,8 +207,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
val context = Context(iterator.next()) val context = Context(iterator.next())
runWriteAction { context.buildAndRunTemplate { buildNext(iterator) } } runWriteAction { context.buildAndRunTemplate { buildNext(iterator) } }
ApplicationManager.getApplication().invokeLater { context.showDialogIfNeeded() } ApplicationManager.getApplication().invokeLater { context.showDialogIfNeeded() }
} } else {
else {
runWriteAction { ShortenReferences.DEFAULT.process(elementsToShorten) } runWriteAction { ShortenReferences.DEFAULT.process(elementsToShorten) }
} }
} }
@@ -220,8 +217,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
assert(config.currentEditor != null) { "Can't run build() without editor" } assert(config.currentEditor != null) { "Can't run build() without editor" }
if (finished) throw IllegalStateException("Current builder has already finished") if (finished) throw IllegalStateException("Current builder has already finished")
buildNext(config.callableInfos.iterator()) buildNext(config.callableInfos.iterator())
} } finally {
finally {
finished = true finished = true
onFinish() onFinish()
} }
@@ -248,7 +244,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
when (placement) { when (placement) {
is CallablePlacement.NoReceiver -> { is CallablePlacement.NoReceiver -> {
containingElement = placement.containingElement containingElement = placement.containingElement
receiverClassDescriptor = with (placement.containingElement) { receiverClassDescriptor = with(placement.containingElement) {
when (this) { when (this) {
is KtClassOrObject -> currentFileContext[BindingContext.CLASS, this] is KtClassOrObject -> currentFileContext[BindingContext.CLASS, this]
is PsiClass -> getJavaClassDescriptor() is PsiClass -> getJavaClassDescriptor()
@@ -279,13 +275,12 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
jetFileToEdit = containingElement.containingKtFile jetFileToEdit = containingElement.containingKtFile
containingFileEditor = if (jetFileToEdit != config.currentFile) { containingFileEditor = if (jetFileToEdit != config.currentFile) {
FileEditorManager.getInstance(project).selectedTextEditor!! FileEditorManager.getInstance(project).selectedTextEditor!!
} } else {
else {
config.currentEditor!! config.currentEditor!!
} }
null null
} else { } else {
val dialog = object: DialogWithEditor(project, "Create from usage", "") { val dialog = object : DialogWithEditor(project, "Create from usage", "") {
override fun doOKAction() { override fun doOKAction() {
project.executeWriteCommand("Premature end of template") { project.executeWriteCommand("Premature end of template") {
TemplateManagerImpl.getTemplateState(editor)?.gotoEnd(false) TemplateManagerImpl.getTemplateState(editor)?.gotoEnd(false)
@@ -315,15 +310,16 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
val typeArgumentsForFakeFunction = callableInfo.typeParameterInfos val typeArgumentsForFakeFunction = callableInfo.typeParameterInfos
.map { .map {
val typeCandidates = computeTypeCandidates(it) val typeCandidates = computeTypeCandidates(it)
assert (typeCandidates.size == 1) { "Ambiguous type candidates for type parameter $it: $typeCandidates" } assert(typeCandidates.size == 1) { "Ambiguous type candidates for type parameter $it: $typeCandidates" }
typeCandidates.first().theType typeCandidates.first().theType
} }
.subtract(substitutionMap.keys) .subtract(substitutionMap.keys)
fakeFunction = createFakeFunctionDescriptor(scope, typeArgumentsForFakeFunction.size) fakeFunction = createFakeFunctionDescriptor(scope, typeArgumentsForFakeFunction.size)
collectSubstitutionsForCallableTypeParameters(fakeFunction, typeArgumentsForFakeFunction, substitutionMap) collectSubstitutionsForCallableTypeParameters(fakeFunction, typeArgumentsForFakeFunction, substitutionMap)
mandatoryTypeParametersAsCandidates = listOfNotNull(receiverTypeCandidate) + typeArgumentsForFakeFunction.map { TypeCandidate(substitutionMap[it]!!, scope) } mandatoryTypeParametersAsCandidates = listOfNotNull(receiverTypeCandidate) + typeArgumentsForFakeFunction.map {
TypeCandidate(substitutionMap[it]!!, scope)
} }
else { } else {
fakeFunction = null fakeFunction = null
mandatoryTypeParametersAsCandidates = Collections.emptyList() mandatoryTypeParametersAsCandidates = Collections.emptyList()
} }
@@ -362,14 +358,16 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
return receiverClassDescriptor.scopeForMemberDeclarationResolution return receiverClassDescriptor.scopeForMemberDeclarationResolution
} }
assert (receiverClassDescriptor is JavaClassDescriptor) { "Unexpected receiver class: $receiverClassDescriptor" } assert(receiverClassDescriptor is JavaClassDescriptor) { "Unexpected receiver class: $receiverClassDescriptor" }
val projections = ((receiverClassDescriptor as JavaClassDescriptor).declaredTypeParameters) val projections = ((receiverClassDescriptor as JavaClassDescriptor).declaredTypeParameters)
.map { TypeProjectionImpl(it.defaultType) } .map { TypeProjectionImpl(it.defaultType) }
val memberScope = receiverClassDescriptor.getMemberScope(projections) val memberScope = receiverClassDescriptor.getMemberScope(projections)
return LexicalScopeImpl(memberScope.memberScopeAsImportingScope(), receiverClassDescriptor, false, null, return LexicalScopeImpl(
LexicalScopeKind.SYNTHETIC) { memberScope.memberScopeAsImportingScope(), receiverClassDescriptor, false, null,
LexicalScopeKind.SYNTHETIC
) {
receiverClassDescriptor.typeConstructor.parameters.forEach { addClassifierDescriptor(it) } receiverClassDescriptor.typeConstructor.parameters.forEach { addClassifierDescriptor(it) }
} }
} }
@@ -390,7 +388,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
private fun collectSubstitutionsForCallableTypeParameters( private fun collectSubstitutionsForCallableTypeParameters(
fakeFunction: FunctionDescriptor, fakeFunction: FunctionDescriptor,
typeArguments: Set<KotlinType>, typeArguments: Set<KotlinType>,
result: MutableMap<KotlinType, KotlinType>) { result: MutableMap<KotlinType, KotlinType>
) {
for ((typeArgument, typeParameter) in typeArguments.zip(fakeFunction.typeParameters)) { for ((typeArgument, typeParameter) in typeArguments.zip(fakeFunction.typeParameters)) {
result[typeArgument] = typeParameter.defaultType result[typeArgument] = typeParameter.defaultType
} }
@@ -407,7 +406,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
val validator = CollectingNameValidator { scope.findClassifier(Name.identifier(it), NoLookupLocation.FROM_IDE) == null } val validator = CollectingNameValidator { scope.findClassifier(Name.identifier(it), NoLookupLocation.FROM_IDE) == null }
val parameterNames = KotlinNameSuggester.suggestNamesForTypeParameters(typeParameterCount, validator) val parameterNames = KotlinNameSuggester.suggestNamesForTypeParameters(typeParameterCount, validator)
val typeParameters = (0..typeParameterCount - 1).map { val typeParameters = (0 until typeParameterCount).map {
TypeParameterDescriptorImpl.createWithDefaultBound( TypeParameterDescriptorImpl.createWithDefaultBound(
fakeFunction, fakeFunction,
Annotations.EMPTY, Annotations.EMPTY,
@@ -418,8 +417,10 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
) )
} }
return fakeFunction.initialize(null, null, typeParameters, Collections.emptyList(), null, return fakeFunction.initialize(
null, Visibilities.INTERNAL) null, null, typeParameters, Collections.emptyList(), null,
null, Visibilities.INTERNAL
)
} }
private fun renderTypeCandidates( private fun renderTypeCandidates(
@@ -436,12 +437,11 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
} }
private fun createDeclarationSkeleton(): KtNamedDeclaration { private fun createDeclarationSkeleton(): KtNamedDeclaration {
with (config) { with(config) {
val assignmentToReplace = val assignmentToReplace =
if (containingElement is KtBlockExpression && (callableInfo as? PropertyInfo)?.writable ?: false) { if (containingElement is KtBlockExpression && (callableInfo as? PropertyInfo)?.writable == true) {
originalElement as KtBinaryExpression originalElement as KtBinaryExpression
} } else null
else null
val ownerTypeString = if (isExtension) { val ownerTypeString = if (isExtension) {
val renderedType = receiverTypeCandidate!!.renderedTypes.first() val renderedType = receiverTypeCandidate!!.renderedTypes.first()
@@ -456,7 +456,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
val list = callableInfo.parameterInfos.indices.joinToString(", ") { i -> "${prefix}p$i: Any" } val list = callableInfo.parameterInfos.indices.joinToString(", ") { i -> "${prefix}p$i: Any" }
return if (callableInfo.parameterInfos.isNotEmpty() return if (callableInfo.parameterInfos.isNotEmpty()
|| callableInfo.kind == CallableKind.FUNCTION || callableInfo.kind == CallableKind.FUNCTION
|| callableInfo.kind == CallableKind.CONSTRUCTOR) "($list)" else list || callableInfo.kind == CallableKind.CONSTRUCTOR
) "($list)" else list
} }
val paramList = when (callableInfo.kind) { val paramList = when (callableInfo.kind) {
@@ -478,7 +479,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
else if (containingElement is KtClassOrObject else if (containingElement is KtClassOrObject
&& !(containingElement is KtClass && containingElement.isInterface()) && !(containingElement is KtClass && containingElement.isInterface())
&& containingElement.isAncestor(config.originalElement) && containingElement.isAncestor(config.originalElement)
&& callableInfo.kind != CallableKind.CONSTRUCTOR) "private " && callableInfo.kind != CallableKind.CONSTRUCTOR
) "private "
else if (isExtension) "private " else if (isExtension) "private "
else "" else ""
append(defaultVisibility) append(defaultVisibility)
@@ -488,7 +490,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
if (callableInfo.isAbstract if (callableInfo.isAbstract
&& containingElement is KtClass && containingElement is KtClass
&& !containingElement.isInterface() && !containingElement.isInterface()
&& !modifierList.hasModifier(KtTokens.ABSTRACT_KEYWORD)) { && !modifierList.hasModifier(KtTokens.ABSTRACT_KEYWORD)
) {
modifierList.appendModifier(KtTokens.ABSTRACT_KEYWORD) modifierList.appendModifier(KtTokens.ABSTRACT_KEYWORD)
} }
@@ -517,15 +520,13 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
} }
@Suppress("USELESS_CAST") // KT-10755 @Suppress("USELESS_CAST") // KT-10755
if (callableInfo is FunctionInfo) { when {
psiFactory.createFunction("${modifiers}fun<> $header $body") as KtNamedDeclaration callableInfo is FunctionInfo -> psiFactory.createFunction("${modifiers}fun<> $header $body") as KtNamedDeclaration
} (callableInfo as ConstructorInfo).isPrimary -> {
else if ((callableInfo as ConstructorInfo).isPrimary) {
val constructorText = if (modifiers.isNotEmpty()) "${modifiers}constructor$paramList" else paramList val constructorText = if (modifiers.isNotEmpty()) "${modifiers}constructor$paramList" else paramList
psiFactory.createPrimaryConstructor(constructorText) as KtNamedDeclaration psiFactory.createPrimaryConstructor(constructorText) as KtNamedDeclaration
} }
else { else -> psiFactory.createSecondaryConstructor("${modifiers}constructor$paramList $body") as KtNamedDeclaration
psiFactory.createSecondaryConstructor("${modifiers}constructor$paramList $body") as KtNamedDeclaration
} }
} }
CallableKind.CLASS_WITH_PRIMARY_CONSTRUCTOR -> { CallableKind.CLASS_WITH_PRIMARY_CONSTRUCTOR -> {
@@ -566,8 +567,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
append("\nset() {}") append("\nset() {}")
} }
} }
} } else ""
else ""
psiFactory.createProperty("$modifiers$valVar<> $header$accessors") psiFactory.createProperty("$modifiers$valVar<> $header$accessors")
} }
} }
@@ -579,16 +579,14 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
val container = if (containingElement is KtClass && callableInfo.isForCompanion) { val container = if (containingElement is KtClass && callableInfo.isForCompanion) {
containingElement.getOrCreateCompanionObject() containingElement.getOrCreateCompanionObject()
} } else containingElement
else containingElement
val declarationInPlace = placeDeclarationInContainer(declaration, container, config.originalElement, jetFileToEdit) val declarationInPlace = placeDeclarationInContainer(declaration, container, config.originalElement, jetFileToEdit)
if (declarationInPlace is KtSecondaryConstructor) { if (declarationInPlace is KtSecondaryConstructor) {
val containingClass = declarationInPlace.containingClassOrObject!! val containingClass = declarationInPlace.containingClassOrObject!!
if (containingClass.primaryConstructorParameters.isNotEmpty()) { if (containingClass.primaryConstructorParameters.isNotEmpty()) {
declarationInPlace.replaceImplicitDelegationCallWithExplicit(true) declarationInPlace.replaceImplicitDelegationCallWithExplicit(true)
} } else if ((receiverClassDescriptor as ClassDescriptor).getSuperClassOrAny().constructors.all { it.valueParameters.isNotEmpty() }) {
else if ((receiverClassDescriptor as ClassDescriptor).getSuperClassOrAny().constructors.all { it.valueParameters.isNotEmpty() }) {
declarationInPlace.replaceImplicitDelegationCallWithExplicit(false) declarationInPlace.replaceImplicitDelegationCallWithExplicit(false)
} }
} }
@@ -612,13 +610,17 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
} }
val validator = CollectingNameValidator { scope.findClassifier(Name.identifier(it), NoLookupLocation.FROM_IDE) == null } val validator = CollectingNameValidator { scope.findClassifier(Name.identifier(it), NoLookupLocation.FROM_IDE) == null }
val typeParameterNames = allTypeParametersNotInScope.map { KotlinNameSuggester.suggestNameByName(it.name.asString(), validator) } val typeParameterNames = allTypeParametersNotInScope.map {
KotlinNameSuggester.suggestNameByName(it.name.asString(), validator)
}
return allTypeParametersNotInScope.zip(typeParameterNames).toMap() return allTypeParametersNotInScope.zip(typeParameterNames).toMap()
} }
private fun setupTypeReferencesForShortening(declaration: KtNamedDeclaration, private fun setupTypeReferencesForShortening(
parameterTypeExpressions: List<TypeExpression>) { declaration: KtNamedDeclaration,
parameterTypeExpressions: List<TypeExpression>
) {
if (config.isExtension) { if (config.isExtension) {
val receiverTypeText = receiverTypeCandidate!!.theType.renderLong(typeParameterNameMap).first() val receiverTypeText = receiverTypeCandidate!!.theType.renderLong(typeParameterNameMap).first()
val replacingTypeRef = KtPsiFactory(declaration).createType(receiverTypeText) val replacingTypeRef = KtPsiFactory(declaration).createType(receiverTypeText)
@@ -692,8 +694,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
} }
if (renderedTypeArgs.isEmpty()) { if (renderedTypeArgs.isEmpty()) {
oldTypeArgumentList.delete() oldTypeArgumentList.delete()
} } else {
else {
oldTypeArgumentList.replace(KtPsiFactory(callElement).createTypeArguments(renderedTypeArgs.joinToString(", ", "<", ">"))) oldTypeArgumentList.replace(KtPsiFactory(callElement).createTypeArguments(renderedTypeArgs.joinToString(", ", "<", ">")))
elementsToShorten.add(callElement.typeArgumentList!!) elementsToShorten.add(callElement.typeArgumentList!!)
} }
@@ -765,7 +766,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
callableInfo.kind != CallableKind.CLASS_WITH_PRIMARY_CONSTRUCTOR callableInfo.kind != CallableKind.CLASS_WITH_PRIMARY_CONSTRUCTOR
) )
val leftSpace = typeParameterList.prevSibling as? PsiWhiteSpace val leftSpace = typeParameterList.prevSibling as? PsiWhiteSpace
val rangeStart = if (leftSpace != null) leftSpace.startOffset else typeParameterList.startOffset val rangeStart = leftSpace?.startOffset ?: typeParameterList.startOffset
val offset = typeParameterList.startOffset val offset = typeParameterList.startOffset
val range = UnfairTextRange(rangeStart - offset, typeParameterList.endOffset - offset) val range = UnfairTextRange(rangeStart - offset, typeParameterList.endOffset - offset)
builder.replaceElement(typeParameterList, range, "TYPE_PARAMETER_LIST", expression, false) builder.replaceElement(typeParameterList, range, "TYPE_PARAMETER_LIST", expression, false)
@@ -819,8 +820,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
val adjustedDeclaration = when (declaration) { val adjustedDeclaration = when (declaration) {
is KtNamedFunction, is KtProperty -> { is KtNamedFunction, is KtProperty -> {
val klass = psiFactory.createClass("class Foo {}") val klass = psiFactory.createClass("class Foo {}")
klass.getBody()!!.add(declaration) klass.body!!.add(declaration)
(declaration.replace(klass) as KtClass).getBody()!!.declarations.first() (declaration.replace(klass) as KtClass).body!!.declarations.first()
} }
else -> declaration else -> declaration
} }
@@ -876,8 +877,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
if (superCall != null) { if (superCall != null) {
val lParen = superCall.argumentList.firstChild val lParen = superCall.argumentList.firstChild
targetEditor.caretModel.moveToOffset(lParen.endOffset) targetEditor.caretModel.moveToOffset(lParen.endOffset)
} } else {
else {
targetEditor.caretModel.moveToOffset(newJavaMember.startOffset) targetEditor.caretModel.moveToOffset(newJavaMember.startOffset)
} }
} }
@@ -962,10 +962,12 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
if (brokenOff && !ApplicationManager.getApplication().isUnitTestMode) return if (brokenOff && !ApplicationManager.getApplication().isUnitTestMode) return
// file templates // file templates
val newDeclaration = PsiTreeUtil.findElementOfClassAtOffset(jetFileToEdit, val newDeclaration = PsiTreeUtil.findElementOfClassAtOffset(
jetFileToEdit,
declarationMarker.startOffset, declarationMarker.startOffset,
declaration::class.java, declaration::class.java,
false) ?: return false
) ?: return
runWriteAction { runWriteAction {
postprocessDeclaration(newDeclaration) postprocessDeclaration(newDeclaration)
@@ -982,7 +984,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
&& newDeclaration.initializer == null && newDeclaration.initializer == null
&& callableInfo is PropertyInfo && callableInfo is PropertyInfo
&& callableInfo.withInitializer && callableInfo.withInitializer
&& !callableInfo.isLateinitPreferred) { && !callableInfo.isLateinitPreferred
) {
newDeclaration.initializer = KtPsiFactory(newDeclaration).createExpression("TODO(\"initialize me\")") newDeclaration.initializer = KtPsiFactory(newDeclaration).createExpression("TODO(\"initialize me\")")
} }
} }
@@ -1001,8 +1004,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
setupEditor(newDeclaration) setupEditor(newDeclaration)
} }
} }
} } finally {
finally {
declarationMarker.dispose() declarationMarker.dispose()
finished = true finished = true
onFinish() onFinish()
@@ -1065,8 +1067,10 @@ internal fun <D : KtNamedDeclaration> placeDeclarationInContainer(
val actualContainer = (container as? KtClassOrObject)?.getOrCreateBody() ?: container val actualContainer = (container as? KtClassOrObject)?.getOrCreateBody() ?: container
fun addDeclarationToClassOrObject(classOrObject: KtClassOrObject, fun addDeclarationToClassOrObject(
declaration: KtNamedDeclaration): KtNamedDeclaration { classOrObject: KtClassOrObject,
declaration: KtNamedDeclaration
): KtNamedDeclaration {
val classBody = classOrObject.getOrCreateBody() val classBody = classOrObject.getOrCreateBody()
return if (declaration is KtNamedFunction) { return if (declaration is KtNamedFunction) {
val neighbor = PsiTreeUtil.skipSiblingsBackward( val neighbor = PsiTreeUtil.skipSiblingsBackward(
@@ -1074,8 +1078,7 @@ internal fun <D : KtNamedDeclaration> placeDeclarationInContainer(
PsiWhiteSpace::class.java PsiWhiteSpace::class.java
) )
classBody.addAfter(declaration, neighbor) as KtNamedDeclaration classBody.addAfter(declaration, neighbor) as KtNamedDeclaration
} } else classBody.addAfter(declaration, classBody.lBrace!!) as KtNamedDeclaration
else classBody.addAfter(declaration, classBody.lBrace!!) as KtNamedDeclaration
} }
@@ -1083,8 +1086,7 @@ internal fun <D : KtNamedDeclaration> placeDeclarationInContainer(
val sibling = anchor.parentsWithSelf.first { it.parent == actualContainer } val sibling = anchor.parentsWithSelf.first { it.parent == actualContainer }
return if (addBefore) { return if (addBefore) {
actualContainer.addBefore(declaration, sibling) actualContainer.addBefore(declaration, sibling)
} } else {
else {
actualContainer.addAfter(declaration, sibling) actualContainer.addAfter(declaration, sibling)
} as D } as D
} }
@@ -1105,9 +1107,11 @@ internal fun <D : KtNamedDeclaration> placeDeclarationInContainer(
} }
} }
} }
addNextToOriginalElementContainer(insertToBlock addNextToOriginalElementContainer(
insertToBlock
|| (declaration is KtProperty && actualContainer !is KtFile) || (declaration is KtProperty && actualContainer !is KtFile)
|| declaration is KtTypeAlias) || declaration is KtTypeAlias
)
} }
container is KtFile -> container.add(declaration) as D container is KtFile -> container.add(declaration) as D
@@ -1117,8 +1121,7 @@ internal fun <D : KtNamedDeclaration> placeDeclarationInContainer(
val wrappingClass = psiFactory.createClass("class ${container.name} {\n}") val wrappingClass = psiFactory.createClass("class ${container.name} {\n}")
addDeclarationToClassOrObject(wrappingClass, declaration) addDeclarationToClassOrObject(wrappingClass, declaration)
(fileToEdit.add(wrappingClass) as KtClass).declarations.first() as D (fileToEdit.add(wrappingClass) as KtClass).declarations.first() as D
} } else {
else {
fileToEdit.add(declaration) as D fileToEdit.add(declaration) as D
} }
} }
@@ -1126,7 +1129,7 @@ internal fun <D : KtNamedDeclaration> placeDeclarationInContainer(
container is KtClassOrObject -> { container is KtClassOrObject -> {
var sibling: PsiElement? = container.declarations.lastOrNull { it::class == declaration::class } var sibling: PsiElement? = container.declarations.lastOrNull { it::class == declaration::class }
if (sibling == null && declaration is KtProperty) { if (sibling == null && declaration is KtProperty) {
sibling = container.getBody()?.lBrace sibling = container.body?.lBrace
} }
insertMember(null, container, declaration, sibling) insertMember(null, container, declaration, sibling)