JetPsiFactory: create by pattern allows Name's as arguments + changed placeholder text specification format
This commit is contained in:
@@ -372,7 +372,7 @@ public class JetPsiFactory(private val project: Project) {
|
|||||||
appendFixedText("(")
|
appendFixedText("(")
|
||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
appendFixedText(Name.identifier(name).renderName())
|
appendName(Name.identifier(name))
|
||||||
appendFixedText("=")
|
appendFixedText("=")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,12 @@ import com.intellij.psi.SmartPointerManager
|
|||||||
import com.intellij.psi.SmartPsiElementPointer
|
import com.intellij.psi.SmartPsiElementPointer
|
||||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||||
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil
|
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.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.replaced
|
import org.jetbrains.kotlin.psi.psiUtil.replaced
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
import java.util.LinkedHashMap
|
import java.util.LinkedHashMap
|
||||||
@@ -38,6 +39,9 @@ public fun <TDeclaration : JetDeclaration> JetPsiFactory.createDeclarationByPatt
|
|||||||
= createByPattern(pattern, *args) { createDeclaration<TDeclaration>(it) }
|
= createByPattern(pattern, *args) { createDeclaration<TDeclaration>(it) }
|
||||||
|
|
||||||
public fun <TElement : JetElement> createByPattern(pattern: String, vararg args: Any, factory: (String) -> TElement): TElement {
|
public fun <TElement : JetElement> 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)
|
val (processedText, allPlaceholders) = processPattern(pattern, args)
|
||||||
|
|
||||||
var resultElement = factory(processedText.trim())
|
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<Int, List<Placeholder>>)
|
private data class PatternData(val processedText: String, val placeholders: Map<Int, List<Placeholder>>)
|
||||||
|
|
||||||
private fun processPattern(pattern: String, args: Array<out Any>): PatternData {
|
private fun processPattern(pattern: String, args: List<Any>): PatternData {
|
||||||
val ranges = LinkedHashMap<Int, MutableList<Placeholder>>()
|
val ranges = LinkedHashMap<Int, MutableList<Placeholder>>()
|
||||||
|
|
||||||
fun charOrNull(i: Int) = if (0 <= i && i < pattern.length()) pattern[i] else null
|
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<out Any>): PatternData {
|
|||||||
i = lastIndex
|
i = lastIndex
|
||||||
|
|
||||||
val arg: Any? = if (n < args.size()) args[n] else null /* report wrong number of arguments later */
|
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"
|
if (arg is String) arg else "xyz"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
check(arg !is String, "do not specify placeholder text for $$n - String argument passed")
|
check(arg !is String, "do not specify placeholder text for $$n - String argument passed")
|
||||||
i++
|
i += 2 // skip ':' and '\''
|
||||||
val endIndex = pattern.indexOf('$', i)
|
val endIndex = pattern.indexOf('\'', i)
|
||||||
check(endIndex >= 0, "unclosed placeholder text")
|
check(endIndex >= 0, "unclosed placeholder text")
|
||||||
check(endIndex > i, "empty placeholder text")
|
check(endIndex > i, "empty placeholder text")
|
||||||
val text = pattern.substring(i, endIndex)
|
val text = pattern.substring(i, endIndex)
|
||||||
@@ -227,6 +231,12 @@ public class BuilderByPattern<TElement> {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun appendName(name: Name): BuilderByPattern<TElement> {
|
||||||
|
patternBuilder.append("$" + arguments.size())
|
||||||
|
arguments.add(name)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
public fun create(factory: (String, Array<out Any>) -> TElement): TElement {
|
public fun create(factory: (String, Array<out Any>) -> TElement): TElement {
|
||||||
return factory(patternBuilder.toString(), arguments.toArray())
|
return factory(patternBuilder.toString(), arguments.toArray())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public class InfixCallToOrdinaryIntention : JetSelfTargetingIntention<JetBinaryE
|
|||||||
override fun applyTo(element: JetBinaryExpression, editor: Editor) {
|
override fun applyTo(element: JetBinaryExpression, editor: Editor) {
|
||||||
val argument = JetPsiUtil.safeDeparenthesize(element.getRight()!!)
|
val argument = JetPsiUtil.safeDeparenthesize(element.getRight()!!)
|
||||||
val pattern = "$0.$1" + when (argument) {
|
val pattern = "$0.$1" + when (argument) {
|
||||||
is JetFunctionLiteralExpression -> " $2={}$"
|
is JetFunctionLiteralExpression -> " $2:'{}'"
|
||||||
else -> "($2)"
|
else -> "($2)"
|
||||||
}
|
}
|
||||||
val replacement = JetPsiFactory(element).createExpressionByPattern(pattern, element.getLeft()!!, element.getOperationReference().getText(), argument)
|
val replacement = JetPsiFactory(element).createExpressionByPattern(pattern, element.getLeft()!!, element.getOperationReference().getText(), argument)
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ fun splitPropertyDeclaration(property: JetProperty): JetBinaryExpression {
|
|||||||
val explicitTypeToSet = if (property.getTypeReference() != null) null else initializer.analyze().getType(initializer)
|
val explicitTypeToSet = if (property.getTypeReference() != null) null else initializer.analyze().getType(initializer)
|
||||||
|
|
||||||
val psiFactory = JetPsiFactory(property)
|
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
|
assignment = parent.addAfter(assignment, property) as JetBinaryExpression
|
||||||
parent.addAfter(psiFactory.createNewLine(), property)
|
parent.addAfter(psiFactory.createNewLine(), property)
|
||||||
|
|||||||
@@ -611,20 +611,19 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
|||||||
) {
|
) {
|
||||||
assert(usages.all { expression.isAncestor(it, strict = true) })
|
assert(usages.all { expression.isAncestor(it, strict = true) })
|
||||||
|
|
||||||
fun nameInCode(name: String) = Name.identifier(name).renderName()
|
fun replaceUsages(name: Name) {
|
||||||
|
val nameInCode = psiFactory.createExpression(name.renderName())
|
||||||
fun replaceUsages(name: String) {
|
|
||||||
val nameInCode = psiFactory.createExpression(nameInCode(name))
|
|
||||||
for (usage in usages) {
|
for (usage in usages) {
|
||||||
usage.replace(nameInCode)
|
usage.replace(nameInCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun suggestName(validator: JetNameValidator): String {
|
fun suggestName(validator: JetNameValidator): Name {
|
||||||
return if (nameSuggestion != null)
|
val name = if (nameSuggestion != null)
|
||||||
validator.validateName(nameSuggestion)
|
validator.validateName(nameSuggestion)
|
||||||
else
|
else
|
||||||
JetNameSuggester.suggestNamesForExpression(value, validator, "t").first()
|
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
|
// 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<JetVariableDeclaration>("val ${nameInCode(name)} = " + value.getText())
|
var declaration = psiFactory.createDeclarationByPattern<JetVariableDeclaration>("val $0 = $1", name, value)
|
||||||
declaration = block.addBefore(declaration, expressionToBeReplaced) as JetVariableDeclaration
|
declaration = block.addBefore(declaration, expressionToBeReplaced) as JetVariableDeclaration
|
||||||
block.addBefore(psiFactory.createNewLine(), expressionToBeReplaced)
|
block.addBefore(psiFactory.createNewLine(), expressionToBeReplaced)
|
||||||
|
|
||||||
@@ -676,7 +675,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
|||||||
val dot = if (safeCall) "?." else "."
|
val dot = if (safeCall) "?." else "."
|
||||||
|
|
||||||
expression = if (!isNameUsed("it")) {
|
expression = if (!isNameUsed("it")) {
|
||||||
replaceUsages("it")
|
replaceUsages(Name.identifier("it"))
|
||||||
psiFactory.createExpressionByPattern("$0${dot}let { $1 }", value, expression)
|
psiFactory.createExpressionByPattern("$0${dot}let { $1 }", value, expression)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -684,7 +683,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
|||||||
override fun validateInner(name: String) = !isNameUsed(name)
|
override fun validateInner(name: String) = !isNameUsed(name)
|
||||||
})
|
})
|
||||||
replaceUsages(name)
|
replaceUsages(name)
|
||||||
psiFactory.createExpressionByPattern("$0${dot}let { ${nameInCode(name)} -> $1 }", value, expression)
|
psiFactory.createExpressionByPattern("$0${dot}let { $1 -> $2 }", value, name, expression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,10 +61,10 @@ public class RemoveNameFromFunctionExpressionFix(element: JetNamedFunction) : Je
|
|||||||
|
|
||||||
private fun removeNameFromFunction(function: JetNamedFunction) {
|
private fun removeNameFromFunction(function: JetNamedFunction) {
|
||||||
var wereAutoLabelUsages = false
|
var wereAutoLabelUsages = false
|
||||||
val name = function.getName() ?: return
|
val name = function.getNameAsName() ?: return
|
||||||
|
|
||||||
function.forEachDescendantOfType<JetReturnExpression> {
|
function.forEachDescendantOfType<JetReturnExpression> {
|
||||||
if (!wereAutoLabelUsages && it.getLabelName() == name) {
|
if (!wereAutoLabelUsages && it.getLabelNameAsName() == name) {
|
||||||
wereAutoLabelUsages = it.analyze().get(BindingContext.LABEL_TARGET, it.getTargetLabel()) == function
|
wereAutoLabelUsages = it.analyze().get(BindingContext.LABEL_TARGET, it.getTargetLabel()) == function
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,7 +73,7 @@ public class RemoveNameFromFunctionExpressionFix(element: JetNamedFunction) : Je
|
|||||||
|
|
||||||
if (wereAutoLabelUsages) {
|
if (wereAutoLabelUsages) {
|
||||||
val psiFactory = JetPsiFactory(function)
|
val psiFactory = JetPsiFactory(function)
|
||||||
val newFunction = psiFactory.createExpressionByPattern("$name@ $0", function)
|
val newFunction = psiFactory.createExpressionByPattern("$0@ $1", name, function)
|
||||||
function.replace(newFunction)
|
function.replace(newFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public class ReplaceObsoleteLabelSyntaxFix(element: JetAnnotationEntry?) : JetIn
|
|||||||
val textRangeToRetain = TextRange(annotation.getTextRange().getEndOffset(), baseExpressionStart)
|
val textRangeToRetain = TextRange(annotation.getTextRange().getEndOffset(), baseExpressionStart)
|
||||||
val textToRetain = textRangeToRetain.substring(annotation.getContainingFile().getText())
|
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)
|
annotatedExpression.replace(labeledExpression)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ fun JetCallExpression.moveFunctionLiteralOutsideParentheses() {
|
|||||||
val expression = argument.getArgumentExpression()!!
|
val expression = argument.getArgumentExpression()!!
|
||||||
assert(expression.unpackFunctionLiteral() != null)
|
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()
|
val functionLiteralArgument = dummyCall.getFunctionLiteralArguments().single()
|
||||||
this.add(functionLiteralArgument)
|
this.add(functionLiteralArgument)
|
||||||
if (argumentList.getArguments().size() > 1) {
|
if (argumentList.getArguments().size() > 1) {
|
||||||
|
|||||||
Reference in New Issue
Block a user