Introduce Property: Implement separate in-place introducer for properties
This commit is contained in:
@@ -181,7 +181,7 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction {
|
|||||||
@Override
|
@Override
|
||||||
public void templateFinished(Template template, boolean brokenOff) {
|
public void templateFinished(Template template, boolean brokenOff) {
|
||||||
JetTypeReference typeRef = declaration.getTypeReference();
|
JetTypeReference typeRef = declaration.getTypeReference();
|
||||||
if (typeRef != null) {
|
if (typeRef != null && typeRef.isValid()) {
|
||||||
ShortenReferences.DEFAULT.process(typeRef);
|
ShortenReferences.DEFAULT.process(typeRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+134
@@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* 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.refactoring.introduce.introduceProperty
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.*
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import com.intellij.openapi.project.*
|
||||||
|
import com.intellij.openapi.editor.*
|
||||||
|
import org.jetbrains.kotlin.types.*
|
||||||
|
import javax.swing.*
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinInplaceVariableIntroducer.ControlWrapper
|
||||||
|
import com.intellij.openapi.util.*
|
||||||
|
import com.intellij.ui.*
|
||||||
|
import javax.swing.event.*
|
||||||
|
import com.intellij.openapi.application.*
|
||||||
|
import com.intellij.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
|
import com.intellij.codeInsight.template.*
|
||||||
|
import org.jetbrains.kotlin.idea.intentions.*
|
||||||
|
|
||||||
|
public class KotlinInplacePropertyIntroducer(
|
||||||
|
property: JetProperty,
|
||||||
|
editor: Editor,
|
||||||
|
project: Project,
|
||||||
|
title: String,
|
||||||
|
doNotChangeVar: Boolean,
|
||||||
|
exprType: JetType?,
|
||||||
|
extractionResult: ExtractionResult,
|
||||||
|
private val availableTargets: List<ExtractionTarget>
|
||||||
|
): KotlinInplaceVariableIntroducer(
|
||||||
|
property, editor, project, title, JetExpression.EMPTY_ARRAY, null, false, property, false, doNotChangeVar, exprType, false
|
||||||
|
) {
|
||||||
|
{
|
||||||
|
assert(availableTargets.isNotEmpty(), "No targets available: ${JetPsiUtil.getElementTextWithContext(property)}")
|
||||||
|
}
|
||||||
|
|
||||||
|
private var extractionResult = extractionResult
|
||||||
|
|
||||||
|
private var currentTarget: ExtractionTarget = extractionResult.config.generatorOptions.target
|
||||||
|
set(value: ExtractionTarget) {
|
||||||
|
if (value == currentTarget) return
|
||||||
|
|
||||||
|
$currentTarget = value
|
||||||
|
runWriteActionAndRestartRefactoring {
|
||||||
|
with (extractionResult.config) {
|
||||||
|
extractionResult = copy(generatorOptions = generatorOptions.copy(target = currentTarget)).generateDeclaration(myProperty)
|
||||||
|
myProperty = extractionResult.declaration as JetProperty
|
||||||
|
myElementToRename = myProperty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updatePanelControls()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isInitializer(): Boolean = currentTarget == ExtractionTarget.PROPERTY_WITH_INITIALIZER
|
||||||
|
|
||||||
|
override fun initPanelControls() {
|
||||||
|
if (availableTargets.size() > 1) {
|
||||||
|
addPanelControl(
|
||||||
|
ControlWrapper {
|
||||||
|
val propertyKindComboBox = with(JComboBox(availableTargets.map { it.name.capitalize() }.copyToArray())) {
|
||||||
|
addPopupMenuListener(
|
||||||
|
object : PopupMenuListenerAdapter() {
|
||||||
|
override fun popupMenuWillBecomeInvisible(e: PopupMenuEvent?) {
|
||||||
|
ApplicationManager.getApplication().invokeLater {
|
||||||
|
currentTarget = availableTargets[getSelectedIndex()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
setSelectedIndex(availableTargets.indexOf(currentTarget))
|
||||||
|
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
val propertyKindLabel = JLabel("Introduce as: ")
|
||||||
|
propertyKindLabel.setDisplayedMnemonic('I')
|
||||||
|
propertyKindLabel.setLabelFor(propertyKindComboBox)
|
||||||
|
|
||||||
|
val panel = JPanel()
|
||||||
|
panel.add(propertyKindLabel)
|
||||||
|
panel.add(propertyKindComboBox)
|
||||||
|
|
||||||
|
panel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ExtractionTarget.PROPERTY_WITH_INITIALIZER in availableTargets) {
|
||||||
|
val condition = { isInitializer() }
|
||||||
|
|
||||||
|
getCreateVarCheckBox()?.let {
|
||||||
|
val initializer = object: Pass<JComponent>() {
|
||||||
|
override fun pass(t: JComponent) {
|
||||||
|
(t as JCheckBox).setSelected(myProperty.isVar())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addPanelControl(ControlWrapper(it, condition, initializer))
|
||||||
|
}
|
||||||
|
getCreateExplicitTypeCheckBox()?.let {
|
||||||
|
val initializer = object: Pass<JComponent>() {
|
||||||
|
override fun pass(t: JComponent) {
|
||||||
|
(t as JCheckBox).setSelected(myProperty.getTypeReference() != null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addPanelControl(ControlWrapper(it, condition, initializer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addTypeReferenceVariable(builder: TemplateBuilderImpl) {
|
||||||
|
if (!isInitializer()) return
|
||||||
|
super.addTypeReferenceVariable(builder)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun checkLocalScope(): PsiElement? {
|
||||||
|
return myElementToRename.parents().first { it is JetClassOrObject || it is JetFile }
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-14
@@ -29,7 +29,6 @@ import kotlin.test.*
|
|||||||
import com.intellij.openapi.application.*
|
import com.intellij.openapi.application.*
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceProperty.*
|
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceProperty.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.*
|
|
||||||
|
|
||||||
public class KotlinIntroducePropertyHandler(
|
public class KotlinIntroducePropertyHandler(
|
||||||
val helper: ExtractionEngineHelper = KotlinIntroducePropertyHandler.InteractiveExtractionHelper
|
val helper: ExtractionEngineHelper = KotlinIntroducePropertyHandler.InteractiveExtractionHelper
|
||||||
@@ -78,19 +77,15 @@ public class KotlinIntroducePropertyHandler(
|
|||||||
doPostponedOperationsAndUnblockDocument(editor.getDocument())
|
doPostponedOperationsAndUnblockDocument(editor.getDocument())
|
||||||
}
|
}
|
||||||
|
|
||||||
val introducer = KotlinInplaceVariableIntroducer(
|
val introducer = KotlinInplacePropertyIntroducer(
|
||||||
property,
|
property = property,
|
||||||
editor,
|
editor = editor,
|
||||||
project,
|
project = project,
|
||||||
INTRODUCE_PROPERTY, // title
|
title = INTRODUCE_PROPERTY,
|
||||||
JetExpression.EMPTY_ARRAY, // occurrences
|
doNotChangeVar = false,
|
||||||
null, // expr
|
exprType = descriptor.controlFlow.outputValueBoxer.returnType,
|
||||||
false, // replaceOccurrence
|
extractionResult = it,
|
||||||
property,
|
availableTargets = propertyTargets.filter { it.isAvailable(descriptor) }
|
||||||
false, // isVar
|
|
||||||
true, // doNotChangeVar
|
|
||||||
descriptor.controlFlow.outputValueBoxer.returnType,
|
|
||||||
true // noTypeInference
|
|
||||||
)
|
)
|
||||||
introducer.performInplaceRefactoring(LinkedHashSet(descriptor.suggestedNames))
|
introducer.performInplaceRefactoring(LinkedHashSet(descriptor.suggestedNames))
|
||||||
}
|
}
|
||||||
|
|||||||
+229
-106
@@ -27,12 +27,15 @@ import com.intellij.openapi.editor.Editor;
|
|||||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.intellij.openapi.util.Pair;
|
||||||
|
import com.intellij.openapi.util.Pass;
|
||||||
import com.intellij.openapi.util.Ref;
|
import com.intellij.openapi.util.Ref;
|
||||||
import com.intellij.openapi.util.TextRange;
|
import com.intellij.openapi.util.TextRange;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||||
import com.intellij.refactoring.introduce.inplace.InplaceVariableIntroducer;
|
import com.intellij.refactoring.introduce.inplace.InplaceVariableIntroducer;
|
||||||
import com.intellij.ui.NonFocusableCheckBox;
|
import com.intellij.ui.NonFocusableCheckBox;
|
||||||
|
import kotlin.Function0;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyAction;
|
import org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyAction;
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers;
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers;
|
||||||
@@ -47,19 +50,73 @@ import javax.swing.*;
|
|||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class KotlinInplaceVariableIntroducer extends InplaceVariableIntroducer<JetExpression> {
|
public class KotlinInplaceVariableIntroducer extends InplaceVariableIntroducer<JetExpression> {
|
||||||
|
private static final Function0<Boolean> TRUE = new Function0<Boolean>() {
|
||||||
|
@Override
|
||||||
|
public Boolean invoke() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final Pass<JComponent> DO_NOTHING = new Pass<JComponent>() {
|
||||||
|
@Override
|
||||||
|
public void pass(JComponent component) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected static final class ControlWrapper {
|
||||||
|
@NotNull
|
||||||
|
private final Function0<JComponent> factory;
|
||||||
|
@NotNull
|
||||||
|
private final Function0<Boolean> condition;
|
||||||
|
@NotNull
|
||||||
|
private final Pass<JComponent> initializer;
|
||||||
|
private JComponent component;
|
||||||
|
|
||||||
|
public ControlWrapper(
|
||||||
|
@NotNull Function0<JComponent> factory,
|
||||||
|
@NotNull Function0<Boolean> condition,
|
||||||
|
@NotNull Pass<JComponent> initializer) {
|
||||||
|
this.factory = factory;
|
||||||
|
this.condition = condition;
|
||||||
|
this.initializer = initializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ControlWrapper(@NotNull Function0<JComponent> factory) {
|
||||||
|
this(factory, TRUE, DO_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return condition.invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
|
initializer.pass(getComponent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JComponent getComponent() {
|
||||||
|
if (component == null) {
|
||||||
|
component = factory.invoke();
|
||||||
|
}
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final boolean myReplaceOccurrence;
|
private final boolean myReplaceOccurrence;
|
||||||
private final JetProperty myProperty;
|
protected JetProperty myProperty;
|
||||||
private final boolean isVar;
|
private final boolean isVar;
|
||||||
private final boolean myDoNotChangeVar;
|
private final boolean myDoNotChangeVar;
|
||||||
@Nullable private final JetType myExprType;
|
@Nullable private final JetType myExprType;
|
||||||
private final boolean noTypeInference;
|
private final boolean noTypeInference;
|
||||||
private JCheckBox myVarCheckbox;
|
private final List<ControlWrapper> panelControls = new ArrayList<ControlWrapper>();
|
||||||
private JCheckBox myExprTypeCheckbox;
|
private JPanel contentPanel;
|
||||||
|
|
||||||
public KotlinInplaceVariableIntroducer(
|
public KotlinInplaceVariableIntroducer(
|
||||||
PsiNamedElement elementToRename, Editor editor, Project project,
|
PsiNamedElement elementToRename, Editor editor, Project project,
|
||||||
@@ -77,119 +134,181 @@ public class KotlinInplaceVariableIntroducer extends InplaceVariableIntroducer<J
|
|||||||
this.noTypeInference = noTypeInference;
|
this.noTypeInference = noTypeInference;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@NotNull
|
||||||
@Nullable
|
private JPanel getContentPanel() {
|
||||||
protected JComponent getComponent() {
|
if (contentPanel == null) {
|
||||||
if (!myDoNotChangeVar) {
|
contentPanel = new JPanel(new GridBagLayout());
|
||||||
myVarCheckbox = new NonFocusableCheckBox("Declare with var");
|
contentPanel.setBorder(null);
|
||||||
myVarCheckbox.setSelected(isVar);
|
|
||||||
myVarCheckbox.setMnemonic('v');
|
|
||||||
myVarCheckbox.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
new WriteCommandAction(myProject, getCommandName(), getCommandName()) {
|
|
||||||
@Override
|
|
||||||
protected void run(Result result) throws Throwable {
|
|
||||||
PsiDocumentManager.getInstance(myProject).commitDocument(myEditor.getDocument());
|
|
||||||
|
|
||||||
JetPsiFactory psiFactory = new JetPsiFactory(myProject);
|
|
||||||
ASTNode node = myVarCheckbox.isSelected() ? psiFactory.createVarNode() : psiFactory.createValNode();
|
|
||||||
myProperty.getValOrVarNode().getPsi().replace(node.getPsi());
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myExprType != null && !noTypeInference) {
|
return contentPanel;
|
||||||
myExprTypeCheckbox = new NonFocusableCheckBox("Specify type explicitly");
|
}
|
||||||
myExprTypeCheckbox.setSelected(false);
|
|
||||||
myExprTypeCheckbox.setMnemonic('t');
|
|
||||||
myExprTypeCheckbox.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
final Ref<Boolean> greedyToRight = new Ref<Boolean>();
|
|
||||||
new WriteCommandAction(myProject, getCommandName(), getCommandName()) {
|
|
||||||
@Override
|
|
||||||
protected void run(Result result) throws Throwable {
|
|
||||||
PsiDocumentManager.getInstance(myProject).commitDocument(myEditor.getDocument());
|
|
||||||
if (myExprTypeCheckbox.isSelected()) {
|
|
||||||
ASTNode identifier = myProperty.getNode().findChildByType(JetTokens.IDENTIFIER);
|
|
||||||
if (identifier != null) {
|
|
||||||
TextRange range = identifier.getTextRange();
|
|
||||||
RangeHighlighter[] highlighters = myEditor.getMarkupModel().getAllHighlighters();
|
|
||||||
for (RangeHighlighter highlighter : highlighters) {
|
|
||||||
if (highlighter.getStartOffset() == range.getStartOffset()) {
|
|
||||||
if (highlighter.getEndOffset() == range.getEndOffset()) {
|
|
||||||
greedyToRight.set(highlighter.isGreedyToRight());
|
|
||||||
highlighter.setGreedyToRight(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String renderedType = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(myExprType);
|
|
||||||
myProperty.setTypeReference(new JetPsiFactory(myProject).createType(renderedType));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
myProperty.setTypeReference(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateState templateState =
|
protected final void addPanelControl(@NotNull ControlWrapper panelControl) {
|
||||||
TemplateManagerImpl.getTemplateState(InjectedLanguageUtil.getTopLevelEditor(myEditor));
|
panelControls.add(panelControl);
|
||||||
if (templateState != null) {
|
}
|
||||||
myEditor.putUserData(INTRODUCE_RESTART, true);
|
|
||||||
templateState.cancelTemplate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (myExprTypeCheckbox.isSelected()) {
|
|
||||||
ASTNode identifier = myProperty.getNode().findChildByType(JetTokens.IDENTIFIER);
|
|
||||||
if (identifier != null) {
|
|
||||||
TextRange range = identifier.getTextRange();
|
|
||||||
RangeHighlighter[] highlighters = myEditor.getMarkupModel().getAllHighlighters();
|
|
||||||
for (RangeHighlighter highlighter : highlighters) {
|
|
||||||
if (highlighter.getStartOffset() == range.getStartOffset()) {
|
|
||||||
if (highlighter.getEndOffset() == range.getEndOffset()) {
|
|
||||||
highlighter.setGreedyToRight(greedyToRight.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (myEditor.getUserData(INTRODUCE_RESTART) == Boolean.TRUE) {
|
protected final void addPanelControl(@Nullable Function0<JComponent> initializer) {
|
||||||
myInitialName = myProperty.getName();
|
if (initializer != null) {
|
||||||
performInplaceRefactoring(getSuggestionsForNextRun());
|
addPanelControl(new ControlWrapper(initializer));
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initPanelControls() {
|
||||||
|
addPanelControl(getCreateVarCheckBox());
|
||||||
|
addPanelControl(getCreateExplicitTypeCheckBox());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void updatePanelControls() {
|
||||||
|
JPanel panel = getContentPanel();
|
||||||
|
|
||||||
|
panel.removeAll();
|
||||||
|
|
||||||
JPanel panel = new JPanel(new GridBagLayout());
|
|
||||||
panel.setBorder(null);
|
|
||||||
int count = 1;
|
int count = 1;
|
||||||
if (myVarCheckbox != null) {
|
for (ControlWrapper panelControl : panelControls) {
|
||||||
panel.add(myVarCheckbox, new GridBagConstraints(0, count, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
|
if (!panelControl.isAvailable()) continue;
|
||||||
GridBagConstraints.HORIZONTAL,
|
panelControl.initialize();
|
||||||
new Insets(5, 5, 5, 5), 0, 0));
|
panel.add(panelControl.getComponent(), new GridBagConstraints(0, count, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
|
||||||
++count;
|
GridBagConstraints.HORIZONTAL,
|
||||||
}
|
new Insets(0, 5, 0, 5), 0, 0));
|
||||||
|
|
||||||
if (myExprTypeCheckbox != null) {
|
|
||||||
panel.add(myExprTypeCheckbox, new GridBagConstraints(0, count, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
|
|
||||||
GridBagConstraints.HORIZONTAL,
|
|
||||||
new Insets(5, 5, 5, 5), 0, 0));
|
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
panel.add(Box.createVerticalBox(), new GridBagConstraints(0, count, 1, 1, 1, 1, GridBagConstraints.NORTHWEST,
|
panel.add(Box.createVerticalBox(), new GridBagConstraints(0, count, 1, 1, 1, 1, GridBagConstraints.NORTHWEST,
|
||||||
GridBagConstraints.BOTH,
|
GridBagConstraints.BOTH,
|
||||||
new Insets(0, 0, 0, 0), 0, 0));
|
new Insets(0, 0, 0, 0), 0, 0));
|
||||||
return panel;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected final JComponent getComponent() {
|
||||||
|
panelControls.clear();
|
||||||
|
initPanelControls();
|
||||||
|
|
||||||
|
updatePanelControls();
|
||||||
|
|
||||||
|
return getContentPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected final Function0<JComponent> getCreateExplicitTypeCheckBox() {
|
||||||
|
if (myExprType == null || noTypeInference) return null;
|
||||||
|
|
||||||
|
return new Function0<JComponent>() {
|
||||||
|
@Override
|
||||||
|
public JComponent invoke() {
|
||||||
|
final JCheckBox exprTypeCheckbox = new NonFocusableCheckBox("Specify type explicitly");
|
||||||
|
exprTypeCheckbox.setSelected(false);
|
||||||
|
exprTypeCheckbox.setMnemonic('t');
|
||||||
|
exprTypeCheckbox.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(@NotNull ActionEvent e) {
|
||||||
|
runWriteActionAndRestartRefactoring(
|
||||||
|
new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (exprTypeCheckbox.isSelected()) {
|
||||||
|
String renderedType =
|
||||||
|
IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(myExprType);
|
||||||
|
myProperty.setTypeReference(new JetPsiFactory(myProject).createType(renderedType));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
myProperty.setTypeReference(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return exprTypeCheckbox;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected final Function0<JComponent> getCreateVarCheckBox() {
|
||||||
|
if (myDoNotChangeVar) return null;
|
||||||
|
|
||||||
|
return new Function0<JComponent>() {
|
||||||
|
@Override
|
||||||
|
public JComponent invoke() {
|
||||||
|
final JCheckBox varCheckbox = new NonFocusableCheckBox("Declare with var");
|
||||||
|
varCheckbox.setSelected(isVar);
|
||||||
|
varCheckbox.setMnemonic('v');
|
||||||
|
varCheckbox.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(@NotNull ActionEvent e) {
|
||||||
|
new WriteCommandAction(myProject, getCommandName(), getCommandName()) {
|
||||||
|
@Override
|
||||||
|
protected void run(@NotNull Result result) throws Throwable {
|
||||||
|
PsiDocumentManager.getInstance(myProject).commitDocument(myEditor.getDocument());
|
||||||
|
|
||||||
|
JetPsiFactory psiFactory = new JetPsiFactory(myProject);
|
||||||
|
ASTNode node = varCheckbox.isSelected() ? psiFactory.createVarNode() : psiFactory.createValNode();
|
||||||
|
myProperty.getValOrVarNode().getPsi().replace(node.getPsi());
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return varCheckbox;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void runWriteActionAndRestartRefactoring(final Runnable runnable) {
|
||||||
|
final Ref<Boolean> greedyToRight = new Ref<Boolean>();
|
||||||
|
new WriteCommandAction(myProject, getCommandName(), getCommandName()) {
|
||||||
|
@Override
|
||||||
|
protected void run(@NotNull Result result) throws Throwable {
|
||||||
|
PsiDocumentManager.getInstance(myProject).commitDocument(myEditor.getDocument());
|
||||||
|
|
||||||
|
ASTNode identifier = myProperty.getNode().findChildByType(JetTokens.IDENTIFIER);
|
||||||
|
if (identifier != null) {
|
||||||
|
TextRange range = identifier.getTextRange();
|
||||||
|
RangeHighlighter[] highlighters = myEditor.getMarkupModel().getAllHighlighters();
|
||||||
|
for (RangeHighlighter highlighter : highlighters) {
|
||||||
|
if (highlighter.getStartOffset() == range.getStartOffset()) {
|
||||||
|
if (highlighter.getEndOffset() == range.getEndOffset()) {
|
||||||
|
greedyToRight.set(highlighter.isGreedyToRight());
|
||||||
|
highlighter.setGreedyToRight(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runnable.run();
|
||||||
|
|
||||||
|
TemplateState templateState =
|
||||||
|
TemplateManagerImpl.getTemplateState(InjectedLanguageUtil.getTopLevelEditor(myEditor));
|
||||||
|
if (templateState != null) {
|
||||||
|
myEditor.putUserData(INTRODUCE_RESTART, true);
|
||||||
|
templateState.cancelTemplate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
ASTNode identifier = myProperty.getNode().findChildByType(JetTokens.IDENTIFIER);
|
||||||
|
if (identifier != null) {
|
||||||
|
TextRange range = identifier.getTextRange();
|
||||||
|
RangeHighlighter[] highlighters = myEditor.getMarkupModel().getAllHighlighters();
|
||||||
|
for (RangeHighlighter highlighter : highlighters) {
|
||||||
|
if (highlighter.getStartOffset() == range.getStartOffset()) {
|
||||||
|
if (highlighter.getEndOffset() == range.getEndOffset()) {
|
||||||
|
highlighter.setGreedyToRight(greedyToRight.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (myEditor.getUserData(INTRODUCE_RESTART) == Boolean.TRUE) {
|
||||||
|
myInitialName = myProperty.getName();
|
||||||
|
performInplaceRefactoring(getSuggestionsForNextRun());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private LinkedHashSet<String> getSuggestionsForNextRun() {
|
private LinkedHashSet<String> getSuggestionsForNextRun() {
|
||||||
@@ -206,14 +325,18 @@ public class KotlinInplaceVariableIntroducer extends InplaceVariableIntroducer<J
|
|||||||
return nameSuggestions;
|
return nameSuggestions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected void addTypeReferenceVariable(TemplateBuilderImpl builder) {
|
||||||
protected void addAdditionalVariables(TemplateBuilderImpl builder) {
|
|
||||||
JetTypeReference typeReference = myProperty.getTypeReference();
|
JetTypeReference typeReference = myProperty.getTypeReference();
|
||||||
if (typeReference != null) {
|
if (typeReference != null) {
|
||||||
builder.replaceElement(typeReference, SpecifyTypeExplicitlyAction.createTypeExpressionForTemplate(myExprType));
|
builder.replaceElement(typeReference, SpecifyTypeExplicitlyAction.createTypeExpressionForTemplate(myExprType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addAdditionalVariables(TemplateBuilderImpl builder) {
|
||||||
|
addTypeReferenceVariable(builder);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean buildTemplateAndStart(
|
protected boolean buildTemplateAndStart(
|
||||||
Collection<PsiReference> refs,
|
Collection<PsiReference> refs,
|
||||||
|
|||||||
Reference in New Issue
Block a user