diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt.172 b/compiler/psi/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt.172 deleted file mode 100644 index 87619e46914..00000000000 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt.172 +++ /dev/null @@ -1,848 +0,0 @@ -/* - * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.psi - -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.Key -import com.intellij.psi.PsiComment -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFileFactory -import com.intellij.psi.util.PsiTreeUtil -import com.intellij.util.LocalTimeCounter -import org.jetbrains.kotlin.idea.KotlinFileType -import org.jetbrains.kotlin.lexer.KtModifierKeywordToken -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.ImportPath - -@JvmOverloads -fun KtPsiFactory(project: Project?, markGenerated: Boolean = true): KtPsiFactory = KtPsiFactory(project!!, markGenerated) - -@JvmOverloads -fun KtPsiFactory(elementForProject: PsiElement, markGenerated: Boolean = true): KtPsiFactory = - KtPsiFactory(elementForProject.project, markGenerated) - -private val DO_NOT_ANALYZE_NOTIFICATION = "This file was created by KtPsiFactory and should not be analyzed\n" + - "Use createAnalyzableFile to create file that can be analyzed\n" - -var KtFile.doNotAnalyze: String? by UserDataProperty(Key.create("DO_NOT_ANALYZE")) -var KtFile.analysisContext: PsiElement? by UserDataProperty(Key.create("ANALYSIS_CONTEXT")) - - -/** - * @param markGenerated This needs to be set to true if the `KtPsiFactory` is going to be used for creating elements that are going - * to be inserted in the user source code (this ensures that the elements will be formatted correctly). In other cases, `markGenerated` - * should be false, which saves time and memory. - */ -class KtPsiFactory @JvmOverloads constructor(private val project: Project, val markGenerated: Boolean = true) { - - fun createValKeyword(): PsiElement { - val property = createProperty("val x = 1") - return property.valOrVarKeyword - } - - fun createVarKeyword(): PsiElement { - val property = createProperty("var x = 1") - return property.valOrVarKeyword - } - - private fun doCreateExpression(text: String): KtExpression? { - //NOTE: '\n' below is important - some strange code indenting problems appear without it - return createProperty("val x =\n$text").initializer - } - - fun createExpression(text: String): KtExpression { - val expression = doCreateExpression(text) ?: error("Failed to create expression from text: '$text'") - assert(expression.text == text) { - "Failed to create expression from text: '$text', resulting expression's text was: '${expression.text}'" - } - return expression - } - - fun createExpressionIfPossible(text: String): KtExpression? { - val expression = doCreateExpression(text) ?: return null - return if (expression.text == text) expression else null - } - - fun createThisExpression() = - (createExpression("this.x") as KtQualifiedExpression).receiverExpression as KtThisExpression - - fun createThisExpression(qualifier: String) = - (createExpression("this@$qualifier.x") as KtQualifiedExpression).receiverExpression as KtThisExpression - - fun createCallArguments(text: String): KtValueArgumentList { - val property = createProperty("val x = foo $text") - return (property.initializer as KtCallExpression).valueArgumentList!! - } - - fun createTypeArguments(text: String): KtTypeArgumentList { - val property = createProperty("val x = foo$text()") - return (property.initializer as KtCallExpression).typeArgumentList!! - } - - fun createTypeArgument(text: String) = createTypeArguments("<$text>").arguments.first() - - fun createType(type: String): KtTypeReference { - val typeReference = createTypeIfPossible(type) - if (typeReference == null || typeReference.text != type) { - throw IllegalArgumentException("Incorrect type: $type") - } - return typeReference - } - - fun createType(typeElement: KtTypeElement) = createType("X").apply { this.typeElement!!.replace(typeElement) } - - fun createTypeIfPossible(type: String): KtTypeReference? { - val typeReference = createProperty("val x : $type").typeReference - return if (typeReference?.text == type) typeReference else null - } - - fun createFunctionTypeReceiver(typeReference: KtTypeReference): KtFunctionTypeReceiver { - return (createType("A.() -> B").typeElement as KtFunctionType).receiver!!.apply { this.typeReference.replace(typeReference) } - } - - fun createFunctionTypeParameter(typeReference: KtTypeReference): KtParameter { - return (createType("(A) -> B").typeElement as KtFunctionType).parameters.first() - .apply { this.typeReference!!.replace(typeReference) } - } - - fun createTypeAlias(name: String, typeParameters: List, typeElement: KtTypeElement): KtTypeAlias { - return createTypeAlias(name, typeParameters, "X").apply { getTypeReference()!!.replace(createType(typeElement)) } - } - - fun createTypeAlias(name: String, typeParameters: List, body: String): KtTypeAlias { - val typeParametersText = if (typeParameters.isNotEmpty()) typeParameters.joinToString(prefix = "<", postfix = ">") else "" - return createDeclaration("typealias $name$typeParametersText = $body") - } - - fun createStar(): PsiElement { - return createType("List<*>").findElementAt(5)!! - } - - fun createComma(): PsiElement { - return createType("T").findElementAt(3)!! - } - - fun createDot(): PsiElement { - return createType("T.(X)").findElementAt(1)!! - } - - fun createColon(): PsiElement { - return createProperty("val x: Int").findElementAt(5)!! - } - - fun createEQ(): PsiElement { - return createFunction("fun foo() = foo").equalsToken!! - } - - fun createSemicolon(): PsiElement { - return createProperty("val x: Int;").findElementAt(10)!! - } - - //the pair contains the first and the last elements of a range - fun createWhitespaceAndArrow(): Pair { - val functionType = createType("() -> Int").typeElement as KtFunctionType - return Pair(functionType.findElementAt(2)!!, functionType.findElementAt(3)!!) - } - - fun createWhiteSpace(): PsiElement { - return createWhiteSpace(" ") - } - - fun createWhiteSpace(text: String): PsiElement { - return createProperty("val${text}x: Int").findElementAt(3)!! - } - - // Remove when all Java usages are rewritten to Kotlin - fun createNewLine(): PsiElement { - return createWhiteSpace("\n ") - } - - fun createNewLine(lineBreaks: Int): PsiElement { - return createWhiteSpace("\n".repeat(lineBreaks)) - } - - fun createClass(text: String): KtClass { - return createDeclaration(text) - } - - fun createObject(text: String): KtObjectDeclaration { - return createDeclaration(text) - } - - fun createCompanionObject(): KtObjectDeclaration { - return createCompanionObject("companion object {\n}") - } - - fun createCompanionObject(text: String): KtObjectDeclaration { - return createClass("class A {\n $text\n}").companionObjects.first() - } - - fun createFileAnnotation(annotationText: String): KtAnnotationEntry { - return createFileAnnotationListWithAnnotation(annotationText).annotationEntries.first() - } - - fun createFileAnnotationListWithAnnotation(annotationText: String): KtFileAnnotationList { - return createFile("@file:$annotationText").fileAnnotationList!! - } - - fun createFile(text: String): KtFile { - return createFile("dummy.kt", text) - } - - private fun doCreateFile(fileName: String, text: String): KtFile { - return PsiFileFactory.getInstance(project).createFileFromText( - fileName, - KotlinFileType.INSTANCE, - text, - LocalTimeCounter.currentTime(), - false, - markGenerated - ) as KtFile - } - - fun createFile(fileName: String, text: String): KtFile { - val file = doCreateFile(fileName, text) - - file.doNotAnalyze = DO_NOT_ANALYZE_NOTIFICATION - - return file - } - - fun createAnalyzableFile(fileName: String, text: String, contextToAnalyzeIn: PsiElement): KtFile { - val file = doCreateFile(fileName, text) - file.analysisContext = contextToAnalyzeIn - return file - } - - fun createFileWithLightClassSupport(fileName: String, text: String, contextToAnalyzeIn: PsiElement): KtFile { - val file = createPhysicalFile(fileName, text) - file.analysisContext = contextToAnalyzeIn - return file - } - - fun createPhysicalFile(fileName: String, text: String): KtFile { - return PsiFileFactory.getInstance(project).createFileFromText( - fileName, - KotlinFileType.INSTANCE, - text, - LocalTimeCounter.currentTime(), - true - ) as KtFile - } - - fun createProperty(modifiers: String?, name: String, type: String?, isVar: Boolean, initializer: String?): KtProperty { - val text = modifiers.let { "$it " } + - (if (isVar) " var " else " val ") + name + - (if (type != null) ":" + type else "") + (if (initializer == null) "" else " = " + initializer) - return createProperty(text) - } - - fun createProperty(name: String, type: String?, isVar: Boolean, initializer: String?): KtProperty { - return createProperty(null, name, type, isVar, initializer) - } - - fun createProperty(name: String, type: String?, isVar: Boolean): KtProperty { - return createProperty(name, type, isVar, null) - } - - fun createProperty(text: String): KtProperty { - return createDeclaration(text) - } - - fun createPropertyGetter(expression: KtExpression): KtPropertyAccessor { - val property = createProperty("val x get() = 1") - val getter = property.getter!! - val bodyExpression = getter.bodyExpression!! - - bodyExpression.replace(expression) - return getter - } - - fun createPropertySetter(expression: KtExpression): KtPropertyAccessor { - val property = if (expression is KtBlockExpression) - createProperty("val x get() = 1\nset(value) {\n field = value\n }") - else - createProperty("val x get() = 1\nset(value) = TODO()") - val setter = property.setter!! - val bodyExpression = setter.bodyExpression!! - - bodyExpression.replace(expression) - return setter - } - - fun createDestructuringDeclaration(text: String): KtDestructuringDeclaration { - return (createFunction("fun foo() {$text}").bodyExpression as KtBlockExpression).statements.first() as KtDestructuringDeclaration - } - - fun createDestructuringParameter(text: String): KtParameter { - val dummyFun = createFunction("fun foo() = { $text -> }") - return (dummyFun.bodyExpression as KtLambdaExpression).functionLiteral.valueParameters.first() - } - - fun createDeclaration(text: String): TDeclaration { - val file = createFile(text) - val declarations = file.declarations - assert(declarations.size == 1) { "${declarations.size} declarations in $text" } - return declarations.first() as TDeclaration - } - - fun createNameIdentifier(name: String) = createNameIdentifierIfPossible(name)!! - - fun createNameIdentifierIfPossible(name: String) = createProperty(name, null, false).nameIdentifier - - fun createSimpleName(name: String): KtSimpleNameExpression { - return createProperty(name, null, false, name).initializer as KtSimpleNameExpression - } - - fun createOperationName(name: String): KtSimpleNameExpression { - return (createExpression("0 $name 0") as KtBinaryExpression).operationReference - } - - fun createIdentifier(name: String): PsiElement { - return createSimpleName(name).getIdentifier()!! - } - - fun createFunction(funDecl: String): KtNamedFunction { - return createDeclaration(funDecl) - } - - fun createCallableReferenceExpression(text: String) = createExpression(text) as? KtCallableReferenceExpression - - fun createSecondaryConstructor(decl: String): KtSecondaryConstructor { - return createClass("class Foo {\n $decl \n}").secondaryConstructors.first() - } - - fun createModifierList(modifier: KtModifierKeywordToken): KtModifierList { - return createModifierList(modifier.value) - } - - fun createModifierList(text: String): KtModifierList { - return createProperty(text + " val x").modifierList!! - } - - fun createModifier(modifier: KtModifierKeywordToken): PsiElement { - return createModifierList(modifier.value).getModifier(modifier)!! - } - - fun createAnnotationEntry(text: String): KtAnnotationEntry { - val modifierList = createProperty(text + " val x").modifierList - return modifierList!!.annotationEntries.first() - } - - fun createEmptyBody(): KtBlockExpression { - return createFunction("fun foo() {}").bodyExpression as KtBlockExpression - } - - fun createAnonymousInitializer(): KtAnonymousInitializer { - return createClass("class A { init {} }").getAnonymousInitializers().first() - } - - fun createEmptyClassBody(): KtClassBody { - return createClass("class A(){}").getBody()!! - } - - fun createParameter(text: String): KtParameter { - return createClass("class A($text)").primaryConstructorParameters.first() - } - - fun createParameterList(text: String): KtParameterList { - return createFunction("fun foo$text{}").valueParameterList!! - } - - fun createTypeParameterList(text: String) = createClass("class Foo$text").typeParameterList!! - - fun createTypeParameter(text: String) = createTypeParameterList("<$text>").parameters.first()!! - - fun createLambdaParameterListIfAny(text: String) = - createLambdaExpression(text, "0").functionLiteral.valueParameterList - - fun createLambdaParameterList(text: String) = createLambdaParameterListIfAny(text)!! - - fun createLambdaExpression(parameters: String, body: String): KtLambdaExpression = - (if (parameters.isNotEmpty()) createExpression("{ $parameters -> $body }") - else createExpression("{ $body }")) as KtLambdaExpression - - - fun createEnumEntry(text: String): KtEnumEntry { - return createDeclaration("enum class E {$text}").declarations[0] as KtEnumEntry - } - - fun createEnumEntryInitializerList(): KtInitializerList { - return createEnumEntry("Entry()").initializerList!! - } - - fun createWhenEntry(entryText: String): KtWhenEntry { - val function = createFunction("fun foo() { when(12) { $entryText } }") - val whenEntry = PsiTreeUtil.findChildOfType(function, KtWhenEntry::class.java) - - assert(whenEntry != null) { "Couldn't generate when entry" } - assert(entryText == whenEntry!!.text) { "Generate when entry text differs from the given text" } - - return whenEntry - } - - fun createWhenCondition(conditionText: String): KtWhenCondition { - val whenEntry = createWhenEntry("$conditionText -> {}") - return whenEntry.conditions[0] - } - - fun createBlockStringTemplateEntry(expression: KtExpression): KtStringTemplateEntryWithExpression { - // We don't want reformatting here as it can potentially change something in raw strings - val stringTemplateExpression = createExpressionByPattern("\"$\${$0}\"", expression, reformat = false) as KtStringTemplateExpression - return stringTemplateExpression.entries[0] as KtStringTemplateEntryWithExpression - } - - fun createSimpleNameStringTemplateEntry(name: String): KtSimpleNameStringTemplateEntry { - val stringTemplateExpression = createExpression("\"\$$name\"") as KtStringTemplateExpression - return stringTemplateExpression.entries[0] as KtSimpleNameStringTemplateEntry - } - - fun createStringTemplate(content: String) = createExpression("\"$content\"") as KtStringTemplateExpression - - fun createPackageDirective(fqName: FqName): KtPackageDirective { - return createFile("package ${fqName.asString()}").packageDirective!! - } - - fun createPackageDirectiveIfNeeded(fqName: FqName): KtPackageDirective? { - return if (fqName.isRoot) null else createPackageDirective(fqName) - } - - fun createImportDirective(importPath: ImportPath): KtImportDirective { - if (importPath.fqName.isRoot) { - throw IllegalArgumentException("import path must not be empty") - } - - val file = createFile(buildString { appendImport(importPath) }) - return file.importDirectives.first() - } - - private fun StringBuilder.appendImport(importPath: ImportPath) { - if (importPath.fqName.isRoot) { - throw IllegalArgumentException("import path must not be empty") - } - - append("import ") - append(importPath.pathStr) - - val alias = importPath.alias - if (alias != null) { - append(" as ").append(alias.asString()) - } - } - - fun createImportDirectives(paths: Collection): List { - val fileContent = buildString { - for (path in paths) { - appendImport(path) - append('\n') - } - } - - val file = createFile(fileContent) - return file.importDirectives - } - - fun createPrimaryConstructor(text: String = ""): KtPrimaryConstructor { - return createClass(if (text.isNotEmpty()) "class A $text" else "class A()").primaryConstructor!! - } - - fun createPrimaryConstructorWithModifiers(modifiers: String?): KtPrimaryConstructor { - return modifiers?.let { createPrimaryConstructor("$it constructor()") } ?: createPrimaryConstructor() - } - - fun createConstructorKeyword(): PsiElement = - createClass("class A constructor()").primaryConstructor!!.getConstructorKeyword()!! - - fun createLabeledExpression(labelName: String): KtLabeledExpression = createExpression("$labelName@ 1") as KtLabeledExpression - - fun createTypeCodeFragment(text: String, context: PsiElement?): KtTypeCodeFragment { - return KtTypeCodeFragment(project, "fragment.kt", text, context) - } - - fun createExpressionCodeFragment(text: String, context: PsiElement?): KtExpressionCodeFragment { - return KtExpressionCodeFragment(project, "fragment.kt", text, null, context) - } - - fun createBlockCodeFragment(text: String, context: PsiElement?): KtBlockCodeFragment { - return KtBlockCodeFragment(project, "fragment.kt", text, null, context) - } - - fun createIf(condition: KtExpression, thenExpr: KtExpression, elseExpr: KtExpression? = null): KtIfExpression { - return (if (elseExpr != null) - createExpressionByPattern("if ($0) $1 else $2", condition, thenExpr, elseExpr) as KtIfExpression - else - createExpressionByPattern("if ($0) $1", condition, thenExpr)) as KtIfExpression - } - - fun createArgument(expression: KtExpression?, name: Name? = null, isSpread: Boolean = false): KtValueArgument { - val argumentList = buildByPattern({ pattern, args -> createByPattern(pattern, *args) { createCallArguments(it) } }) { - appendFixedText("(") - - if (name != null) { - appendName(name) - appendFixedText("=") - } - - if (isSpread) { - appendFixedText("*") - } - - appendExpression(expression) - - appendFixedText(")") - } - return argumentList.arguments.single() - } - - fun createArgument(text: String) = createCallArguments("($text)").arguments.first()!! - - fun createSuperTypeCallEntry(text: String): KtSuperTypeCallEntry { - return createClass("class A: $text").superTypeListEntries.first() as KtSuperTypeCallEntry - } - - fun createSuperTypeEntry(text: String): KtSuperTypeEntry { - return createClass("class A: $text").superTypeListEntries.first() as KtSuperTypeEntry - } - - fun creareDelegatedSuperTypeEntry(text: String): KtConstructorDelegationCall { - val colonOrEmpty = if (text.isEmpty()) "" else ": " - return createClass("class A { constructor()$colonOrEmpty$text {}").secondaryConstructors.first().getDelegationCall() - } - - class ClassHeaderBuilder { - - enum class State { - MODIFIERS, - NAME, - TYPE_PARAMETERS, - BASE_CLASS, - TYPE_CONSTRAINTS, - DONE - } - - private val sb = StringBuilder() - private var state = State.MODIFIERS - - fun modifier(modifier: String): ClassHeaderBuilder { - assert(state == State.MODIFIERS) - - sb.append(modifier) - - return this - } - - private fun placeKeyword() { - assert(state == State.MODIFIERS) - - if (sb.isNotEmpty()) { - sb.append(" ") - } - sb.append("class ") - - state = State.NAME - } - - - fun name(name: String): ClassHeaderBuilder { - placeKeyword() - - sb.append(name) - state = State.TYPE_PARAMETERS - - return this - } - - private fun appendInAngleBrackets(values: Collection) { - if (values.isNotEmpty()) { - sb.append(values.joinToString(", ", "<", ">")) - } - } - - fun typeParameters(values: Collection): ClassHeaderBuilder { - assert(state == State.TYPE_PARAMETERS) - - appendInAngleBrackets(values) - state = State.BASE_CLASS - - return this - } - - fun baseClass(name: String, typeArguments: Collection, isInterface: Boolean): ClassHeaderBuilder { - assert(state == State.BASE_CLASS) - - sb.append(" : $name") - appendInAngleBrackets(typeArguments) - if (!isInterface) { - sb.append("()") - } - - state = State.TYPE_CONSTRAINTS - - return this - } - - fun typeConstraints(values: Collection): ClassHeaderBuilder { - assert(state == State.TYPE_CONSTRAINTS) - - if (!values.isEmpty()) { - sb.append(values.joinToString(", ", " where ", "", -1, "")) - } - state = State.DONE - - return this - } - - fun transform(f: StringBuilder.() -> Unit) = sb.f() - - fun asString(): String { - if (state != State.DONE) { - state = State.DONE - } - - return sb.toString() - } - } - - class CallableBuilder(private val target: Target) { - - companion object { - val CONSTRUCTOR_NAME = KtTokens.CONSTRUCTOR_KEYWORD.value - } - - enum class Target { - FUNCTION, - CONSTRUCTOR, - READ_ONLY_PROPERTY - } - - enum class State { - MODIFIERS, - NAME, - RECEIVER, - FIRST_PARAM, - REST_PARAMS, - TYPE_CONSTRAINTS, - BODY, - DONE - } - - private val sb = StringBuilder() - private var state = State.MODIFIERS - - private fun closeParams() { - if (target == Target.FUNCTION || target == Target.CONSTRUCTOR) { - assert(state == State.FIRST_PARAM || state == State.REST_PARAMS) - sb.append(")") - } - - state = State.TYPE_CONSTRAINTS - } - - private fun placeKeyword() { - assert(state == State.MODIFIERS) - - if (sb.isNotEmpty() && !sb.endsWith(" ")) { - sb.append(" ") - } - val keyword = when (target) { - Target.FUNCTION -> "fun" - Target.CONSTRUCTOR -> "" - Target.READ_ONLY_PROPERTY -> "val" - } - sb.append("$keyword ") - - state = State.RECEIVER - } - - private fun bodyPrefix(breakLine: Boolean = true) = when (target) { - Target.FUNCTION, Target.CONSTRUCTOR -> "" - Target.READ_ONLY_PROPERTY -> (if (breakLine) "\n" else " ") + "get()" - } - - fun modifier(modifier: String): CallableBuilder { - assert(state == State.MODIFIERS) - - sb.append(modifier) - - return this - } - - fun typeParams(values: Collection = emptyList()): CallableBuilder { - placeKeyword() - if (!values.isEmpty()) { - sb.append(values.joinToString(", ", "<", "> ", -1, "")) - } - - return this - } - - fun receiver(receiverType: String): CallableBuilder { - assert(state == State.RECEIVER) - - sb.append(receiverType).append(".") - state = State.NAME - - return this - } - - fun name(name: String = CONSTRUCTOR_NAME): CallableBuilder { - assert(state == State.NAME || state == State.RECEIVER) - assert(name != CONSTRUCTOR_NAME || target == Target.CONSTRUCTOR) - - sb.append(name) - state = when (target) { - Target.FUNCTION, Target.CONSTRUCTOR -> { - sb.append("(") - State.FIRST_PARAM - } - else -> - State.TYPE_CONSTRAINTS - } - - return this - } - - fun param(name: String, type: String, defaultValue: String? = null): CallableBuilder { - assert(target == Target.FUNCTION || target == Target.CONSTRUCTOR) - assert(state == State.FIRST_PARAM || state == State.REST_PARAMS) - - if (state == State.REST_PARAMS) { - sb.append(", ") - } - sb.append(name).append(": ").append(type) - if (defaultValue != null) { - sb.append(" = ").append(defaultValue) - } - if (state == State.FIRST_PARAM) { - state = State.REST_PARAMS - } - - return this - } - - fun returnType(type: String): CallableBuilder { - closeParams() - sb.append(": ").append(type) - - return this - } - - fun noReturnType(): CallableBuilder { - closeParams() - - return this - } - - fun typeConstraints(values: Collection): CallableBuilder { - assert(state == State.TYPE_CONSTRAINTS && target != Target.CONSTRUCTOR) - - if (!values.isEmpty()) { - sb.append(values.joinToString(", ", " where ", "", -1, "")) - } - state = State.BODY - - return this - } - - fun superDelegation(argumentList: String): CallableBuilder { - assert(state == State.TYPE_CONSTRAINTS && target == Target.CONSTRUCTOR) - - sb.append(": super").append(argumentList) - state = State.BODY - - return this - } - - fun blockBody(body: String): CallableBuilder { - assert(state == State.BODY || state == State.TYPE_CONSTRAINTS) - - sb.append(bodyPrefix()).append(" {\n").append(body).append("\n}") - state = State.DONE - - return this - } - - fun getterExpression(expression: String, breakLine: Boolean = true): CallableBuilder { - assert(target == Target.READ_ONLY_PROPERTY) - assert(state == State.BODY || state == State.TYPE_CONSTRAINTS) - - sb.append(bodyPrefix(breakLine)).append(" = ").append(expression) - state = State.DONE - - return this - } - - fun initializer(body: String): CallableBuilder { - assert(target == Target.READ_ONLY_PROPERTY && (state == State.BODY || state == State.TYPE_CONSTRAINTS)) - - sb.append(" = ").append(body) - state = State.DONE - - return this - } - - fun lazyBody(body: String): CallableBuilder { - assert(target == Target.READ_ONLY_PROPERTY && (state == State.BODY || state == State.TYPE_CONSTRAINTS)) - - sb.append(" by kotlin.lazy {\n").append(body).append("\n}") - state = State.DONE - - return this - } - - fun transform(f: StringBuilder.() -> Unit) = sb.f() - - fun asString(): String { - if (state != State.DONE) { - state = State.DONE - } - - return sb.toString() - } - } - - fun createBlock(bodyText: String): KtBlockExpression { - return createFunction("fun foo() {\n$bodyText\n}").bodyExpression as KtBlockExpression - } - - fun createSingleStatementBlock(statement: KtExpression, prevComment: String? = null, nextComment: String? = null): KtBlockExpression { - val prev = if (prevComment == null) "" else " $prevComment " - val next = if (nextComment == null) "" else " $nextComment " - return createDeclarationByPattern("fun foo() {\n$prev$0$next\n}", statement).bodyExpression as KtBlockExpression - } - - fun createComment(text: String): PsiComment { - val file = createFile(text) - val comments = file.children.filterIsInstance() - val comment = comments.single() - assert(comment.text == text) - return comment - } - - // special hack used in ControlStructureTypingVisitor - // TODO: get rid of it - fun wrapInABlockWrapper(expression: KtExpression): KtBlockExpression { - if (expression is KtBlockExpression) { - return expression - } - val function = createFunction("fun f() { ${expression.text} }") - val block = function.bodyExpression as KtBlockExpression - return BlockWrapper(block, expression) - } - - private class BlockWrapper(fakeBlockExpression: KtBlockExpression, private val expression: KtExpression) : - KtBlockExpression(fakeBlockExpression.node), KtPsiUtil.KtExpressionWrapper { - override fun getStatements(): List { - return listOf(expression) - } - - override fun getBaseExpression(): KtExpression { - return expression - } - } -} diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt.172 b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt.172 deleted file mode 100644 index cbcce5ee86b..00000000000 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/psiModificationUtils.kt.172 +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.idea.core - -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiWhiteSpace -import com.intellij.psi.impl.source.codeStyle.CodeEditUtil -import com.intellij.psi.tree.IElementType -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.builtins.isFunctionType -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny -import org.jetbrains.kotlin.idea.references.mainReference -import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers -import org.jetbrains.kotlin.lexer.KtModifierKeywordToken -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.* -import org.jetbrains.kotlin.psi.typeRefHelpers.setReceiverTypeReference -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.OverridingUtil -import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentsInParentheses -import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.isError -import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments - -@Suppress("UNCHECKED_CAST") -inline fun PsiElement.replaced(newElement: T): T { - val result = replace(newElement) - return if (result is T) - result - else - (result as KtParenthesizedExpression).expression as T -} - -@Suppress("UNCHECKED_CAST") -fun T.copied(): T = copy() as T - -fun KtLambdaArgument.moveInsideParentheses(bindingContext: BindingContext): KtCallExpression { - val ktExpression = this.getArgumentExpression() - ?: throw KotlinExceptionWithAttachments("no argument expression for $this") - .withAttachment("lambdaExpression", this.text) - return moveInsideParenthesesAndReplaceWith(ktExpression, bindingContext) -} - -fun KtLambdaArgument.moveInsideParenthesesAndReplaceWith( - replacement: KtExpression, - bindingContext: BindingContext -): KtCallExpression = moveInsideParenthesesAndReplaceWith(replacement, getLambdaArgumentName(bindingContext)) - - -fun KtLambdaArgument.getLambdaArgumentName(bindingContext: BindingContext): Name? { - val callExpression = parent as KtCallExpression - val resolvedCall = callExpression.getResolvedCall(bindingContext) - return (resolvedCall?.getArgumentMapping(this) as? ArgumentMatch)?.valueParameter?.name -} - -fun KtLambdaArgument.moveInsideParenthesesAndReplaceWith( - replacement: KtExpression, - functionLiteralArgumentName: Name? -): KtCallExpression { - val oldCallExpression = parent as KtCallExpression - val newCallExpression = oldCallExpression.copy() as KtCallExpression - - val psiFactory = KtPsiFactory(project) - - val argument = if (shouldLambdaParameterBeNamed(newCallExpression.getValueArgumentsInParentheses(), oldCallExpression)) { - psiFactory.createArgument(replacement, functionLiteralArgumentName) - } - else { - psiFactory.createArgument(replacement) - } - - val functionLiteralArgument = newCallExpression.lambdaArguments.firstOrNull()!! - val valueArgumentList = newCallExpression.valueArgumentList ?: psiFactory.createCallArguments("()") - - valueArgumentList.addArgument(argument) - - (functionLiteralArgument.prevSibling as? PsiWhiteSpace)?.delete() - if (newCallExpression.valueArgumentList != null) { - functionLiteralArgument.delete() - } - else { - functionLiteralArgument.replace(valueArgumentList) - } - return oldCallExpression.replace(newCallExpression) as KtCallExpression -} - -private fun shouldLambdaParameterBeNamed(args: List, callExpr: KtCallExpression): Boolean { - if (args.any { it.isNamed() }) return true - val calee = (callExpr.calleeExpression?.mainReference?.resolve() as? KtFunction) ?: return true - return if (calee.valueParameters.any { it.isVarArg }) true else calee.valueParameters.size - 1 > args.size -} - -fun KtCallExpression.getLastLambdaExpression(): KtLambdaExpression? { - if (lambdaArguments.isNotEmpty()) return null - return valueArguments.lastOrNull()?.getArgumentExpression()?.unpackFunctionLiteral() -} - -fun KtCallExpression.canMoveLambdaOutsideParentheses(): Boolean { - if (getLastLambdaExpression() == null) return false - - val callee = calleeExpression - if (callee is KtNameReferenceExpression) { - val bindingContext = analyze(BodyResolveMode.PARTIAL) - val targets = bindingContext[BindingContext.REFERENCE_TARGET, callee]?.let { listOf(it) } - ?: bindingContext[BindingContext.AMBIGUOUS_REFERENCE_TARGET, callee] - ?: listOf() - val candidates = targets.filterIsInstance() - // if there are functions among candidates but none of them have last function parameter then not show the intention - if (candidates.isNotEmpty() && candidates.none { - val lastParameter = it.valueParameters.lastOrNull() - lastParameter != null && lastParameter.type.isFunctionType - }) { - return false - } - } - - return true -} - -fun KtCallExpression.moveFunctionLiteralOutsideParentheses() { - assert(lambdaArguments.isEmpty()) - val argumentList = valueArgumentList!! - val argument = argumentList.arguments.last() - val expression = argument.getArgumentExpression()!! - assert(expression.unpackFunctionLiteral() != null) - - val dummyCall = KtPsiFactory(this).createExpressionByPattern("foo()$0:'{}'", expression) as KtCallExpression - val functionLiteralArgument = dummyCall.lambdaArguments.single() - this.add(functionLiteralArgument) - /* we should not remove empty parenthesis when callee is a call too - it won't parse */ - if (argumentList.arguments.size == 1 && calleeExpression !is KtCallExpression) { - argumentList.delete() - } - else { - argumentList.removeArgument(argument) - } -} - -fun KtBlockExpression.appendElement(element: KtElement, addNewLine: Boolean = false): KtElement { - val rBrace = rBrace - val newLine = KtPsiFactory(this).createNewLine() - val anchor = if (rBrace == null) { - val lastChild = lastChild - if (lastChild !is PsiWhiteSpace) addAfter(newLine, lastChild)!! else lastChild - } - else { - rBrace.prevSibling!! - } - val addedElement = addAfter(element, anchor)!! as KtElement - if (addNewLine) { - addAfter(newLine, addedElement) - } - return addedElement -} - -//TODO: git rid of this method -fun PsiElement.deleteElementAndCleanParent() { - val parent = parent - - deleteElementWithDelimiters(this) - deleteChildlessElement(parent, this::class.java) -} - -// Delete element if it doesn't contain children of a given type -private fun deleteChildlessElement(element: PsiElement, childClass: Class) { - if (PsiTreeUtil.getChildrenOfType(element, childClass) == null) { - element.delete() - } -} - -// Delete given element and all the elements separating it from the neighboring elements of the same class -private fun deleteElementWithDelimiters(element: PsiElement) { - val paramBefore = PsiTreeUtil.getPrevSiblingOfType(element, element.javaClass) - - val from: PsiElement - val to: PsiElement - if (paramBefore != null) { - from = paramBefore.nextSibling - to = element - } - else { - val paramAfter = PsiTreeUtil.getNextSiblingOfType(element, element.javaClass) - - from = element - to = if (paramAfter != null) paramAfter.prevSibling else element - } - - val parent = element.parent - - parent.deleteChildRange(from, to) -} - -fun PsiElement.deleteSingle() { - CodeEditUtil.removeChild(parent?.node ?: return, node ?: return) -} - -fun KtClass.getOrCreateCompanionObject(): KtObjectDeclaration { - companionObjects.firstOrNull()?.let { return it } - return addDeclaration(KtPsiFactory(this).createCompanionObject()) -} - -fun KtDeclaration.toDescriptor(): DeclarationDescriptor? { - val bindingContext = analyze() - // TODO: temporary code - if (this is KtPrimaryConstructor) { - return this.getContainingClassOrObject().resolveToDescriptorIfAny()?.unsubstitutedPrimaryConstructor - } - - val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, this] - if (descriptor is ValueParameterDescriptor) { - return bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor] - } - return descriptor -} - -//TODO: code style option whether to insert redundant 'public' keyword or not -fun KtModifierListOwner.setVisibility(visibilityModifier: KtModifierKeywordToken) { - if (this is KtDeclaration) { - val defaultVisibilityKeyword = implicitVisibility() - - if (visibilityModifier == defaultVisibilityKeyword) { - this.visibilityModifierType()?.let { removeModifier(it) } - return - } - } - - addModifier(visibilityModifier) -} - -fun KtDeclaration.implicitVisibility(): KtModifierKeywordToken? = - when { - this is KtConstructor<*> -> { - val klass = getContainingClassOrObject() - if (klass is KtClass && (klass.isEnum() || klass.isSealed())) KtTokens.PRIVATE_KEYWORD - else KtTokens.DEFAULT_VISIBILITY_KEYWORD - } - hasModifier(KtTokens.OVERRIDE_KEYWORD) -> { - (resolveToDescriptorIfAny() as? CallableMemberDescriptor) - ?.overriddenDescriptors - ?.let { OverridingUtil.findMaxVisibility(it) } - ?.toKeywordToken() - } - else -> { - KtTokens.DEFAULT_VISIBILITY_KEYWORD - } - } - -fun KtModifierListOwner.canBePrivate() = modifierList?.hasModifier(KtTokens.ABSTRACT_KEYWORD) != true - -fun KtModifierListOwner.canBeProtected(): Boolean { - val parent = when (this) { - is KtPropertyAccessor -> this.property.parent - else -> this.parent - } - return when (parent) { - is KtClassBody -> parent.parent is KtClass - is KtParameterList -> parent.parent is KtPrimaryConstructor - else -> false - } -} - -fun KtClass.isInheritable(): Boolean { - return when (getModalityFromDescriptor()) { - KtTokens.ABSTRACT_KEYWORD, KtTokens.OPEN_KEYWORD, KtTokens.SEALED_KEYWORD -> true - else -> false - } -} - -fun KtDeclaration.isOverridable(): Boolean { - val parent = parent - if (!(parent is KtClassBody || parent is KtParameterList)) return false - - val klass = if (parent.parent is KtPrimaryConstructor) - parent.parent.parent as? KtClass - else - parent.parent as? KtClass - - if (klass == null || (!klass.isInheritable() && !klass.isEnum())) return false - - if (this.hasModifier(KtTokens.PRIVATE_KEYWORD)) { - // 'private' is incompatible with 'open' - return false - } - - return when (getModalityFromDescriptor()) { - KtTokens.ABSTRACT_KEYWORD, KtTokens.OPEN_KEYWORD -> true - else -> false - } -} - -fun KtDeclaration.getModalityFromDescriptor(): KtModifierKeywordToken? { - val descriptor = this.resolveToDescriptorIfAny() - if (descriptor is MemberDescriptor) { - return mapModality(descriptor.modality) - } - - return null -} - -fun KtDeclaration.implicitModality(): KtModifierKeywordToken { - var predictedModality = predictImplicitModality() - val bindingContext = analyze(BodyResolveMode.PARTIAL) - val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, this] ?: return predictedModality - val containingDescriptor = descriptor.containingDeclaration ?: return predictedModality - - val extensions = DeclarationAttributeAltererExtension.getInstances(this.project) - for (extension in extensions) { - val newModality = extension.refineDeclarationModality( - this, - descriptor as? ClassDescriptor, - containingDescriptor, - mapModalityToken(predictedModality), - bindingContext, - isImplicitModality = true) - - if (newModality != null) { - predictedModality = mapModality(newModality) - } - } - - return predictedModality -} - -fun mapModality(accurateModality: Modality): KtModifierKeywordToken = when (accurateModality) { - Modality.FINAL -> KtTokens.FINAL_KEYWORD - Modality.SEALED -> KtTokens.SEALED_KEYWORD - Modality.OPEN -> KtTokens.OPEN_KEYWORD - Modality.ABSTRACT -> KtTokens.ABSTRACT_KEYWORD -} - -private fun mapModalityToken(modalityToken: IElementType): Modality = when (modalityToken) { - KtTokens.FINAL_KEYWORD -> Modality.FINAL - KtTokens.SEALED_KEYWORD -> Modality.SEALED - KtTokens.OPEN_KEYWORD -> Modality.OPEN - KtTokens.ABSTRACT_KEYWORD -> Modality.ABSTRACT - else -> error("Unexpected modality keyword $modalityToken") -} - -private fun KtDeclaration.predictImplicitModality(): KtModifierKeywordToken { - if (this is KtClassOrObject) { - if (this is KtClass && this.isInterface()) return KtTokens.ABSTRACT_KEYWORD - return KtTokens.FINAL_KEYWORD - } - val klass = containingClassOrObject ?: return KtTokens.FINAL_KEYWORD - if (hasModifier(KtTokens.OVERRIDE_KEYWORD)) { - if (klass.hasModifier(KtTokens.ABSTRACT_KEYWORD) || - klass.hasModifier(KtTokens.OPEN_KEYWORD) || - klass.hasModifier(KtTokens.SEALED_KEYWORD)) { - return KtTokens.OPEN_KEYWORD - } - } - if (klass is KtClass && klass.isInterface() && !hasModifier(KtTokens.PRIVATE_KEYWORD)) { - return if (hasBody()) KtTokens.OPEN_KEYWORD else KtTokens.ABSTRACT_KEYWORD - } - return KtTokens.FINAL_KEYWORD -} - -fun KtSecondaryConstructor.getOrCreateBody(): KtBlockExpression { - bodyExpression?.let { return it } - - val delegationCall = getDelegationCall() - val anchor = if (delegationCall.isImplicit) valueParameterList else delegationCall - val newBody = KtPsiFactory(this).createEmptyBody() - return addAfter(newBody, anchor) as KtBlockExpression -} - -fun KtParameter.dropDefaultValue() { - val from = equalsToken ?: return - val to = defaultValue ?: from - deleteChildRange(from, to) -} - -fun dropEnclosingParenthesesIfPossible(expression: KtExpression): KtExpression { - val parent = expression.parent as? KtParenthesizedExpression ?: return expression - if (!KtPsiUtil.areParenthesesUseless(parent)) return expression - return parent.replaced(expression) -} - -fun KtTypeParameterListOwner.addTypeParameter(typeParameter: KtTypeParameter): KtTypeParameter? { - typeParameterList?.let { return it.addParameter(typeParameter) } - - val list = KtPsiFactory(this).createTypeParameterList("") - list.parameters[0].replace(typeParameter) - val leftAnchor = when (this) { - is KtClass -> nameIdentifier ?: getClassOrInterfaceKeyword() - is KtNamedFunction -> funKeyword - is KtProperty -> valOrVarKeyword - else -> null - } ?: return null - return (addAfter(list, leftAnchor) as KtTypeParameterList).parameters.first() -} - -fun KtNamedFunction.getOrCreateValueParameterList(): KtParameterList { - valueParameterList?.let { return it } - val parameterList = KtPsiFactory(this).createParameterList("()") - val anchor = nameIdentifier ?: funKeyword!! - return addAfter(parameterList, anchor) as KtParameterList -} - -fun KtCallableDeclaration.setType(type: KotlinType, shortenReferences: Boolean = true) { - if (type.isError) return - setType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type), shortenReferences) -} - -fun KtCallableDeclaration.setType(typeString: String, shortenReferences: Boolean = true) { - val typeReference = KtPsiFactory(project).createType(typeString) - setTypeReference(typeReference) - if (shortenReferences) { - ShortenReferences.DEFAULT.process(getTypeReference()!!) - } -} - -fun KtCallableDeclaration.setReceiverType(type: KotlinType) { - if (type.isError) return - val typeReference = KtPsiFactory(project).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type)) - setReceiverTypeReference(typeReference) - ShortenReferences.DEFAULT.process(receiverTypeReference!!) -} - -fun KtParameter.setDefaultValue(newDefaultValue: KtExpression): PsiElement? { - defaultValue?.let { return it.replaced(newDefaultValue) } - - val psiFactory = KtPsiFactory(this) - val eq = equalsToken ?: add(psiFactory.createEQ()) - return addAfter(newDefaultValue, eq) as KtExpression -} - -fun KtBlockStringTemplateEntry.canDropBraces() = - expression is KtNameReferenceExpression && canPlaceAfterSimpleNameEntry(nextSibling) - -fun KtBlockStringTemplateEntry.dropBraces(): KtSimpleNameStringTemplateEntry { - val name = (expression as KtNameReferenceExpression).getReferencedName() - val newEntry = KtPsiFactory(this).createSimpleNameStringTemplateEntry(name) - return replaced(newEntry) -} \ No newline at end of file