From e296390dd6cdcba4405ac81c575d98599a41c9d6 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Wed, 24 Dec 2014 20:27:30 +0300 Subject: [PATCH] Introduce Variable: Do not create separate template to edit type reference #KT-4314 Fixed --- .../jet/lang/psi/JetCallableDeclaration.java | 1 + .../SpecifyTypeExplicitlyAction.java | 65 ++++++++++------- .../KotlinInplaceVariableIntroducer.java | 73 +++++++++++++++++-- 3 files changed, 105 insertions(+), 34 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallableDeclaration.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallableDeclaration.java index 84cef9a9181..b20acbe7846 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallableDeclaration.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallableDeclaration.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.lang.psi; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/idea/src/org/jetbrains/jet/plugin/intentions/SpecifyTypeExplicitlyAction.java b/idea/src/org/jetbrains/jet/plugin/intentions/SpecifyTypeExplicitlyAction.java index 38688908888..b3e65dde306 100644 --- a/idea/src/org/jetbrains/jet/plugin/intentions/SpecifyTypeExplicitlyAction.java +++ b/idea/src/org/jetbrains/jet/plugin/intentions/SpecifyTypeExplicitlyAction.java @@ -141,24 +141,8 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction { return type == null ? ErrorUtils.createErrorType("null type") : type; } - public static void addTypeAnnotation(Project project, @Nullable Editor editor, @NotNull JetCallableDeclaration declaration, @NotNull JetType exprType) { - if (editor != null) { - addTypeAnnotationWithTemplate(project, editor, declaration, exprType); - } - else { - declaration.setTypeReference(anyTypeRef(project)); - } - } - - private static void addTypeAnnotationWithTemplate( - @NotNull Project project, - @NotNull Editor editor, - @NotNull final JetCallableDeclaration declaration, - @NotNull JetType exprType - ) { - assert !exprType.isError() : "Unexpected error type, should have been checked before: " - + JetPsiUtil.getElementTextWithContext(declaration) + ", type = " + exprType; - + @NotNull + public static Expression createTypeExpressionForTemplate(JetType exprType) { ClassifierDescriptor descriptor = exprType.getConstructor().getDeclarationDescriptor(); boolean isAnonymous = descriptor != null && DescriptorUtils.isAnonymousObject(descriptor); @@ -166,7 +150,7 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction { List types = isAnonymous ? new ArrayList() : Lists.newArrayList(exprType); types.addAll(allSupertypes); - Expression expression = new JetTypeLookupExpression( + return new JetTypeLookupExpression( types, types.iterator().next(), JetBundle.message("specify.type.explicitly.add.action.name") @@ -181,6 +165,39 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction { return IdeDescriptorRenderers.SOURCE_CODE.renderType(element); } }; + } + + public static void addTypeAnnotation(Project project, @Nullable Editor editor, @NotNull JetCallableDeclaration declaration, @NotNull JetType exprType) { + if (editor != null) { + addTypeAnnotationWithTemplate(project, editor, declaration, exprType); + } + else { + declaration.setTypeReference(anyTypeRef(project)); + } + } + + public static TemplateEditingAdapter createTypeReferencePostprocessor(final JetCallableDeclaration declaration) { + return new TemplateEditingAdapter() { + @Override + public void templateFinished(Template template, boolean brokenOff) { + JetTypeReference typeRef = declaration.getTypeReference(); + if (typeRef != null) { + ShortenReferences.INSTANCE$.process(typeRef); + } + } + }; + } + + private static void addTypeAnnotationWithTemplate( + @NotNull Project project, + @NotNull Editor editor, + @NotNull JetCallableDeclaration declaration, + @NotNull JetType exprType + ) { + assert !exprType.isError() : "Unexpected error type, should have been checked before: " + + JetPsiUtil.getElementTextWithContext(declaration) + ", type = " + exprType; + + Expression expression = createTypeExpressionForTemplate(exprType); declaration.setTypeReference(anyTypeRef(project)); @@ -195,15 +212,7 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction { editor.getCaretModel().moveToOffset(newTypeRef.getNode().getStartOffset()); TemplateManagerImpl manager = new TemplateManagerImpl(project); - manager.startTemplate(editor, builder.buildInlineTemplate(), new TemplateEditingAdapter() { - @Override - public void templateFinished(Template template, boolean brokenOff) { - JetTypeReference typeRef = declaration.getTypeReference(); - if (typeRef != null) { - ShortenReferences.INSTANCE$.process(typeRef); - } - } - }); + manager.startTemplate(editor, builder.buildInlineTemplate(), createTypeReferencePostprocessor(declaration)); } private static JetTypeReference anyTypeRef(@NotNull Project project) { diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinInplaceVariableIntroducer.java b/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinInplaceVariableIntroducer.java index c55c70e6041..1cdbc915d20 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinInplaceVariableIntroducer.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinInplaceVariableIntroducer.java @@ -16,6 +16,9 @@ package org.jetbrains.jet.plugin.refactoring.introduce.introduceVariable; +import com.intellij.codeInsight.template.TemplateBuilderImpl; +import com.intellij.codeInsight.template.impl.TemplateManagerImpl; +import com.intellij.codeInsight.template.impl.TemplateState; import com.intellij.lang.ASTNode; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; @@ -23,25 +26,29 @@ import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiNamedElement; +import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.refactoring.introduce.inplace.InplaceVariableIntroducer; import com.intellij.ui.NonFocusableCheckBox; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetProperty; +import org.jetbrains.jet.lang.psi.JetPsiFactory; +import org.jetbrains.jet.lang.psi.JetTypeReference; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.intentions.SpecifyTypeExplicitlyAction; +import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Collection; +import java.util.LinkedHashSet; public class KotlinInplaceVariableIntroducer extends InplaceVariableIntroducer { @@ -117,12 +124,19 @@ public class KotlinInplaceVariableIntroducer extends InplaceVariableIntroducer getSuggestionsForNextRun() { + LinkedHashSet nameSuggestions; + String currentName = myProperty.getName(); + if (myNameSuggestions.contains(currentName)) { + nameSuggestions = myNameSuggestions; + } + else { + nameSuggestions = new LinkedHashSet(); + nameSuggestions.add(currentName); + nameSuggestions.addAll(myNameSuggestions); + } + return nameSuggestions; + } + + @Override + protected void addAdditionalVariables(TemplateBuilderImpl builder) { + JetTypeReference typeReference = myProperty.getTypeReference(); + if (typeReference != null) { + builder.replaceElement(typeReference, SpecifyTypeExplicitlyAction.createTypeExpressionForTemplate(myExprType)); + } + } + + @Override + protected boolean buildTemplateAndStart( + Collection refs, + Collection> stringUsages, + PsiElement scope, + PsiFile containingFile + ) { + myEditor.putUserData(INTRODUCE_RESTART, false); + //noinspection ConstantConditions + myEditor.getCaretModel().moveToOffset(getNameIdentifier().getTextOffset()); + boolean result = super.buildTemplateAndStart(refs, stringUsages, scope, containingFile); + + TemplateState templateState = + TemplateManagerImpl.getTemplateState(InjectedLanguageUtil.getTopLevelEditor(myEditor)); + if (templateState != null && myProperty.getTypeReference() != null) { + templateState.addTemplateStateListener(SpecifyTypeExplicitlyAction.createTypeReferencePostprocessor(myProperty)); + } + + return result; + } + @Override protected void moveOffsetAfter(boolean success) { if (!myReplaceOccurrence || myExprMarker == null) {