Renames
This commit is contained in:
Generated
+1
-1
@@ -44,13 +44,13 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-analysis/idea-analysis.iml" filepath="$PROJECT_DIR$/idea/idea-analysis/idea-analysis.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-android/idea-android.iml" filepath="$PROJECT_DIR$/idea/idea-android/idea-android.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-android/idea-android-output-parser/idea-android-output-parser.iml" filepath="$PROJECT_DIR$/idea/idea-android/idea-android-output-parser/idea-android-output-parser.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-code-inliner/idea-replacement-engine.iml" filepath="$PROJECT_DIR$/idea/idea-code-inliner/idea-replacement-engine.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-completion/idea-completion.iml" filepath="$PROJECT_DIR$/idea/idea-completion/idea-completion.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-core/idea-core.iml" filepath="$PROJECT_DIR$/idea/idea-core/idea-core.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-jps-common/idea-jps-common.iml" filepath="$PROJECT_DIR$/idea/idea-jps-common/idea-jps-common.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-live-templates/idea-live-templates.iml" filepath="$PROJECT_DIR$/idea/idea-live-templates/idea-live-templates.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-maven/idea-maven.iml" filepath="$PROJECT_DIR$/idea/idea-maven/idea-maven.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" filepath="$PROJECT_DIR$/idea/idea-repl/idea-repl.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-replacement-engine/idea-replacement-engine.iml" filepath="$PROJECT_DIR$/idea/idea-replacement-engine/idea-replacement-engine.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea-runner/idea-runner.iml" filepath="$PROJECT_DIR$/idea-runner/idea-runner.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-test-framework/idea-test-framework.iml" filepath="$PROJECT_DIR$/idea/idea-test-framework/idea-test-framework.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/preloader/instrumentation/instrumentation.iml" filepath="$PROJECT_DIR$/compiler/preloader/instrumentation/instrumentation.iml" group="compiler/cli" />
|
||||
|
||||
+3
-3
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.replacement
|
||||
package org.jetbrains.kotlin.idea.inliner
|
||||
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.intentions.OperatorToFunctionIntention
|
||||
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
|
||||
class CallableUsageReplacementStrategy(
|
||||
private val replacement: ReplacementCode
|
||||
private val replacement: CodeToInline
|
||||
) : UsageReplacementStrategy {
|
||||
|
||||
override fun createReplacer(usage: KtSimpleNameExpression): (() -> KtElement?)? {
|
||||
@@ -44,7 +44,7 @@ class CallableUsageReplacementStrategy(
|
||||
createReplacer(nameExpression)!!.invoke()
|
||||
}
|
||||
else {
|
||||
CallReplacementEngine(usage, bindingContext, resolvedCall, callElement, replacement).performReplacement()
|
||||
CodeInliner(usage, bindingContext, resolvedCall, callElement, replacement).doInline()
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.replacement
|
||||
package org.jetbrains.kotlin.idea.inliner
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
|
||||
class ClassUsageReplacementStrategy(
|
||||
typeReplacement: KtUserType?,
|
||||
constructorReplacement: ReplacementCode?,
|
||||
constructorReplacement: CodeToInline?,
|
||||
project: Project
|
||||
) : UsageReplacementStrategy {
|
||||
|
||||
+37
-37
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.replacement
|
||||
package org.jetbrains.kotlin.idea.inliner
|
||||
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.PsiElement
|
||||
@@ -45,18 +45,18 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
|
||||
class CallReplacementEngine<TCallElement : KtElement>(
|
||||
class CodeInliner<TCallElement : KtElement>(
|
||||
private val nameExpression: KtSimpleNameExpression,
|
||||
private val bindingContext: BindingContext,
|
||||
private val resolvedCall: ResolvedCall<out CallableDescriptor>,
|
||||
private val callElement: TCallElement,
|
||||
replacement: ReplacementCode
|
||||
codeToInline: CodeToInline
|
||||
) {
|
||||
private val replacement = replacement.toMutable()
|
||||
private val codeToInline = codeToInline.toMutable()
|
||||
private val project = nameExpression.project
|
||||
private val psiFactory = KtPsiFactory(project)
|
||||
|
||||
fun performReplacement(): KtElement? {
|
||||
fun doInline(): KtElement? {
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
val file = nameExpression.getContainingKtFile()
|
||||
|
||||
@@ -82,9 +82,9 @@ class CallReplacementEngine<TCallElement : KtElement>(
|
||||
receiver?.mark(RECEIVER_VALUE_KEY)
|
||||
|
||||
//TODO: this@
|
||||
for (thisExpression in replacement.collectDescendantsOfType<KtThisExpression>()) {
|
||||
for (thisExpression in codeToInline.collectDescendantsOfType<KtThisExpression>()) {
|
||||
if (receiver != null) {
|
||||
replacement.replaceExpression(thisExpression, receiver)
|
||||
codeToInline.replaceExpression(thisExpression, receiver)
|
||||
}
|
||||
else {
|
||||
thisExpression.mark(RECEIVER_VALUE_KEY)
|
||||
@@ -104,25 +104,25 @@ class CallReplacementEngine<TCallElement : KtElement>(
|
||||
|
||||
if (elementToBeReplaced is KtExpression) {
|
||||
if (receiver != null) {
|
||||
val thisReplaced = replacement.collectDescendantsOfType<KtExpression> { it[RECEIVER_VALUE_KEY] }
|
||||
val thisReplaced = codeToInline.collectDescendantsOfType<KtExpression> { it[RECEIVER_VALUE_KEY] }
|
||||
if (receiver.shouldKeepValue(thisReplaced.size)) {
|
||||
replacement.introduceValue(receiver, receiverType, thisReplaced, elementToBeReplaced)
|
||||
codeToInline.introduceValue(receiver, receiverType, thisReplaced, elementToBeReplaced)
|
||||
}
|
||||
}
|
||||
|
||||
for ((parameter, value, valueType) in introduceValuesForParameters) {
|
||||
val usagesReplaced = replacement.collectDescendantsOfType<KtExpression> { it[PARAMETER_VALUE_KEY] == parameter }
|
||||
replacement.introduceValue(value, valueType, usagesReplaced, elementToBeReplaced, nameSuggestion = parameter.name.asString())
|
||||
val usagesReplaced = codeToInline.collectDescendantsOfType<KtExpression> { it[PARAMETER_VALUE_KEY] == parameter }
|
||||
codeToInline.introduceValue(value, valueType, usagesReplaced, elementToBeReplaced, nameSuggestion = parameter.name.asString())
|
||||
}
|
||||
}
|
||||
|
||||
replacement.fqNamesToImport
|
||||
codeToInline.fqNamesToImport
|
||||
.flatMap { file.resolveImportReference(it) }
|
||||
.forEach { ImportInsertHelper.getInstance(project).importDescriptor(file, it) }
|
||||
|
||||
val replacementPerformer = when (elementToBeReplaced) {
|
||||
is KtExpression -> ExpressionReplacementPerformer(replacement, elementToBeReplaced)
|
||||
is KtAnnotationEntry -> AnnotationEntryReplacementPerformer(replacement, elementToBeReplaced)
|
||||
is KtExpression -> ExpressionReplacementPerformer(codeToInline, elementToBeReplaced)
|
||||
is KtAnnotationEntry -> AnnotationEntryReplacementPerformer(codeToInline, elementToBeReplaced)
|
||||
else -> error("Unsupported element")
|
||||
}
|
||||
|
||||
@@ -146,8 +146,8 @@ class CallReplacementEngine<TCallElement : KtElement>(
|
||||
argument.expression.put(PARAMETER_VALUE_KEY, parameter)
|
||||
|
||||
val parameterName = parameter.name
|
||||
val usages = replacement.collectDescendantsOfType<KtExpression> {
|
||||
it[ReplacementCode.PARAMETER_USAGE_KEY] == parameterName
|
||||
val usages = codeToInline.collectDescendantsOfType<KtExpression> {
|
||||
it[CodeToInline.PARAMETER_USAGE_KEY] == parameterName
|
||||
}
|
||||
usages.forEach {
|
||||
val usageArgument = it.parent as? KtValueArgument
|
||||
@@ -157,7 +157,7 @@ class CallReplacementEngine<TCallElement : KtElement>(
|
||||
if (argument.isDefaultValue) {
|
||||
usageArgument?.mark(DEFAULT_PARAMETER_VALUE_KEY)
|
||||
}
|
||||
replacement.replaceExpression(it, argument.expression)
|
||||
codeToInline.replaceExpression(it, argument.expression)
|
||||
}
|
||||
|
||||
//TODO: sometimes we need to add explicit type arguments here because we don't have expected type in the new context
|
||||
@@ -185,8 +185,8 @@ class CallReplacementEngine<TCallElement : KtElement>(
|
||||
|
||||
for ((index, typeParameter) in typeParameters.withIndex()) {
|
||||
val parameterName = typeParameter.name
|
||||
val usages = replacement.collectDescendantsOfType<KtExpression> {
|
||||
it[ReplacementCode.TYPE_PARAMETER_USAGE_KEY] == parameterName
|
||||
val usages = codeToInline.collectDescendantsOfType<KtExpression> {
|
||||
it[CodeToInline.TYPE_PARAMETER_USAGE_KEY] == parameterName
|
||||
}
|
||||
|
||||
val type = resolvedCall.typeArguments[typeParameter]!!
|
||||
@@ -207,7 +207,7 @@ class CallReplacementEngine<TCallElement : KtElement>(
|
||||
val arguments =
|
||||
if (typeElement is KtUserType && KotlinBuiltIns.isArray(type)) typeElement.typeArgumentList?.text.orEmpty()
|
||||
else ""
|
||||
replacement.replaceExpression(usage, psiFactory.createExpression(
|
||||
codeToInline.replaceExpression(usage, psiFactory.createExpression(
|
||||
IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(typeClassifier) + arguments
|
||||
))
|
||||
}
|
||||
@@ -216,21 +216,21 @@ class CallReplacementEngine<TCallElement : KtElement>(
|
||||
}
|
||||
else {
|
||||
//TODO: tests for this?
|
||||
replacement.replaceExpression(usage, psiFactory.createExpression(typeElement.text))
|
||||
codeToInline.replaceExpression(usage, psiFactory.createExpression(typeElement.text))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun wrapCodeForSafeCall(receiver: KtExpression, receiverType: KotlinType?, expressionToBeReplaced: KtExpression) {
|
||||
if (replacement.statementsBefore.isEmpty()) {
|
||||
val qualified = replacement.mainExpression as? KtQualifiedExpression
|
||||
if (codeToInline.statementsBefore.isEmpty()) {
|
||||
val qualified = codeToInline.mainExpression as? KtQualifiedExpression
|
||||
if (qualified != null) {
|
||||
if (qualified.receiverExpression[RECEIVER_VALUE_KEY]) {
|
||||
if (qualified is KtSafeQualifiedExpression) return // already safe
|
||||
val selector = qualified.selectorExpression
|
||||
if (selector != null) {
|
||||
replacement.mainExpression = psiFactory.createExpressionByPattern("$0?.$1", receiver, selector)
|
||||
codeToInline.mainExpression = psiFactory.createExpressionByPattern("$0?.$1", receiver, selector)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -238,32 +238,32 @@ class CallReplacementEngine<TCallElement : KtElement>(
|
||||
}
|
||||
|
||||
if (expressionToBeReplaced.isUsedAsExpression(bindingContext)) {
|
||||
val thisReplaced = replacement.collectDescendantsOfType<KtExpression> { it[RECEIVER_VALUE_KEY] }
|
||||
replacement.introduceValue(receiver, receiverType, thisReplaced, expressionToBeReplaced, safeCall = true)
|
||||
val thisReplaced = codeToInline.collectDescendantsOfType<KtExpression> { it[RECEIVER_VALUE_KEY] }
|
||||
codeToInline.introduceValue(receiver, receiverType, thisReplaced, expressionToBeReplaced, safeCall = true)
|
||||
}
|
||||
else {
|
||||
val ifExpression = psiFactory.buildExpression {
|
||||
appendFixedText("if (")
|
||||
appendExpression(receiver)
|
||||
appendFixedText("!=null) {")
|
||||
replacement.statementsBefore.forEach {
|
||||
codeToInline.statementsBefore.forEach {
|
||||
appendExpression(it)
|
||||
appendFixedText("\n")
|
||||
}
|
||||
replacement.mainExpression?.let {
|
||||
codeToInline.mainExpression?.let {
|
||||
appendExpression(it)
|
||||
appendFixedText("\n")
|
||||
}
|
||||
appendFixedText("}")
|
||||
}
|
||||
replacement.mainExpression = ifExpression
|
||||
replacement.statementsBefore.clear()
|
||||
codeToInline.mainExpression = ifExpression
|
||||
codeToInline.statementsBefore.clear()
|
||||
}
|
||||
}
|
||||
|
||||
private fun keepInfixFormIfPossible() {
|
||||
if (replacement.statementsBefore.isNotEmpty()) return
|
||||
val dotQualified = replacement.mainExpression as? KtDotQualifiedExpression ?: return
|
||||
if (codeToInline.statementsBefore.isNotEmpty()) return
|
||||
val dotQualified = codeToInline.mainExpression as? KtDotQualifiedExpression ?: return
|
||||
val receiver = dotQualified.receiverExpression
|
||||
if (!receiver[RECEIVER_VALUE_KEY]) return
|
||||
val call = dotQualified.selectorExpression as? KtCallExpression ?: return
|
||||
@@ -271,7 +271,7 @@ class CallReplacementEngine<TCallElement : KtElement>(
|
||||
val argument = call.valueArguments.singleOrNull() ?: return
|
||||
if (argument.getArgumentName() != null) return
|
||||
val argumentExpression = argument.getArgumentExpression() ?: return
|
||||
replacement.mainExpression = psiFactory.createExpressionByPattern("$0 ${nameExpression.text} $1", receiver, argumentExpression)
|
||||
codeToInline.mainExpression = psiFactory.createExpressionByPattern("$0 ${nameExpression.text} $1", receiver, argumentExpression)
|
||||
}
|
||||
|
||||
private fun KtExpression?.shouldKeepValue(usageCount: Int): Boolean {
|
||||
@@ -317,13 +317,13 @@ class CallReplacementEngine<TCallElement : KtElement>(
|
||||
val (expression, parameterUsages) = defaultValue
|
||||
|
||||
for ((param, usages) in parameterUsages) {
|
||||
usages.forEach { it.put(ReplacementCode.PARAMETER_USAGE_KEY, param.name) }
|
||||
usages.forEach { it.put(CodeToInline.PARAMETER_USAGE_KEY, param.name) }
|
||||
}
|
||||
|
||||
val expressionCopy = expression.copied()
|
||||
|
||||
// clean up user data in original
|
||||
expression.forEachDescendantOfType<KtExpression> { it.clear(ReplacementCode.PARAMETER_USAGE_KEY) }
|
||||
expression.forEachDescendantOfType<KtExpression> { it.clear(CodeToInline.PARAMETER_USAGE_KEY) }
|
||||
|
||||
return Argument(expressionCopy, null/*TODO*/, isDefaultValue = true)
|
||||
}
|
||||
@@ -395,8 +395,8 @@ class CallReplacementEngine<TCallElement : KtElement>(
|
||||
// clean up user data
|
||||
it.forEachDescendantOfType<KtExpression> {
|
||||
it.clear(USER_CODE_KEY)
|
||||
it.clear(ReplacementCode.PARAMETER_USAGE_KEY)
|
||||
it.clear(ReplacementCode.TYPE_PARAMETER_USAGE_KEY)
|
||||
it.clear(CodeToInline.PARAMETER_USAGE_KEY)
|
||||
it.clear(CodeToInline.TYPE_PARAMETER_USAGE_KEY)
|
||||
it.clear(PARAMETER_VALUE_KEY)
|
||||
it.clear(RECEIVER_VALUE_KEY)
|
||||
it.clear(WAS_FUNCTION_LITERAL_ARGUMENT_KEY)
|
||||
+6
-6
@@ -14,25 +14,25 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.replacement
|
||||
package org.jetbrains.kotlin.idea.inliner
|
||||
|
||||
import com.intellij.openapi.util.Key
|
||||
import org.jetbrains.kotlin.idea.replacement.ReplacementCode.Companion.PARAMETER_USAGE_KEY
|
||||
import org.jetbrains.kotlin.idea.replacement.ReplacementCode.Companion.TYPE_PARAMETER_USAGE_KEY
|
||||
import org.jetbrains.kotlin.idea.inliner.CodeToInline.Companion.PARAMETER_USAGE_KEY
|
||||
import org.jetbrains.kotlin.idea.inliner.CodeToInline.Companion.TYPE_PARAMETER_USAGE_KEY
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
|
||||
/**
|
||||
* Represents an expression to replace usages of particular callable.
|
||||
* Represents code to be inlined to replace usages of particular callable.
|
||||
* The expression should be preprocessed in the following way:
|
||||
* * Type arguments for all calls should be made explicit
|
||||
* * All external symbols to be imported should be either referenced via fully-qualified form or included into [fqNamesToImport]
|
||||
* * All usages of value parameters (of our callable) should be marked with [PARAMETER_USAGE_KEY] copyable user data (holds the name of the corresponding parameter)
|
||||
* * All usages of type parameters (of our callable) should be marked with [TYPE_PARAMETER_USAGE_KEY] copyable user data (holds the name of the corresponding type parameter)
|
||||
* Use [ReplacementBuilder.buildReplacementCode].
|
||||
* Use [CodeToInlineBuilder.prepareCodeToInline].
|
||||
*/
|
||||
class ReplacementCode(
|
||||
class CodeToInline(
|
||||
val mainExpression: KtExpression?,
|
||||
val statementsBefore: List<KtExpression>,
|
||||
val fqNamesToImport: Collection<FqName>
|
||||
+7
-7
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.replacement
|
||||
package org.jetbrains.kotlin.idea.inliner
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
@@ -36,21 +36,21 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||
import java.util.*
|
||||
|
||||
class ReplacementBuilder(
|
||||
class CodeToInlineBuilder(
|
||||
private val targetCallable: CallableDescriptor,
|
||||
private val resolutionFacade: ResolutionFacade
|
||||
) {
|
||||
private val psiFactory = KtPsiFactory(resolutionFacade.project)
|
||||
|
||||
fun buildReplacementCode(
|
||||
fun prepareCodeToInline(
|
||||
mainExpression: KtExpression?,
|
||||
statementsBefore: List<KtExpression>,
|
||||
analyze: () -> BindingContext,
|
||||
importFqNames: Collection<FqName> = emptyList()
|
||||
): ReplacementCode {
|
||||
): CodeToInline {
|
||||
var bindingContext = analyze()
|
||||
|
||||
val result = MutableReplacementCode(mainExpression, statementsBefore.toMutableList(), importFqNames.toMutableSet())
|
||||
val result = MutableCodeToInline(mainExpression, statementsBefore.toMutableList(), importFqNames.toMutableSet())
|
||||
|
||||
val typeArgsToAdd = ArrayList<Pair<KtCallExpression, KtTypeArgumentList>>()
|
||||
result.forEachDescendantOfType<KtCallExpression> {
|
||||
@@ -80,10 +80,10 @@ class ReplacementBuilder(
|
||||
|
||||
if (expression.getReceiverExpression() == null) {
|
||||
if (target is ValueParameterDescriptor && target.containingDeclaration == targetCallable) {
|
||||
expression.putCopyableUserData(ReplacementCode.PARAMETER_USAGE_KEY, target.name)
|
||||
expression.putCopyableUserData(CodeToInline.PARAMETER_USAGE_KEY, target.name)
|
||||
}
|
||||
else if (target is TypeParameterDescriptor && target.containingDeclaration == targetCallable) {
|
||||
expression.putCopyableUserData(ReplacementCode.TYPE_PARAMETER_USAGE_KEY, target.name)
|
||||
expression.putCopyableUserData(CodeToInline.TYPE_PARAMETER_USAGE_KEY, target.name)
|
||||
}
|
||||
|
||||
val resolvedCall = expression.getResolvedCall(bindingContext)
|
||||
+8
-8
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.replacement
|
||||
package org.jetbrains.kotlin.idea.inliner
|
||||
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.PsiElement
|
||||
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||
|
||||
private val POST_INSERTION_ACTION: Key<(KtElement) -> Unit> = Key("POST_INSERTION_ACTION")
|
||||
|
||||
internal class MutableReplacementCode(
|
||||
internal class MutableCodeToInline(
|
||||
var mainExpression: KtExpression?,
|
||||
val statementsBefore: MutableList<KtExpression>,
|
||||
val fqNamesToImport: MutableCollection<FqName>
|
||||
@@ -81,22 +81,22 @@ internal class MutableReplacementCode(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ReplacementCode.toMutable(): MutableReplacementCode {
|
||||
return MutableReplacementCode(
|
||||
internal fun CodeToInline.toMutable(): MutableCodeToInline {
|
||||
return MutableCodeToInline(
|
||||
mainExpression?.copied(),
|
||||
statementsBefore.map { it.copied() }.toMutableList(),
|
||||
fqNamesToImport.toMutableSet())
|
||||
}
|
||||
|
||||
internal fun MutableReplacementCode.toNonMutable(): ReplacementCode {
|
||||
return ReplacementCode(mainExpression, statementsBefore, fqNamesToImport)
|
||||
internal fun MutableCodeToInline.toNonMutable(): CodeToInline {
|
||||
return CodeToInline(mainExpression, statementsBefore, fqNamesToImport)
|
||||
}
|
||||
|
||||
internal inline fun <reified T : PsiElement> MutableReplacementCode.collectDescendantsOfType(noinline predicate: (T) -> Boolean = { true }): List<T> {
|
||||
internal inline fun <reified T : PsiElement> MutableCodeToInline.collectDescendantsOfType(noinline predicate: (T) -> Boolean = { true }): List<T> {
|
||||
return expressions.flatMap { it.collectDescendantsOfType<T>({ true }, predicate) }
|
||||
}
|
||||
|
||||
internal inline fun <reified T : PsiElement> MutableReplacementCode.forEachDescendantOfType(noinline action: (T) -> Unit) {
|
||||
internal inline fun <reified T : PsiElement> MutableCodeToInline.forEachDescendantOfType(noinline action: (T) -> Unit) {
|
||||
expressions.forEach { it.forEachDescendantOfType<T>(action) }
|
||||
}
|
||||
|
||||
+14
-14
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.replacement
|
||||
package org.jetbrains.kotlin.idea.inliner
|
||||
|
||||
import com.intellij.openapi.util.Key
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||
import java.util.*
|
||||
|
||||
internal abstract class ReplacementPerformer<TElement : KtElement>(
|
||||
protected val replacement: MutableReplacementCode,
|
||||
protected val codeToInline: MutableCodeToInline,
|
||||
protected var elementToBeReplaced: TElement
|
||||
) {
|
||||
protected val psiFactory = KtPsiFactory(elementToBeReplaced)
|
||||
@@ -40,18 +40,18 @@ internal abstract class ReplacementPerformer<TElement : KtElement>(
|
||||
}
|
||||
|
||||
internal class AnnotationEntryReplacementPerformer(
|
||||
replacement: MutableReplacementCode,
|
||||
codeToInline: MutableCodeToInline,
|
||||
elementToBeReplaced: KtAnnotationEntry
|
||||
) : ReplacementPerformer<KtAnnotationEntry>(replacement, elementToBeReplaced) {
|
||||
) : ReplacementPerformer<KtAnnotationEntry>(codeToInline, elementToBeReplaced) {
|
||||
|
||||
override fun doIt(postProcessing: (PsiChildRange) -> PsiChildRange): KtAnnotationEntry {
|
||||
assert(replacement.mainExpression != null)
|
||||
assert(replacement.statementsBefore.isEmpty())
|
||||
assert(codeToInline.mainExpression != null)
|
||||
assert(codeToInline.statementsBefore.isEmpty())
|
||||
|
||||
val dummyAnnotationEntry = createByPattern("@Dummy($0)", replacement.mainExpression!!) { psiFactory.createAnnotationEntry(it) }
|
||||
val dummyAnnotationEntry = createByPattern("@Dummy($0)", codeToInline.mainExpression!!) { psiFactory.createAnnotationEntry(it) }
|
||||
val replaced = elementToBeReplaced.replace(dummyAnnotationEntry)
|
||||
|
||||
replacement.performPostInsertionActions(replaced.singletonList())
|
||||
codeToInline.performPostInsertionActions(replaced.singletonList())
|
||||
|
||||
var range = PsiChildRange.singleElement(replaced)
|
||||
range = postProcessing(range)
|
||||
@@ -65,13 +65,13 @@ internal class AnnotationEntryReplacementPerformer(
|
||||
}
|
||||
|
||||
internal class ExpressionReplacementPerformer(
|
||||
replacement: MutableReplacementCode,
|
||||
codeToInline: MutableCodeToInline,
|
||||
expressionToBeReplaced: KtExpression
|
||||
) : ReplacementPerformer<KtExpression>(replacement, expressionToBeReplaced) {
|
||||
) : ReplacementPerformer<KtExpression>(codeToInline, expressionToBeReplaced) {
|
||||
|
||||
override fun doIt(postProcessing: (PsiChildRange) -> PsiChildRange): KtExpression? {
|
||||
val insertedStatements = ArrayList<KtExpression>()
|
||||
for (statement in replacement.statementsBefore) {
|
||||
for (statement in codeToInline.statementsBefore) {
|
||||
// copy the statement if it can get invalidated by findOrCreateBlockToInsertStatement()
|
||||
val statementToUse = if (statement.isPhysical) statement.copy() else statement
|
||||
val anchor = findOrCreateBlockToInsertStatement()
|
||||
@@ -83,8 +83,8 @@ internal class ExpressionReplacementPerformer(
|
||||
insertedStatements.add(inserted)
|
||||
}
|
||||
|
||||
val replaced = if (replacement.mainExpression != null) {
|
||||
elementToBeReplaced.replace(replacement.mainExpression!!)
|
||||
val replaced = if (codeToInline.mainExpression != null) {
|
||||
elementToBeReplaced.replace(codeToInline.mainExpression!!)
|
||||
}
|
||||
else {
|
||||
val bindingContext = elementToBeReplaced.analyze(BodyResolveMode.FULL)
|
||||
@@ -98,7 +98,7 @@ internal class ExpressionReplacementPerformer(
|
||||
}
|
||||
}
|
||||
|
||||
replacement.performPostInsertionActions(insertedStatements + replaced.singletonOrEmptyList())
|
||||
codeToInline.performPostInsertionActions(insertedStatements + replaced.singletonOrEmptyList())
|
||||
|
||||
var range = if (replaced != null) {
|
||||
if (insertedStatements.isEmpty()) {
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.replacement
|
||||
package org.jetbrains.kotlin.idea.inliner
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
+6
-6
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.replacement
|
||||
package org.jetbrains.kotlin.idea.inliner
|
||||
|
||||
import org.jetbrains.kotlin.idea.analysis.computeTypeInContext
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
@@ -38,17 +38,17 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
|
||||
/**
|
||||
* Modifies [MutableReplacementCode] introducing a variable initialized by [value] and replacing all of [usages] with its use.
|
||||
* The variable must be initialized (and so the value is calculated) before any other code in [MutableReplacementCode].
|
||||
* Modifies [MutableCodeToInline] introducing a variable initialized by [value] and replacing all of [usages] with its use.
|
||||
* The variable must be initialized (and so the value is calculated) before any other code in [MutableCodeToInline].
|
||||
* @param value Value to use for variable initialization
|
||||
* @param valueType Type of the value
|
||||
* @param usages Usages to be replaced. This collection can be empty and in this case the actual variable is not needed.
|
||||
* But the expression [value] must be calculated because it may have side effects.
|
||||
* @param expressionToBeReplaced Expression to be replaced by the [MutableReplacementCode].
|
||||
* @param expressionToBeReplaced Expression to be replaced by the [MutableCodeToInline].
|
||||
* @param nameSuggestion Name suggestion for the variable.
|
||||
* @param safeCall If true, then the whole code must not be executed if the [value] evaluates to null.
|
||||
*/
|
||||
internal fun MutableReplacementCode.introduceValue(
|
||||
internal fun MutableCodeToInline.introduceValue(
|
||||
value: KtExpression,
|
||||
valueType: KotlinType?,
|
||||
usages: Collection<KtExpression>,
|
||||
@@ -151,7 +151,7 @@ private fun variableNeedsExplicitType(
|
||||
return valueTypeWithoutExpectedType == null || ErrorUtils.containsErrorType(valueTypeWithoutExpectedType)
|
||||
}
|
||||
|
||||
private fun collectNameUsages(scope: MutableReplacementCode, name: String): List<KtSimpleNameExpression> {
|
||||
private fun collectNameUsages(scope: MutableCodeToInline, name: String): List<KtSimpleNameExpression> {
|
||||
return scope.expressions.flatMap { expression ->
|
||||
expression.collectDescendantsOfType<KtSimpleNameExpression> { it.getReceiverExpression() == null && it.getReferencedName() == name }
|
||||
}
|
||||
+1
-1
@@ -55,6 +55,6 @@
|
||||
<orderEntry type="module" module-name="formatter" />
|
||||
<orderEntry type="module" module-name="idea-maven" />
|
||||
<orderEntry type="library" scope="TEST" name="native-platform-uberjar" level="project" />
|
||||
<orderEntry type="module" module-name="idea-replacement-engine" />
|
||||
<orderEntry type="module" module-name="idea-code-inliner" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.idea.core.moveCaret
|
||||
import org.jetbrains.kotlin.idea.core.targetDescriptors
|
||||
import org.jetbrains.kotlin.idea.quickfix.CleanupFix
|
||||
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
|
||||
import org.jetbrains.kotlin.idea.replacement.UsageReplacementStrategy
|
||||
import org.jetbrains.kotlin.idea.inliner.UsageReplacementStrategy
|
||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||
|
||||
+3
-3
@@ -31,9 +31,9 @@ import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.core.OptionalParametersHelper
|
||||
import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.replacement.CallableUsageReplacementStrategy
|
||||
import org.jetbrains.kotlin.idea.replacement.ClassUsageReplacementStrategy
|
||||
import org.jetbrains.kotlin.idea.replacement.UsageReplacementStrategy
|
||||
import org.jetbrains.kotlin.idea.inliner.CallableUsageReplacementStrategy
|
||||
import org.jetbrains.kotlin.idea.inliner.ClassUsageReplacementStrategy
|
||||
import org.jetbrains.kotlin.idea.inliner.UsageReplacementStrategy
|
||||
import org.jetbrains.kotlin.psi.KtConstructorCalleeExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
|
||||
+2
-2
@@ -23,8 +23,8 @@ import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.replacement.UsageReplacementStrategy
|
||||
import org.jetbrains.kotlin.idea.replacement.replaceUsagesInWholeProject
|
||||
import org.jetbrains.kotlin.idea.inliner.UsageReplacementStrategy
|
||||
import org.jetbrains.kotlin.idea.inliner.replaceUsagesInWholeProject
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.renderer.ClassifierNamePolicy
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
|
||||
+6
-6
@@ -21,8 +21,8 @@ import org.jetbrains.kotlin.idea.analysis.analyzeInContext
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.replacement.ReplacementBuilder
|
||||
import org.jetbrains.kotlin.idea.replacement.ReplacementCode
|
||||
import org.jetbrains.kotlin.idea.inliner.CodeToInlineBuilder
|
||||
import org.jetbrains.kotlin.idea.inliner.CodeToInline
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -50,7 +50,7 @@ object ReplaceWithAnnotationAnalyzer {
|
||||
annotation: ReplaceWith,
|
||||
symbolDescriptor: CallableDescriptor,
|
||||
resolutionFacade: ResolutionFacade
|
||||
): ReplacementCode? {
|
||||
): CodeToInline? {
|
||||
val originalDescriptor = (if (symbolDescriptor is CallableMemberDescriptor)
|
||||
DescriptorUtils.unwrapFakeOverride(symbolDescriptor)
|
||||
else
|
||||
@@ -62,7 +62,7 @@ object ReplaceWithAnnotationAnalyzer {
|
||||
annotation: ReplaceWith,
|
||||
symbolDescriptor: CallableDescriptor,
|
||||
resolutionFacade: ResolutionFacade
|
||||
): ReplacementCode? {
|
||||
): CodeToInline? {
|
||||
val psiFactory = KtPsiFactory(resolutionFacade.project)
|
||||
val expression = try {
|
||||
psiFactory.createExpression(annotation.pattern)
|
||||
@@ -89,8 +89,8 @@ object ReplaceWithAnnotationAnalyzer {
|
||||
return expression.analyzeInContext(scope, expressionTypingServices = expressionTypingServices)
|
||||
}
|
||||
|
||||
return ReplacementBuilder(symbolDescriptor, resolutionFacade)
|
||||
.buildReplacementCode(expression, emptyList(), ::analyzeExpression, importFqNames = importFqNames(annotation))
|
||||
return CodeToInlineBuilder(symbolDescriptor, resolutionFacade)
|
||||
.prepareCodeToInline(expression, emptyList(), ::analyzeExpression, importFqNames = importFqNames(annotation))
|
||||
}
|
||||
|
||||
fun analyzeClassReplacement(
|
||||
|
||||
+7
-7
@@ -29,9 +29,9 @@ import org.jetbrains.kotlin.idea.analysis.analyzeInContext
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.copied
|
||||
import org.jetbrains.kotlin.idea.replacement.CallableUsageReplacementStrategy
|
||||
import org.jetbrains.kotlin.idea.replacement.ReplacementBuilder
|
||||
import org.jetbrains.kotlin.idea.replacement.replaceUsagesInWholeProject
|
||||
import org.jetbrains.kotlin.idea.inliner.CallableUsageReplacementStrategy
|
||||
import org.jetbrains.kotlin.idea.inliner.CodeToInlineBuilder
|
||||
import org.jetbrains.kotlin.idea.inliner.replaceUsagesInWholeProject
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
@@ -67,21 +67,21 @@ class KotlinInlineFunctionHandler: InlineActionHandler() {
|
||||
expectedType = expectedType)
|
||||
}
|
||||
|
||||
val replacementBuilder = ReplacementBuilder(descriptor, element.getResolutionFacade())
|
||||
val replacementBuilder = CodeToInlineBuilder(descriptor, element.getResolutionFacade())
|
||||
val replacement = if (element.hasBlockBody()) {
|
||||
bodyCopy as KtBlockExpression
|
||||
val statements = bodyCopy.statements
|
||||
//TODO: check no other return's!
|
||||
val lastReturn = statements.lastOrNull() as? KtReturnExpression
|
||||
if (lastReturn != null) {
|
||||
replacementBuilder.buildReplacementCode(lastReturn.returnedExpression, statements.dropLast(1), ::analyzeBodyCopy)
|
||||
replacementBuilder.prepareCodeToInline(lastReturn.returnedExpression, statements.dropLast(1), ::analyzeBodyCopy)
|
||||
}
|
||||
else {
|
||||
replacementBuilder.buildReplacementCode(null, statements, ::analyzeBodyCopy)
|
||||
replacementBuilder.prepareCodeToInline(null, statements, ::analyzeBodyCopy)
|
||||
}
|
||||
}
|
||||
else {
|
||||
replacementBuilder.buildReplacementCode(bodyCopy, emptyList(), ::analyzeBodyCopy)
|
||||
replacementBuilder.prepareCodeToInline(bodyCopy, emptyList(), ::analyzeBodyCopy)
|
||||
}
|
||||
|
||||
val commandName = RefactoringBundle.message("inline.command", element.name)
|
||||
|
||||
Reference in New Issue
Block a user