diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt index ea800b7a919..722705b2ef0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt @@ -372,7 +372,7 @@ public class JetPsiFactory(private val project: Project) { appendFixedText("(") if (name != null) { - appendFixedText(Name.identifier(name).renderName()) + appendName(Name.identifier(name)) appendFixedText("=") } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/createByPattern.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/createByPattern.kt index e7f68b71450..db87384fcad 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/createByPattern.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/createByPattern.kt @@ -22,11 +22,12 @@ import com.intellij.psi.SmartPointerManager import com.intellij.psi.SmartPsiElementPointer import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.psi.impl.source.codeStyle.CodeEditUtil +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.renderName import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.psi.psiUtil.replaced import org.jetbrains.kotlin.psi.psiUtil.startOffset -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import java.util.ArrayList import java.util.HashMap import java.util.LinkedHashMap @@ -38,6 +39,9 @@ public fun JetPsiFactory.createDeclarationByPatt = createByPattern(pattern, *args) { createDeclaration(it) } public fun createByPattern(pattern: String, vararg args: Any, factory: (String) -> TElement): TElement { + @suppress("NAME_SHADOWING") + val args = args.map { if (it is Name) it.renderName() else it } + val (processedText, allPlaceholders) = processPattern(pattern, args) var resultElement = factory(processedText.trim()) @@ -125,7 +129,7 @@ private data class Placeholder(val range: TextRange, val text: String) private data class PatternData(val processedText: String, val placeholders: Map>) -private fun processPattern(pattern: String, args: Array): PatternData { +private fun processPattern(pattern: String, args: List): PatternData { val ranges = LinkedHashMap>() fun charOrNull(i: Int) = if (0 <= i && i < pattern.length()) pattern[i] else null @@ -155,13 +159,13 @@ private fun processPattern(pattern: String, args: Array): PatternData { i = lastIndex val arg: Any? = if (n < args.size()) args[n] else null /* report wrong number of arguments later */ - val placeholderText = if (charOrNull(i) != '=') { + val placeholderText = if (charOrNull(i) != ':' || charOrNull(i + 1) != '\'') { if (arg is String) arg else "xyz" } else { check(arg !is String, "do not specify placeholder text for $$n - String argument passed") - i++ - val endIndex = pattern.indexOf('$', i) + i += 2 // skip ':' and '\'' + val endIndex = pattern.indexOf('\'', i) check(endIndex >= 0, "unclosed placeholder text") check(endIndex > i, "empty placeholder text") val text = pattern.substring(i, endIndex) @@ -227,6 +231,12 @@ public class BuilderByPattern { return this } + public fun appendName(name: Name): BuilderByPattern { + patternBuilder.append("$" + arguments.size()) + arguments.add(name) + return this + } + public fun create(factory: (String, Array) -> TElement): TElement { return factory(patternBuilder.toString(), arguments.toArray()) } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/InfixCallToOrdinaryIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/InfixCallToOrdinaryIntention.kt index eeb4dea3bf8..3351e942871 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/InfixCallToOrdinaryIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/InfixCallToOrdinaryIntention.kt @@ -29,7 +29,7 @@ public class InfixCallToOrdinaryIntention : JetSelfTargetingIntention " $2={}$" + is JetFunctionLiteralExpression -> " $2:'{}'" else -> "($2)" } val replacement = JetPsiFactory(element).createExpressionByPattern(pattern, element.getLeft()!!, element.getOperationReference().getText(), argument) diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt index 49a34f25cfa..4206c6a3f3b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt @@ -89,7 +89,7 @@ fun splitPropertyDeclaration(property: JetProperty): JetBinaryExpression { val explicitTypeToSet = if (property.getTypeReference() != null) null else initializer.analyze().getType(initializer) val psiFactory = JetPsiFactory(property) - var assignment = psiFactory.createExpressionByPattern("$0 = $1", property.getName()!!, initializer) + var assignment = psiFactory.createExpressionByPattern("$0 = $1", property.getNameAsName()!!, initializer) assignment = parent.addAfter(assignment, property) as JetBinaryExpression parent.addAfter(psiFactory.createNewLine(), property) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFixBase.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFixBase.kt index 80631febcc1..45e6f8791a2 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFixBase.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFixBase.kt @@ -611,20 +611,19 @@ public abstract class DeprecatedSymbolUsageFixBase( ) { assert(usages.all { expression.isAncestor(it, strict = true) }) - fun nameInCode(name: String) = Name.identifier(name).renderName() - - fun replaceUsages(name: String) { - val nameInCode = psiFactory.createExpression(nameInCode(name)) + fun replaceUsages(name: Name) { + val nameInCode = psiFactory.createExpression(name.renderName()) for (usage in usages) { usage.replace(nameInCode) } } - fun suggestName(validator: JetNameValidator): String { - return if (nameSuggestion != null) + fun suggestName(validator: JetNameValidator): Name { + val name = if (nameSuggestion != null) validator.validateName(nameSuggestion) else JetNameSuggester.suggestNamesForExpression(value, validator, "t").first() + return Name.identifier(name) } // checks that name is used (without receiver) inside expression being constructed but not inside usages that will be replaced @@ -653,7 +652,7 @@ public abstract class DeprecatedSymbolUsageFixBase( } }) - var declaration = psiFactory.createDeclaration("val ${nameInCode(name)} = " + value.getText()) + var declaration = psiFactory.createDeclarationByPattern("val $0 = $1", name, value) declaration = block.addBefore(declaration, expressionToBeReplaced) as JetVariableDeclaration block.addBefore(psiFactory.createNewLine(), expressionToBeReplaced) @@ -676,7 +675,7 @@ public abstract class DeprecatedSymbolUsageFixBase( val dot = if (safeCall) "?." else "." expression = if (!isNameUsed("it")) { - replaceUsages("it") + replaceUsages(Name.identifier("it")) psiFactory.createExpressionByPattern("$0${dot}let { $1 }", value, expression) } else { @@ -684,7 +683,7 @@ public abstract class DeprecatedSymbolUsageFixBase( override fun validateInner(name: String) = !isNameUsed(name) }) replaceUsages(name) - psiFactory.createExpressionByPattern("$0${dot}let { ${nameInCode(name)} -> $1 }", value, expression) + psiFactory.createExpressionByPattern("$0${dot}let { $1 -> $2 }", value, name, expression) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveNameFromFunctionExpressionFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveNameFromFunctionExpressionFix.kt index 58f195705b2..fbffa2ac9bb 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveNameFromFunctionExpressionFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/RemoveNameFromFunctionExpressionFix.kt @@ -61,10 +61,10 @@ public class RemoveNameFromFunctionExpressionFix(element: JetNamedFunction) : Je private fun removeNameFromFunction(function: JetNamedFunction) { var wereAutoLabelUsages = false - val name = function.getName() ?: return + val name = function.getNameAsName() ?: return function.forEachDescendantOfType { - if (!wereAutoLabelUsages && it.getLabelName() == name) { + if (!wereAutoLabelUsages && it.getLabelNameAsName() == name) { wereAutoLabelUsages = it.analyze().get(BindingContext.LABEL_TARGET, it.getTargetLabel()) == function } } @@ -73,7 +73,7 @@ public class RemoveNameFromFunctionExpressionFix(element: JetNamedFunction) : Je if (wereAutoLabelUsages) { val psiFactory = JetPsiFactory(function) - val newFunction = psiFactory.createExpressionByPattern("$name@ $0", function) + val newFunction = psiFactory.createExpressionByPattern("$0@ $1", name, function) function.replace(newFunction) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceObsoleteLabelSyntaxFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceObsoleteLabelSyntaxFix.kt index 11b08c92be7..47598fb4195 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceObsoleteLabelSyntaxFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceObsoleteLabelSyntaxFix.kt @@ -94,7 +94,7 @@ public class ReplaceObsoleteLabelSyntaxFix(element: JetAnnotationEntry?) : JetIn val textRangeToRetain = TextRange(annotation.getTextRange().getEndOffset(), baseExpressionStart) val textToRetain = textRangeToRetain.substring(annotation.getContainingFile().getText()) - val labeledExpression = JetPsiFactory(annotation).createExpressionByPattern("$labelName@$0$1", textToRetain, expression) + val labeledExpression = JetPsiFactory(annotation).createExpressionByPattern("$0@$1$2", labelName, textToRetain, expression) annotatedExpression.replace(labeledExpression) } diff --git a/idea/src/org/jetbrains/kotlin/idea/util/psiModificationUtil.kt b/idea/src/org/jetbrains/kotlin/idea/util/psiModificationUtil.kt index d06b3ec7c92..6bff091c1c4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/util/psiModificationUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/util/psiModificationUtil.kt @@ -76,7 +76,7 @@ fun JetCallExpression.moveFunctionLiteralOutsideParentheses() { val expression = argument.getArgumentExpression()!! assert(expression.unpackFunctionLiteral() != null) - val dummyCall = JetPsiFactory(this).createExpressionByPattern("foo()$0={}$", expression) as JetCallExpression + val dummyCall = JetPsiFactory(this).createExpressionByPattern("foo()$0:'{}'", expression) as JetCallExpression val functionLiteralArgument = dummyCall.getFunctionLiteralArguments().single() this.add(functionLiteralArgument) if (argumentList.getArguments().size() > 1) {