blob: b703768a909a245bfa6d219e5f638e6a0fc85345 [file] [log] [blame]
/*
* Copyright 2000-2014 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.plugins.groovy.refactoring.introduce.parameter;
import com.intellij.codeInsight.template.TextResult;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.impl.DocumentMarkupModel;
import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.editor.markup.MarkupModel;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiType;
import com.intellij.refactoring.IntroduceParameterRefactoring;
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
import com.intellij.refactoring.rename.inplace.InplaceRefactoring;
import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.ArrayUtil;
import gnu.trove.TIntArrayList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
/**
* Created by Max Medvedev on 9/1/13
*/
public class GrInplaceParameterIntroducer extends GrAbstractInplaceIntroducer<GrIntroduceParameterSettings> {
private final IntroduceParameterInfo myInfo;
private final TIntArrayList myParametersToRemove;
private JBCheckBox myDelegateCB;
private final LinkedHashSet<String> mySuggestedNames;
public GrInplaceParameterIntroducer(IntroduceParameterInfo info, GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) {
super(GrIntroduceParameterHandler.REFACTORING_NAME, choice, context);
myInfo = info;
GrVariable localVar = GrIntroduceHandlerBase.resolveLocalVar(context);
mySuggestedNames = GroovyIntroduceParameterUtil.suggestNames(localVar, context.getExpression(), context.getStringPart(), info.getToReplaceIn(), context.getProject());
myParametersToRemove = new TIntArrayList(GroovyIntroduceParameterUtil.findParametersToRemove(info).getValues());
}
@Override
protected String getActionName() {
return GrIntroduceParameterHandler.REFACTORING_NAME;
}
@Override
protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) {
return ArrayUtil.toStringArray(mySuggestedNames);
}
@Override
protected JComponent getComponent() {
JPanel previewPanel = new JPanel(new BorderLayout());
previewPanel.add(getPreviewEditor().getComponent(), BorderLayout.CENTER);
previewPanel.setBorder(new EmptyBorder(2, 2, 6, 2));
DocumentAdapter documentAdapter = new DocumentAdapter() {
@Override
public void documentChanged(DocumentEvent e) {
final TemplateState templateState = TemplateManagerImpl.getTemplateState(myEditor);
if (templateState != null) {
final TextResult value = templateState.getVariableValue(InplaceRefactoring.PRIMARY_VARIABLE_NAME);
if (value != null) {
updateTitle(getVariable(), value.getText());
}
}
}
};
myEditor.getDocument().addDocumentListener(documentAdapter);
myDelegateCB = new JBCheckBox("Delegate via overloading method");
myDelegateCB.setMnemonic('l');
myDelegateCB.setFocusable(false);
JPanel panel = new JPanel(new BorderLayout());
panel.add(previewPanel, BorderLayout.CENTER);
panel.add(myDelegateCB, BorderLayout.SOUTH);
return panel;
}
@Override
protected void saveSettings(@NotNull GrVariable variable) {
}
@Override
protected void updateTitle(@Nullable GrVariable variable) {
if (variable == null) return;
updateTitle(variable, variable.getName());
}
@Override
protected void updateTitle(@Nullable GrVariable variable, String value) {
if (getPreviewEditor() == null || variable == null) return;
final PsiElement declarationScope = ((PsiParameter)variable).getDeclarationScope();
if (declarationScope instanceof PsiMethod) {
final PsiMethod psiMethod = (PsiMethod)declarationScope;
final StringBuilder buf = new StringBuilder();
buf.append(psiMethod.getName()).append(" (");
boolean frst = true;
final List<TextRange> ranges2Remove = new ArrayList<TextRange>();
TextRange addedRange = null;
int i = 0;
for (PsiParameter parameter : psiMethod.getParameterList().getParameters()) {
if (frst) {
frst = false;
}
else {
buf.append(", ");
}
int startOffset = buf.length();
/*if (myMustBeFinal || myPanel.isGenerateFinal()) {
buf.append("final ");
}*/
buf.append(parameter.getType().getPresentableText()).append(" ").append(variable == parameter ? value : parameter.getName());
int endOffset = buf.length();
if (variable == parameter) {
addedRange = new TextRange(startOffset, endOffset);
}
else if (myParametersToRemove.contains(i)) {
ranges2Remove.add(new TextRange(startOffset, endOffset));
}
i++;
}
assert addedRange != null;
buf.append(")");
setPreviewText(buf.toString());
final MarkupModel markupModel = DocumentMarkupModel.forDocument(getPreviewEditor().getDocument(), myProject, true);
markupModel.removeAllHighlighters();
for (TextRange textRange : ranges2Remove) {
markupModel.addRangeHighlighter(textRange.getStartOffset(), textRange.getEndOffset(), 0, getTestAttributesForRemoval(), HighlighterTargetArea.EXACT_RANGE);
}
markupModel.addRangeHighlighter(addedRange.getStartOffset(), addedRange.getEndOffset(), 0, getTextAttributesForAdd(), HighlighterTargetArea.EXACT_RANGE);
//revalidate();
}
}
private static TextAttributes getTextAttributesForAdd() {
final TextAttributes textAttributes = new TextAttributes();
textAttributes.setEffectType(EffectType.ROUNDED_BOX);
textAttributes.setEffectColor(JBColor.RED);
return textAttributes;
}
private static TextAttributes getTestAttributesForRemoval() {
final TextAttributes textAttributes = new TextAttributes();
textAttributes.setEffectType(EffectType.STRIKEOUT);
textAttributes.setEffectColor(JBColor.BLACK);
return textAttributes;
}
@Override
protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceParameterSettings settings, boolean processUsages) {
GrExpressionWrapper wrapper = createExpressionWrapper(context);
if (processUsages) {
GrIntroduceExpressionSettingsImpl patchedSettings =
new GrIntroduceExpressionSettingsImpl(settings, settings.getName(), settings.declareFinal(), settings.parametersToRemove(),
settings.generateDelegate(), settings.replaceFieldsWithGetters(), context.getExpression(),
context.getVar(), settings.getSelectedType(), context.getVar() != null || settings.replaceAllOccurrences(),
context.getVar() != null, settings.isForceReturn());
GrIntroduceParameterProcessor processor = new GrIntroduceParameterProcessor(patchedSettings, wrapper);
processor.run();
}
else {
GrIntroduceParameterProcessor processor = new GrIntroduceParameterProcessor(settings, wrapper);
processor.performRefactoring(UsageInfo.EMPTY_ARRAY);
}
GrParametersOwner owner = settings.getToReplaceIn();
return ArrayUtil.getLastElement(owner.getParameters());
}
@NotNull
private static GrExpressionWrapper createExpressionWrapper(@NotNull GrIntroduceContext context) {
GrExpression expression = context.getExpression();
GrVariable var = context.getVar();
assert expression != null || var != null ;
GrExpression initializer = expression != null ? expression : var.getInitializerGroovy();
return new GrExpressionWrapper(initializer);
}
@Nullable
@Override
protected GrIntroduceParameterSettings getInitialSettingsForInplace(@NotNull GrIntroduceContext context,
@NotNull OccurrencesChooser.ReplaceChoice choice,
String[] names) {
GrExpression expression = context.getExpression();
GrVariable var = context.getVar();
PsiType type = var != null ? var.getDeclaredType() :
expression != null ? expression.getType() :
null;
return new GrIntroduceExpressionSettingsImpl(myInfo, names[0], false, new TIntArrayList(), false,
IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, expression,
var, type, false, false, false);
}
@Override
protected GrIntroduceParameterSettings getSettings() {
return new GrIntroduceExpressionSettingsImpl(myInfo, getInputName(), false, myParametersToRemove, myDelegateCB.isSelected(),
IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, null,
null, getSelectedType(), isReplaceAllOccurrences(), false, false);
}
}