mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# The file might be automatically updated. Comments and empty lines will be removed.
|
||||
kotlinPluginBuild=1.1.2-release-IJ2017.2-1
|
||||
jetSignBuild=42.30
|
||||
jdkBuild=u152b884.5
|
||||
jdkBuild=u152b915.1
|
||||
|
||||
@@ -92,7 +92,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
myContextSet = contextSet;
|
||||
}
|
||||
|
||||
static JavaValue create(JavaValue parent,
|
||||
public static JavaValue create(JavaValue parent,
|
||||
@NotNull ValueDescriptorImpl valueDescriptor,
|
||||
@NotNull EvaluationContextImpl evaluationContext,
|
||||
NodeManagerImpl nodeManager,
|
||||
@@ -364,11 +364,6 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
return myValueDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemaining(int remaining) {
|
||||
node.tooManyChildren(remaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initChildrenArrayRenderer(ArrayRenderer renderer) {
|
||||
renderer.START_INDEX = myCurrentChildrenStart;
|
||||
@@ -408,6 +403,36 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
@Nullable XDebuggerTreeNodeHyperlink link) {
|
||||
node.setMessage(message, icon, attributes, link);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChildren(@NotNull XValueChildrenList children, boolean last) {
|
||||
node.addChildren(children, last);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tooManyChildren(int remaining) {
|
||||
node.tooManyChildren(remaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlreadySorted(boolean alreadySorted) {
|
||||
node.setAlreadySorted(alreadySorted);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setErrorMessage(@NotNull String errorMessage) {
|
||||
node.setErrorMessage(errorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setErrorMessage(@NotNull String errorMessage, @Nullable XDebuggerTreeNodeHyperlink link) {
|
||||
node.setErrorMessage(errorMessage, link);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isObsolete() {
|
||||
return node.isObsolete();
|
||||
}
|
||||
}, myEvaluationContext);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -56,13 +56,17 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.ui.SpeedSearchComparator;
|
||||
import com.intellij.ui.TreeSpeedSearch;
|
||||
import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink;
|
||||
import com.intellij.xdebugger.frame.XValueChildrenList;
|
||||
import com.intellij.xdebugger.settings.XDebuggerSettingsManager;
|
||||
import com.sun.jdi.*;
|
||||
import com.sun.jdi.event.Event;
|
||||
import com.sun.jdi.event.ExceptionEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.TreeModelEvent;
|
||||
@@ -576,9 +580,6 @@ public abstract class DebuggerTree extends DebuggerTreeBase implements DataProvi
|
||||
return (ValueDescriptorImpl)getNode().getDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemaining(int remaining) {}
|
||||
|
||||
@Override
|
||||
public void initChildrenArrayRenderer(ArrayRenderer renderer) {}
|
||||
|
||||
@@ -591,6 +592,38 @@ public abstract class DebuggerTree extends DebuggerTreeBase implements DataProvi
|
||||
}
|
||||
updateUI(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChildren(@NotNull XValueChildrenList children, boolean last) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tooManyChildren(int remaining) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlreadySorted(boolean alreadySorted) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setErrorMessage(@NotNull String errorMessage) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setErrorMessage(@NotNull String errorMessage, @Nullable XDebuggerTreeNodeHyperlink link) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessage(@NotNull String message,
|
||||
@Nullable Icon icon,
|
||||
@NotNull SimpleTextAttributes attributes,
|
||||
@Nullable XDebuggerTreeNodeHyperlink link) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isObsolete() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class BuildStaticNodeCommand extends BuildNodeCommand {
|
||||
|
||||
@@ -21,21 +21,25 @@ import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.debugger.actions.ArrayAction;
|
||||
import com.intellij.debugger.engine.ContextUtil;
|
||||
import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
|
||||
import com.intellij.debugger.engine.JavaValue;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContext;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
|
||||
import com.intellij.debugger.impl.DebuggerUtilsEx;
|
||||
import com.intellij.debugger.memory.utils.ErrorsValueGroup;
|
||||
import com.intellij.debugger.settings.NodeRendererSettings;
|
||||
import com.intellij.debugger.settings.ViewsGeneralSettings;
|
||||
import com.intellij.debugger.ui.impl.watch.ArrayElementDescriptorImpl;
|
||||
import com.intellij.debugger.ui.impl.watch.NodeManagerImpl;
|
||||
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
|
||||
import com.intellij.debugger.ui.tree.DebuggerTreeNode;
|
||||
import com.intellij.debugger.ui.tree.NodeDescriptor;
|
||||
import com.intellij.debugger.ui.tree.NodeDescriptorFactory;
|
||||
import com.intellij.debugger.ui.tree.ValueDescriptor;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.openapi.util.DefaultJDOMExternalizer;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
@@ -49,6 +53,7 @@ import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.xdebugger.XExpression;
|
||||
import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink;
|
||||
import com.intellij.xdebugger.frame.XValueChildrenList;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
|
||||
import com.sun.jdi.ArrayReference;
|
||||
@@ -159,7 +164,7 @@ public class ArrayRenderer extends NodeRendererImpl{
|
||||
builder.setMessage(DebuggerBundle.message("message.node.elements.null.hidden"), null, SimpleTextAttributes.REGULAR_ATTRIBUTES, null);
|
||||
}
|
||||
if (!myForced && END_INDEX < arrayLength - 1) {
|
||||
builder.setRemaining(arrayLength - 1 - END_INDEX);
|
||||
builder.tooManyChildren(arrayLength - 1 - END_INDEX);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,6 +257,7 @@ public class ArrayRenderer extends NodeRendererImpl{
|
||||
|
||||
int added = 0;
|
||||
if (arrayLength - 1 >= START_INDEX) {
|
||||
ErrorsValueGroup errorsGroup = null;
|
||||
for (int idx = START_INDEX; idx < arrayLength; idx++) {
|
||||
try {
|
||||
if (DebuggerUtilsEx.evaluateBoolean(cachedEvaluator.getEvaluator(evaluationContext.getProject()),
|
||||
@@ -269,7 +275,17 @@ public class ArrayRenderer extends NodeRendererImpl{
|
||||
}
|
||||
}
|
||||
catch (EvaluateException e) {
|
||||
builder.addChildren(Collections.singletonList(nodeManager.createMessageNode(e.getMessage())), false);
|
||||
if (errorsGroup == null) {
|
||||
errorsGroup = new ErrorsValueGroup();
|
||||
builder.addChildren(XValueChildrenList.bottomGroup(errorsGroup), false);
|
||||
}
|
||||
JavaValue childValue = JavaValue
|
||||
.create(null,
|
||||
(ValueDescriptorImpl)descriptorFactory.getArrayItemDescriptor(builder.getParentDescriptor(), array, idx),
|
||||
((EvaluationContextImpl)evaluationContext),
|
||||
nodeManager,
|
||||
false);
|
||||
errorsGroup.addErrorValue(e.getMessage(), childValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,16 +15,15 @@
|
||||
*/
|
||||
package com.intellij.debugger.ui.tree.render;
|
||||
|
||||
import com.intellij.debugger.ui.tree.*;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import com.intellij.debugger.ui.tree.DebuggerTreeNode;
|
||||
import com.intellij.debugger.ui.tree.NodeDescriptorFactory;
|
||||
import com.intellij.debugger.ui.tree.NodeManager;
|
||||
import com.intellij.debugger.ui.tree.ValueDescriptor;
|
||||
import com.intellij.xdebugger.frame.XCompositeNode;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
|
||||
public interface ChildrenBuilder {
|
||||
public interface ChildrenBuilder extends XCompositeNode {
|
||||
NodeDescriptorFactory getDescriptorManager();
|
||||
|
||||
NodeManager getNodeManager();
|
||||
@@ -37,13 +36,10 @@ public interface ChildrenBuilder {
|
||||
setChildren(children);
|
||||
}
|
||||
|
||||
default void setMessage(@NotNull String message,
|
||||
@Nullable Icon icon,
|
||||
@NotNull SimpleTextAttributes attributes,
|
||||
@Nullable XDebuggerTreeNodeHyperlink link) {
|
||||
@Deprecated
|
||||
default void setRemaining(int remaining) {
|
||||
tooManyChildren(remaining);
|
||||
}
|
||||
|
||||
void setRemaining(int remaining);
|
||||
|
||||
void initChildrenArrayRenderer(ArrayRenderer renderer);
|
||||
}
|
||||
|
||||
+5
-3
@@ -1579,11 +1579,13 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
final PsiElement parent = expr.getParent();
|
||||
final PsiElement resolved = parent instanceof PsiReferenceExpression ? ((PsiReferenceExpression)parent).resolve() : null;
|
||||
|
||||
PsiClass containingClass =
|
||||
ObjectUtils.notNull(resolved instanceof PsiMethod ? ((PsiMethod)resolved).getContainingClass() : null, aClass);
|
||||
for (PsiClass superClass : classT.getSupers()) {
|
||||
if (superClass.isInheritor(aClass, true)) {
|
||||
if (superClass.isInheritor(containingClass, true)) {
|
||||
String cause = null;
|
||||
if (superClass.isInterface()) {
|
||||
cause = "redundant interface " + format(aClass) + " is extended by ";
|
||||
if (superClass.isInheritor(aClass, true) && superClass.isInterface()) {
|
||||
cause = "redundant interface " + format(containingClass) + " is extended by ";
|
||||
}
|
||||
else if (resolved instanceof PsiMethod &&
|
||||
MethodSignatureUtil.findMethodBySuperMethod(superClass, (PsiMethod)resolved, true) != resolved) {
|
||||
|
||||
+9
-1
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.util.RefactoringChangeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class QualifySuperArgumentFix extends QualifyThisOrSuperArgumentFix {
|
||||
@@ -50,7 +51,14 @@ public class QualifySuperArgumentFix extends QualifyThisOrSuperArgumentFix {
|
||||
final PsiExpression superQualifierCopy = copy.getMethodExpression().getQualifierExpression();
|
||||
LOG.assertTrue(superQualifierCopy != null);
|
||||
superQualifierCopy.delete();
|
||||
PsiMethod method = ((PsiMethodCallExpression)elementFactory.createExpressionFromText(copy.getText(), superClass)).resolveMethod();
|
||||
PsiMethod method;
|
||||
try {
|
||||
method = ((PsiMethodCallExpression)elementFactory.createExpressionFromText(copy.getText(), superClass)).resolveMethod();
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.info(e);
|
||||
return;
|
||||
}
|
||||
if (method != null && !method.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new QualifySuperArgumentFix(expr, superClass));
|
||||
}
|
||||
|
||||
@@ -83,18 +83,12 @@ public class MakeVoidQuickFix implements LocalQuickFix {
|
||||
for (final PsiMethod oMethod : OverridingMethodsSearch.search(psiMethod)) {
|
||||
replaceReturnStatements(oMethod);
|
||||
}
|
||||
final PsiParameter[] params = psiMethod.getParameterList().getParameters();
|
||||
final ParameterInfoImpl[] infos = new ParameterInfoImpl[params.length];
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
PsiParameter param = params[i];
|
||||
infos[i] = new ParameterInfoImpl(i, param.getName(), param.getType());
|
||||
}
|
||||
|
||||
|
||||
final ChangeSignatureProcessor csp = new ChangeSignatureProcessor(project,
|
||||
psiMethod,
|
||||
false, null, psiMethod.getName(),
|
||||
PsiType.VOID,
|
||||
infos);
|
||||
ParameterInfoImpl.fromMethod(psiMethod));
|
||||
|
||||
csp.run();
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.intellij.refactoring.extractclass.ExtractClassHandler;
|
||||
import com.intellij.refactoring.introduceField.IntroduceConstantHandler;
|
||||
import com.intellij.refactoring.introduceField.IntroduceFieldHandler;
|
||||
import com.intellij.refactoring.introduceParameter.IntroduceParameterHandler;
|
||||
import com.intellij.refactoring.introduceVariable.IntroduceFunctionalVariableHandler;
|
||||
import com.intellij.refactoring.introduceVariable.IntroduceVariableHandler;
|
||||
import com.intellij.refactoring.memberPullUp.JavaPullUpHandler;
|
||||
import com.intellij.refactoring.memberPushDown.JavaPushDownHandler;
|
||||
@@ -92,6 +93,11 @@ public class JavaRefactoringSupportProvider extends RefactoringSupportProvider {
|
||||
return new IntroduceFunctionalParameterHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefactoringActionHandler getIntroduceFunctionalVariableHandler() {
|
||||
return new IntroduceFunctionalVariableHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefactoringActionHandler getPullUpHandler() {
|
||||
return new JavaPullUpHandler();
|
||||
|
||||
+29
-23
@@ -124,6 +124,7 @@ public class ExtractMethodDialog extends DialogWrapper implements AbstractExtrac
|
||||
if (canBeChainedConstructor) {
|
||||
myCbChainedConstructor = new NonFocusableCheckBox(RefactoringBundle.message("extract.chained.constructor.checkbox"));
|
||||
}
|
||||
myInputVariables = myVariableData.getInputVariables().toArray(new VariableData[myVariableData.getInputVariables().size()]);
|
||||
|
||||
init();
|
||||
}
|
||||
@@ -308,28 +309,7 @@ public class ExtractMethodDialog extends DialogWrapper implements AbstractExtrac
|
||||
|
||||
//optionsPanel.add(new JLabel("Options: "));
|
||||
|
||||
if (myStaticFlag || myCanBeStatic) {
|
||||
myMakeStatic.setEnabled(!myStaticFlag);
|
||||
myMakeStatic.setSelected(myStaticFlag);
|
||||
if (myVariableData.hasInstanceFields()) {
|
||||
myMakeStatic.setText(RefactoringBundle.message("declare.static.pass.fields.checkbox"));
|
||||
}
|
||||
myMakeStatic.addItemListener(e -> {
|
||||
if (myVariableData.hasInstanceFields()) {
|
||||
myVariableData.setPassFields(myMakeStatic.isSelected());
|
||||
myInputVariables = myVariableData.getInputVariables().toArray(new VariableData[myVariableData.getInputVariables().size()]);
|
||||
updateVarargsEnabled();
|
||||
createParametersPanel();
|
||||
}
|
||||
updateSignature();
|
||||
});
|
||||
optionsPanel.add(myMakeStatic);
|
||||
} else {
|
||||
myMakeStatic.setSelected(false);
|
||||
myMakeStatic.setEnabled(false);
|
||||
}
|
||||
final Border emptyBorder = IdeBorderFactory.createEmptyBorder(5, 0, 5, 4);
|
||||
myMakeStatic.setBorder(emptyBorder);
|
||||
createStaticOptions(optionsPanel, RefactoringBundle.message("declare.static.pass.fields.checkbox"));
|
||||
|
||||
myFoldParameters.setSelected(myVariableData.isFoldingSelectedByDefault());
|
||||
myFoldParameters.setVisible(myVariableData.isFoldable());
|
||||
@@ -344,6 +324,7 @@ public class ExtractMethodDialog extends DialogWrapper implements AbstractExtrac
|
||||
updateSignature();
|
||||
});
|
||||
optionsPanel.add(myFoldParameters);
|
||||
final Border emptyBorder = IdeBorderFactory.createEmptyBorder(5, 0, 5, 4);
|
||||
myFoldParameters.setBorder(emptyBorder);
|
||||
|
||||
boolean canBeVarargs = false;
|
||||
@@ -394,6 +375,30 @@ public class ExtractMethodDialog extends DialogWrapper implements AbstractExtrac
|
||||
return optionsPanel;
|
||||
}
|
||||
|
||||
protected void createStaticOptions(JPanel optionsPanel, String passFieldsAsParamsLabel) {
|
||||
if (myStaticFlag || myCanBeStatic) {
|
||||
myMakeStatic.setEnabled(!myStaticFlag);
|
||||
myMakeStatic.setSelected(myStaticFlag);
|
||||
if (myVariableData.hasInstanceFields()) {
|
||||
myMakeStatic.setText(passFieldsAsParamsLabel);
|
||||
}
|
||||
myMakeStatic.addItemListener(e -> {
|
||||
if (myVariableData.hasInstanceFields()) {
|
||||
myVariableData.setPassFields(myMakeStatic.isSelected());
|
||||
myInputVariables = myVariableData.getInputVariables().toArray(new VariableData[myVariableData.getInputVariables().size()]);
|
||||
updateVarargsEnabled();
|
||||
createParametersPanel();
|
||||
}
|
||||
updateSignature();
|
||||
});
|
||||
optionsPanel.add(myMakeStatic);
|
||||
} else {
|
||||
myMakeStatic.setSelected(false);
|
||||
myMakeStatic.setEnabled(false);
|
||||
}
|
||||
myMakeStatic.setBorder(IdeBorderFactory.createEmptyBorder(5, 0, 5, 4));
|
||||
}
|
||||
|
||||
private ComboBoxVisibilityPanel<String> createVisibilityPanel() {
|
||||
final JavaComboBoxVisibilityPanel panel = new JavaComboBoxVisibilityPanel();
|
||||
final PsiMethod containingMethod = getContainingMethod();
|
||||
@@ -432,7 +437,8 @@ public class ExtractMethodDialog extends DialogWrapper implements AbstractExtrac
|
||||
@Override
|
||||
@NotNull
|
||||
public String getVisibility() {
|
||||
return myTargetClass.isInterface() ? PsiModifier.PUBLIC : ObjectUtils.notNull(myVisibilityPanel.getVisibility(), PsiModifier.PUBLIC);
|
||||
return myTargetClass.isInterface() || myVisibilityPanel == null
|
||||
? PsiModifier.PUBLIC : ObjectUtils.notNull(myVisibilityPanel.getVisibility(), PsiModifier.PUBLIC);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+19
-3
@@ -549,8 +549,7 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
}
|
||||
|
||||
protected AbstractExtractDialog createExtractMethodDialog(final boolean direct) {
|
||||
final List<VariableData> variables = myInputVariables.getInputVariables();
|
||||
myVariableDatum = variables.toArray(new VariableData[variables.size()]);
|
||||
setDataFromInputVariables();
|
||||
myNullness = initNullness();
|
||||
myArtificialOutputVariable = PsiType.VOID.equals(myReturnType) ? getArtificialOutputVariable() : null;
|
||||
final PsiType returnType = myArtificialOutputVariable != null ? myArtificialOutputVariable.getType() : myReturnType;
|
||||
@@ -608,6 +607,11 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
};
|
||||
}
|
||||
|
||||
public void setDataFromInputVariables() {
|
||||
final List<VariableData> variables = myInputVariables.getInputVariables();
|
||||
myVariableDatum = variables.toArray(new VariableData[variables.size()]);
|
||||
}
|
||||
|
||||
public PsiExpression[] findOccurrences() {
|
||||
if (myExpression != null) {
|
||||
return new PsiExpression[] {myExpression};
|
||||
@@ -1350,7 +1354,7 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
}
|
||||
list.add(parm);
|
||||
}
|
||||
else {
|
||||
else if (defineVariablesForUnselectedParameters()){
|
||||
@NonNls StringBuilder buffer = new StringBuilder();
|
||||
if (isFinal) {
|
||||
buffer.append("final ");
|
||||
@@ -1382,6 +1386,10 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
return (PsiMethod)myStyleManager.reformat(newMethod);
|
||||
}
|
||||
|
||||
protected boolean defineVariablesForUnselectedParameters() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void copyParamAnnotations(PsiParameter parm) {
|
||||
final PsiVariable variable = PsiResolveHelper.SERVICE.getInstance(myProject).resolveReferencedVariable(parm.getName(), myElements[0]);
|
||||
if (variable instanceof PsiParameter) {
|
||||
@@ -1735,6 +1743,10 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
return myExtractedMethod;
|
||||
}
|
||||
|
||||
public void setMethodName(String methodName) {
|
||||
myMethodName = methodName;
|
||||
}
|
||||
|
||||
public Boolean hasDuplicates() {
|
||||
List<Match> duplicates = getDuplicates();
|
||||
if (duplicates != null && !duplicates.isEmpty()) {
|
||||
@@ -1831,4 +1843,8 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
public PsiVariable[] getOutputVariables() {
|
||||
return myOutputVariables;
|
||||
}
|
||||
|
||||
public void setMethodVisibility(String methodVisibility) {
|
||||
myMethodVisibility = methodVisibility;
|
||||
}
|
||||
}
|
||||
|
||||
+24
-24
@@ -548,20 +548,7 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiElement[] elementsCopy;
|
||||
if (!elements[0].isPhysical()) {
|
||||
elementsCopy = elements;
|
||||
}
|
||||
else {
|
||||
final PsiFile copy = PsiFileFactory.getInstance(project)
|
||||
.createFileFromText(file.getName(), file.getFileType(), file.getText(), file.getModificationStamp(), false);
|
||||
final TextRange range = new TextRange(elements[0].getTextRange().getStartOffset(),
|
||||
elements[elements.length - 1].getTextRange().getEndOffset());
|
||||
final PsiExpression exprInRange = CodeInsightUtil.findExpressionInRange(copy, range.getStartOffset(), range.getEndOffset());
|
||||
elementsCopy = exprInRange != null
|
||||
? new PsiElement[]{exprInRange}
|
||||
: CodeInsightUtil.findStatementsInRange(copy, range.getStartOffset(), range.getEndOffset());
|
||||
}
|
||||
final PsiElement[] elementsCopy = getElementsInCopy(project, file, elements);
|
||||
final PsiMethod containingMethodCopy = Util.getContainingMethod(elementsCopy[0]);
|
||||
LOG.assertTrue(containingMethodCopy != null);
|
||||
final List<PsiMethod> enclosingMethodsInCopy = getEnclosingMethods(containingMethodCopy);
|
||||
@@ -613,6 +600,28 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static PsiElement[] getElementsInCopy(Project project, PsiFile file, PsiElement[] elements) {
|
||||
final PsiElement[] elementsCopy;
|
||||
if (!elements[0].isPhysical()) {
|
||||
elementsCopy = elements;
|
||||
}
|
||||
else {
|
||||
final PsiFile copy = PsiFileFactory.getInstance(project)
|
||||
.createFileFromText(file.getName(), file.getFileType(), file.getText(), file.getModificationStamp(), false);
|
||||
final TextRange range = new TextRange(elements[0].getTextRange().getStartOffset(),
|
||||
elements[elements.length - 1].getTextRange().getEndOffset());
|
||||
final PsiExpression exprInRange = CodeInsightUtil.findExpressionInRange(copy, range.getStartOffset(), range.getEndOffset());
|
||||
elementsCopy = exprInRange != null
|
||||
? new PsiElement[]{exprInRange}
|
||||
: CodeInsightUtil.findStatementsInRange(copy, range.getStartOffset(), range.getEndOffset());
|
||||
}
|
||||
if (elementsCopy.length == 1 && elementsCopy[0].getUserData(ElementToWorkOn.PARENT) == null) {
|
||||
elementsCopy[0].putUserData(ElementToWorkOn.REPLACE_NON_PHYSICAL, true);
|
||||
}
|
||||
|
||||
return elementsCopy;
|
||||
}
|
||||
|
||||
private void functionalInterfaceSelected(final PsiType selectedType,
|
||||
final List<PsiMethod> enclosingMethods,
|
||||
final Project project,
|
||||
@@ -628,7 +637,7 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
|
||||
PsiMethod methodToSearchFor, Editor editor,
|
||||
final Project project,
|
||||
final PsiType selectedType,
|
||||
final MyExtractMethodProcessor processor,
|
||||
final ExtractMethodProcessor processor,
|
||||
final PsiElement[] elements) {
|
||||
final PsiElement commonParent = findCommonParent(elements);
|
||||
if (commonParent == null) {
|
||||
@@ -657,11 +666,6 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
|
||||
LOG.assertTrue(method != null);
|
||||
final String interfaceMethodName = method.getName();
|
||||
processor.setMethodName(interfaceMethodName);
|
||||
|
||||
if (copyElements.length == 1 && copyElements[0].getUserData(ElementToWorkOn.PARENT) == null) {
|
||||
copyElements[0].putUserData(ElementToWorkOn.REPLACE_NON_PHYSICAL, true);
|
||||
}
|
||||
|
||||
processor.doExtract();
|
||||
|
||||
final PsiMethod extractedMethod = processor.getExtractedMethod();
|
||||
@@ -730,10 +734,6 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setMethodName(String methodName) {
|
||||
myMethodName = methodName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean hasDuplicates() {
|
||||
return false;
|
||||
|
||||
+320
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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 com.intellij.refactoring.introduceVariable;
|
||||
|
||||
import com.intellij.codeInsight.FunctionalInterfaceSuggester;
|
||||
import com.intellij.codeInsight.navigation.NavigationUtil;
|
||||
import com.intellij.ide.util.PsiClassListCellRenderer;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.psi.util.PsiFormatUtilBase;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.actions.IntroduceFunctionalVariableAction;
|
||||
import com.intellij.refactoring.extractMethod.*;
|
||||
import com.intellij.refactoring.introduceParameter.IntroduceParameterHandler;
|
||||
import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class IntroduceFunctionalVariableHandler extends IntroduceVariableHandler {
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file, DataContext dataContext) {
|
||||
ExtractMethodHandler.selectAndPass(project, editor, file, new Pass<PsiElement[]>() {
|
||||
@Override
|
||||
public void pass(PsiElement[] elements) {
|
||||
PsiElement anchorStatement = RefactoringUtil.getParentStatement(elements[0], false);
|
||||
PsiElement tempContainer = checkAnchorStatement(project, editor, anchorStatement);
|
||||
if (tempContainer == null) return;
|
||||
|
||||
PsiElement[] elementsInCopy = IntroduceParameterHandler.getElementsInCopy(project, file, elements);
|
||||
MyExtractMethodProcessor processor =
|
||||
new MyExtractMethodProcessor(project, editor, elementsInCopy, null, IntroduceFunctionalVariableAction.REFACTORING_NAME, null,
|
||||
HelpID.INTRODUCE_VARIABLE);
|
||||
try {
|
||||
processor.prepare();
|
||||
}
|
||||
catch (PrepareFailedException e) {
|
||||
showErrorMessage(project, editor);
|
||||
}
|
||||
|
||||
if (!processor.showDialog()) return;
|
||||
|
||||
final PsiMethod emptyMethod = JavaPsiFacade.getElementFactory(project)
|
||||
.createMethodFromText(processor.generateEmptyMethod("name").getText(), elements[0]);
|
||||
final Collection<? extends PsiType> types = FunctionalInterfaceSuggester.suggestFunctionalInterfaces(emptyMethod);
|
||||
if (types.isEmpty()) {
|
||||
showErrorMessage(project, editor, "No applicable functional interfaces found");
|
||||
return;
|
||||
}
|
||||
if (types.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
functionalInterfaceSelected(ContainerUtil.getFirstItem(types), project, editor, processor, elements, anchorStatement);
|
||||
}
|
||||
else {
|
||||
final Map<PsiClass, PsiType> classes = new LinkedHashMap<>();
|
||||
for (PsiType type : types) {
|
||||
classes.put(PsiUtil.resolveClassInType(type), type);
|
||||
}
|
||||
final PsiClass[] psiClasses = classes.keySet().toArray(new PsiClass[classes.size()]);
|
||||
final String methodSignature =
|
||||
PsiFormatUtil.formatMethod(emptyMethod, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_TYPE);
|
||||
final PsiType returnType = emptyMethod.getReturnType();
|
||||
assert returnType != null;
|
||||
final String title = "Choose Applicable Functional Interface: " + methodSignature + " -> " + returnType.getPresentableText();
|
||||
NavigationUtil.getPsiElementPopup(psiClasses, new PsiClassListCellRenderer(), title,
|
||||
new PsiElementProcessor<PsiClass>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiClass psiClass) {
|
||||
functionalInterfaceSelected(classes.get(psiClass), project, editor, processor, elements,
|
||||
anchorStatement);
|
||||
return true;
|
||||
}
|
||||
}).showInBestPositionFor(editor);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void functionalInterfaceSelected(PsiType type,
|
||||
Project project,
|
||||
Editor editor,
|
||||
MyExtractMethodProcessor processor,
|
||||
PsiElement[] elements,
|
||||
PsiElement anchorStatement) {
|
||||
if (!CommonRefactoringUtil.checkReadOnlyStatus(project, elements[0])) return;
|
||||
PsiMethodCallExpression functionalExpression = createReplacement(project, type, processor, elements);
|
||||
|
||||
PsiExpression qualifier = functionalExpression.getMethodExpression().getQualifierExpression();
|
||||
|
||||
assert qualifier != null;
|
||||
|
||||
SuggestedNameInfo uniqueNames = getSuggestedName(type, qualifier, anchorStatement);
|
||||
|
||||
WriteCommandAction.runWriteCommandAction(project, () -> {
|
||||
PsiDeclarationStatement declaration =
|
||||
replaceSelectionWithFunctionalCall(type, elements, anchorStatement, functionalExpression, qualifier, uniqueNames.names[0]);
|
||||
|
||||
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
|
||||
|
||||
PsiLocalVariable localVariable = (PsiLocalVariable)declaration.getDeclaredElements()[0];
|
||||
PsiIdentifier nameIdentifier = localVariable.getNameIdentifier();
|
||||
final int textOffset = ObjectUtils.notNull(nameIdentifier, localVariable).getTextOffset();
|
||||
editor.getCaretModel().moveToOffset(textOffset);
|
||||
new VariableInplaceRenamer(localVariable, editor) {
|
||||
@Override
|
||||
protected boolean shouldSelectAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void moveOffsetAfter(boolean success) {
|
||||
super.moveOffsetAfter(success);
|
||||
if (success) {
|
||||
final PsiNamedElement renamedVariable = getVariable();
|
||||
if (renamedVariable != null) {
|
||||
editor.getCaretModel().moveToOffset(renamedVariable.getTextRange().getEndOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
}.performInplaceRename();
|
||||
});
|
||||
}
|
||||
|
||||
private static PsiDeclarationStatement replaceSelectionWithFunctionalCall(PsiType type,
|
||||
PsiElement[] elements,
|
||||
PsiElement anchorStatement,
|
||||
PsiMethodCallExpression functionalExpression,
|
||||
PsiExpression qualifier,
|
||||
String variableName) {
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(functionalExpression.getProject());
|
||||
PsiElement tempContainer = anchorStatement.getParent();
|
||||
|
||||
boolean singleExpression = elements.length == 1 && elements[0] instanceof PsiExpression;
|
||||
PsiDeclarationStatement declaration = elementFactory
|
||||
.createVariableDeclarationStatement(variableName, type, qualifier, anchorStatement);
|
||||
String callExpressionText = variableName + "." +
|
||||
functionalExpression.getMethodExpression().getReferenceName() +
|
||||
functionalExpression.getArgumentList().getText();
|
||||
if (singleExpression) {
|
||||
elements[0].replace(elementFactory.createExpressionFromText(callExpressionText, declaration));
|
||||
}
|
||||
if (RefactoringUtil.isLoopOrIf(tempContainer)) {
|
||||
declaration = (PsiDeclarationStatement)RefactoringUtil.putStatementInLoopBody(declaration, tempContainer, anchorStatement, !singleExpression);
|
||||
tempContainer = declaration.getParent();
|
||||
}
|
||||
else {
|
||||
declaration = (PsiDeclarationStatement)tempContainer.addBefore(declaration, anchorStatement);
|
||||
if (!singleExpression) {
|
||||
tempContainer.deleteChildRange(elements[0], elements[elements.length - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!singleExpression) {
|
||||
tempContainer.addAfter(elementFactory.createStatementFromText(callExpressionText + ";", declaration), declaration);
|
||||
}
|
||||
return (PsiDeclarationStatement)JavaCodeStyleManager.getInstance(declaration.getProject()).shortenClassReferences(declaration);
|
||||
}
|
||||
|
||||
private static PsiMethodCallExpression createReplacement(Project project,
|
||||
PsiType selectedType,
|
||||
ExtractMethodProcessor processor,
|
||||
PsiElement[] elements) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(selectedType);
|
||||
final PsiClass wrapperClass = resolveResult.getElement();
|
||||
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
final PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(wrapperClass);
|
||||
assert method != null : "not functional class";
|
||||
final String interfaceMethodName = method.getName();
|
||||
processor.setMethodName(interfaceMethodName);
|
||||
processor.doExtract();
|
||||
|
||||
final PsiMethod extractedMethod = processor.getExtractedMethod();
|
||||
final PsiParameter[] parameters = extractedMethod.getParameterList().getParameters();
|
||||
final PsiParameter[] interfaceParameters = method.getParameterList().getParameters();
|
||||
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
|
||||
for (int i = 0; i < interfaceParameters.length; i++) {
|
||||
final PsiTypeElement typeAfterInterface = factory.createTypeElement(substitutor.substitute(interfaceParameters[i].getType()));
|
||||
final PsiTypeElement typeElement = parameters[i].getTypeElement();
|
||||
if (typeElement != null) {
|
||||
typeElement.replace(typeAfterInterface);
|
||||
}
|
||||
}
|
||||
final PsiMethodCallExpression methodCall = processor.getMethodCall();
|
||||
PsiExpression psiExpression = factory
|
||||
.createExpressionFromText("new " + selectedType.getCanonicalText() + "() {" + extractedMethod.getText() + "}." + methodCall.getText(),
|
||||
elements[0]);
|
||||
return (PsiMethodCallExpression)JavaCodeStyleManager.getInstance(project).shortenClassReferences(psiExpression);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void showErrorMessage(Project project, Editor editor, String message) {
|
||||
CommonRefactoringUtil
|
||||
.showErrorHint(project, editor, message, IntroduceFunctionalVariableAction.REFACTORING_NAME, HelpID.INTRODUCE_VARIABLE);
|
||||
}
|
||||
|
||||
private void showErrorMessage(@NotNull Project project, Editor editor) {
|
||||
final String message = RefactoringBundle
|
||||
.getCannotRefactorMessage(
|
||||
RefactoringBundle.message("is.not.supported.in.the.current.context", IntroduceFunctionalVariableAction.REFACTORING_NAME));
|
||||
showErrorMessage(project, editor, message);
|
||||
}
|
||||
|
||||
protected void setupProcessorWithoutDialog(ExtractMethodProcessor processor, InputVariables inputVariables) {
|
||||
processor.setDataFromInputVariables();
|
||||
processor.setMethodVisibility(PsiModifier.PUBLIC);
|
||||
}
|
||||
|
||||
private class MyExtractMethodProcessor extends ExtractMethodProcessor {
|
||||
|
||||
public MyExtractMethodProcessor(Project project,
|
||||
Editor editor,
|
||||
PsiElement[] elements,
|
||||
PsiType forcedReturnType,
|
||||
String refactoringName, String initialMethodName, String helpId) {
|
||||
super(project, editor, elements, forcedReturnType, refactoringName, initialMethodName, helpId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatic() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isFoldingApplicable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractExtractDialog createExtractMethodDialog(boolean direct) {
|
||||
setDataFromInputVariables();
|
||||
return new ExtractMethodDialog(myProject, myTargetClass, myInputVariables, null, getTypeParameterList(),
|
||||
getThrownExceptions(), isStatic(), isCanBeStatic(), false,
|
||||
IntroduceFunctionalVariableAction.REFACTORING_NAME, HelpID.INTRODUCE_VARIABLE, null, myElements) {
|
||||
@Override
|
||||
protected JComponent createNorthPanel() {
|
||||
if (!myInputVariables.hasInstanceFields()) {
|
||||
return null;
|
||||
}
|
||||
JPanel optionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 5));
|
||||
createStaticOptions(optionsPanel, "Pass fields as params");
|
||||
return optionsPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myParamTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSignature() {
|
||||
String parametersList =
|
||||
Arrays.stream(getChosenParameters())
|
||||
.filter(data -> data.passAsParameter)
|
||||
.map(data -> data.type.getPresentableText())
|
||||
.reduce((result, item) -> result + ", " + item)
|
||||
.orElse("");
|
||||
String returnTypeString = myReturnType == null || PsiType.VOID.equals(myReturnType)
|
||||
? "{}" : myReturnType.getPresentableText();
|
||||
return "(" + parametersList + ") -> " + returnTypeString;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getVisibility() {
|
||||
return PsiModifier.PUBLIC;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showDialog() {
|
||||
if (!myInputVariables.hasInstanceFields() && myInputVariables.getInputVariables().isEmpty() ||
|
||||
ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
setupProcessorWithoutDialog(this, myInputVariables);
|
||||
return true;
|
||||
}
|
||||
return super.showDialog();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean defineVariablesForUnselectedParameters() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
-18
@@ -613,18 +613,8 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
|
||||
|
||||
final PsiElement anchorStatement = RefactoringUtil.getParentStatement(physicalElement != null ? physicalElement : expr, false);
|
||||
|
||||
if (anchorStatement == null) {
|
||||
return parentStatementNotFound(project, editor);
|
||||
}
|
||||
if (checkAnchorBeforeThisOrSuper(project, editor, anchorStatement, REFACTORING_NAME, HelpID.INTRODUCE_VARIABLE)) return false;
|
||||
|
||||
final PsiElement tempContainer = anchorStatement.getParent();
|
||||
|
||||
if (!(tempContainer instanceof PsiCodeBlock) && !RefactoringUtil.isLoopOrIf(tempContainer) && !(tempContainer instanceof PsiLambdaExpression) && (tempContainer.getParent() instanceof PsiLambdaExpression)) {
|
||||
String message = RefactoringBundle.message("refactoring.is.not.supported.in.the.current.context", REFACTORING_NAME);
|
||||
showErrorMessage(project, editor, message);
|
||||
return false;
|
||||
}
|
||||
PsiElement tempContainer = checkAnchorStatement(project, editor, anchorStatement);
|
||||
if (tempContainer == null) return false;
|
||||
|
||||
final PsiFile file = anchorStatement.getContainingFile();
|
||||
LOG.assertTrue(file != null, "expr.getContainingFile() == null");
|
||||
@@ -766,6 +756,24 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
|
||||
return wasSucceed[0];
|
||||
}
|
||||
|
||||
protected PsiElement checkAnchorStatement(Project project, Editor editor, PsiElement anchorStatement) {
|
||||
if (anchorStatement == null) {
|
||||
String message = RefactoringBundle.message("refactoring.is.not.supported.in.the.current.context", REFACTORING_NAME);
|
||||
showErrorMessage(project, editor, message);
|
||||
return null;
|
||||
}
|
||||
if (checkAnchorBeforeThisOrSuper(project, editor, anchorStatement, REFACTORING_NAME, HelpID.INTRODUCE_VARIABLE)) return null;
|
||||
|
||||
final PsiElement tempContainer = anchorStatement.getParent();
|
||||
|
||||
if (!(tempContainer instanceof PsiCodeBlock) && !RefactoringUtil.isLoopOrIf(tempContainer) && !(tempContainer instanceof PsiLambdaExpression) && (tempContainer.getParent() instanceof PsiLambdaExpression)) {
|
||||
String message = RefactoringBundle.message("refactoring.is.not.supported.in.the.current.context", REFACTORING_NAME);
|
||||
showErrorMessage(project, editor, message);
|
||||
return null;
|
||||
}
|
||||
return tempContainer;
|
||||
}
|
||||
|
||||
protected JavaReplaceChoice getOccurrencesChoice() {
|
||||
return null;
|
||||
}
|
||||
@@ -1110,12 +1118,6 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
|
||||
: factory.createExpressionFromText(text, parent);
|
||||
}
|
||||
|
||||
private boolean parentStatementNotFound(final Project project, Editor editor) {
|
||||
String message = RefactoringBundle.message("refactoring.is.not.supported.in.the.current.context", REFACTORING_NAME);
|
||||
showErrorMessage(project, editor, message);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean invokeImpl(Project project, PsiLocalVariable localVariable, Editor editor) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
+2
-2
@@ -1984,8 +1984,8 @@ public class InferenceSession {
|
||||
final PsiSubstitutor sSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(gClass, (PsiClassType)sBound);
|
||||
final PsiSubstitutor tSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(gClass, (PsiClassType)tBound);
|
||||
for (PsiTypeParameter typeParameter : gClass.getTypeParameters()) {
|
||||
final PsiType sType = sSubstitutor.substitute(typeParameter);
|
||||
final PsiType tType = tSubstitutor.substitute(typeParameter);
|
||||
final PsiType sType = sSubstitutor.substituteWithBoundsPromotion(typeParameter);
|
||||
final PsiType tType = tSubstitutor.substituteWithBoundsPromotion(typeParameter);
|
||||
final Pair<PsiType, PsiType> typePair = Pair.create(sType, tType);
|
||||
if (!processor.process(typePair)) {
|
||||
return gClass;
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
|
||||
abstract class Bug {
|
||||
{
|
||||
D<?> _m = m();
|
||||
}
|
||||
|
||||
abstract <J extends C<? extends String>> J m();
|
||||
}
|
||||
|
||||
abstract class C<T extends String> { }
|
||||
abstract class D<T extends String> extends C<T> { }
|
||||
+24
@@ -81,3 +81,27 @@ class InsideThisRxpression {
|
||||
public interface Bar extends Foo {}
|
||||
}
|
||||
|
||||
class SameDefaultMethodDifferentInheritors {
|
||||
interface A { default void a() {} }
|
||||
interface B extends A { default void a() {} }
|
||||
interface B1 extends A { }
|
||||
interface C extends A {}
|
||||
|
||||
class Clazz implements B, C {
|
||||
{
|
||||
<error descr="Bad type qualifier in default super call: method a is overridden in SameDefaultMethodDifferentInheritors.B">C</error>.super.a();
|
||||
}
|
||||
}
|
||||
|
||||
class Clazz1 implements B1, C {
|
||||
{
|
||||
C.super.a();
|
||||
}
|
||||
}
|
||||
|
||||
class Clazz2 implements C {
|
||||
{
|
||||
C.super.a();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class Test {
|
||||
void foo() {
|
||||
if (true) {
|
||||
Supplier<String> stringSupplier = new Supplier<String>() {
|
||||
public String get() {
|
||||
return "Hello, world";
|
||||
}
|
||||
};
|
||||
System.out.println(stringSupplier.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class Test {
|
||||
void foo() {
|
||||
Supplier<String> stringSupplier = new Supplier<String>() {
|
||||
public String get() {
|
||||
return "Hello, world";
|
||||
}
|
||||
};
|
||||
System.out.println(stringSupplier.get());
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import java.util.function.Consumer;
|
||||
|
||||
class Test {
|
||||
String myName;
|
||||
void foo() {
|
||||
if (true) {
|
||||
Consumer<String> stringConsumer = new Consumer<String>() {
|
||||
public void accept(String myName) {
|
||||
System.out.println("Hello, world " + myName);
|
||||
}
|
||||
};
|
||||
stringConsumer.accept(myName);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Test {
|
||||
void foo(String name) {
|
||||
System.out.println("Hello, ");
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
System.out.println(name);
|
||||
}
|
||||
};
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import java.util.function.Consumer;
|
||||
|
||||
class Test {
|
||||
void foo(String s) {
|
||||
if (true) {
|
||||
Consumer<String> stringConsumer = new Consumer<String>() {
|
||||
public void accept(String s) {
|
||||
System.out.println("Hello, world " + s);
|
||||
}
|
||||
};
|
||||
stringConsumer.accept(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import java.util.function.Consumer;
|
||||
|
||||
class Test {
|
||||
void foo(String s) {
|
||||
if (true) {
|
||||
Consumer<String> stringConsumer = new Consumer<String>() {
|
||||
public void accept(String s) {
|
||||
System.out.println("Hello, world " + s);
|
||||
System.out.println();
|
||||
}
|
||||
};
|
||||
stringConsumer.accept(s);
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class Test {
|
||||
void foo() {
|
||||
if (true) System.out.println(<selection>"Hello, world"</selection>);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class Test {
|
||||
void foo() {
|
||||
System.out.println(<selection>"Hello, world"</selection>);
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class Test {
|
||||
String myName;
|
||||
void foo() {
|
||||
if (true) <selection>System.out.println("Hello, world " + myName);</selection>
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class Test {
|
||||
void foo(String name) {
|
||||
System.out.println("Hello, ");
|
||||
<selection>System.out.println(name);</selection>
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class Test {
|
||||
void foo(String s) {
|
||||
if (true) <selection>System.out.println("Hello, world " + s);</selection>
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
class Test {
|
||||
void foo(String s) {
|
||||
if (true) {
|
||||
<selection>System.out.println("Hello, world " + s);
|
||||
System.out.println();
|
||||
</selection>
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -115,6 +115,7 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
|
||||
public void testPullUncheckedWarningNotionThroughNestedCalls() { doTest(); }
|
||||
public void testIDEA149774() { doTest(); }
|
||||
public void testDisjunctionTypes() { doTest(); }
|
||||
public void testValidIntersectionTypeWithCapturedBounds() { doTest(); }
|
||||
public void testPushErasedStateToArguments() { doTest(); }
|
||||
public void testStopAtStandaloneConditional() { doTest(); }
|
||||
public void testTransitiveInferenceVariableDependencies() { doTest(); }
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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 com.intellij.java.refactoring;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.refactoring.extractMethod.ExtractMethodProcessor;
|
||||
import com.intellij.refactoring.extractMethod.InputVariables;
|
||||
import com.intellij.refactoring.introduceVariable.IntroduceFunctionalVariableHandler;
|
||||
import com.intellij.testFramework.MapDataContext;
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@TestDataPath("$CONTENT_ROOT/testData")
|
||||
public class IntroduceFunctionalVariableTest extends LightRefactoringTestCase {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LanguageLevel getLanguageLevel() {
|
||||
return LanguageLevel.JDK_1_8;
|
||||
}
|
||||
|
||||
public void testExpressionNoVarsSelected() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testExpressionInLoopNoVars() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testStatementInLoop() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testStatements() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testPassFieldsAsParameters() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testSkipUsedLocals() throws Exception {
|
||||
doTest(0);
|
||||
}
|
||||
|
||||
private void doTest(int... disableParams) {
|
||||
boolean enabled = true;
|
||||
try {
|
||||
configureByFile("/refactoring/introduceFunctionalVariable/before" + getTestName(false) + ".java");
|
||||
enabled = getEditor().getSettings().isVariableInplaceRenameEnabled();
|
||||
getEditor().getSettings().setVariableInplaceRenameEnabled(false);
|
||||
new IntroduceFunctionalVariableHandler() {
|
||||
@Override
|
||||
protected void setupProcessorWithoutDialog(ExtractMethodProcessor processor, InputVariables inputVariables) {
|
||||
inputVariables.setPassFields(true);
|
||||
super.setupProcessorWithoutDialog(processor, inputVariables);
|
||||
for (int i : disableParams) {
|
||||
processor.doNotPassParameter(i);
|
||||
}
|
||||
}
|
||||
}.invoke(getProject(), getEditor(), getFile(), new MapDataContext());
|
||||
checkResultByFile("/refactoring/introduceFunctionalVariable/after" + getTestName(false) + ".java");
|
||||
} finally {
|
||||
getEditor().getSettings().setVariableInplaceRenameEnabled(enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
+101
-95
@@ -4,6 +4,7 @@ import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.intention.LowPriorityAction;
|
||||
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -43,6 +44,7 @@ public class ConvertFieldToAtomicIntention extends PsiElementBaseIntentionAction
|
||||
private static final Logger LOG = Logger.getInstance(ConvertFieldToAtomicIntention.class);
|
||||
|
||||
private final Map<PsiType, String> myFromToMap = ContainerUtil.newHashMap();
|
||||
|
||||
{
|
||||
myFromToMap.put(PsiType.INT, AtomicInteger.class.getName());
|
||||
myFromToMap.put(PsiType.LONG, AtomicLong.class.getName());
|
||||
@@ -112,119 +114,123 @@ public class ConvertFieldToAtomicIntention extends PsiElementBaseIntentionAction
|
||||
}
|
||||
if (!FileModificationService.getInstance().preparePsiElementsForWrite(elements)) return;
|
||||
|
||||
psiVariable.normalizeDeclaration();
|
||||
WriteAction.run(() -> {
|
||||
psiVariable.normalizeDeclaration();
|
||||
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
final PsiType fromType = psiVariable.getType();
|
||||
PsiClassType toType;
|
||||
final String atomicQualifiedName = myFromToMap.get(fromType);
|
||||
if (atomicQualifiedName != null) {
|
||||
final PsiClass atomicClass = psiFacade.findClass(atomicQualifiedName, GlobalSearchScope.allScope(project));
|
||||
if (atomicClass == null) {//show warning
|
||||
return;
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
final PsiType fromType = psiVariable.getType();
|
||||
PsiClassType toType;
|
||||
final String atomicQualifiedName = myFromToMap.get(fromType);
|
||||
if (atomicQualifiedName != null) {
|
||||
final PsiClass atomicClass = psiFacade.findClass(atomicQualifiedName, GlobalSearchScope.allScope(project));
|
||||
if (atomicClass == null) {//show warning
|
||||
return;
|
||||
}
|
||||
toType = factory.createType(atomicClass);
|
||||
}
|
||||
toType = factory.createType(atomicClass);
|
||||
}
|
||||
else if (fromType instanceof PsiArrayType) {
|
||||
final PsiClass atomicReferenceArrayClass =
|
||||
psiFacade.findClass(AtomicReferenceArray.class.getName(), GlobalSearchScope.allScope(project));
|
||||
if (atomicReferenceArrayClass == null) {//show warning
|
||||
return;
|
||||
else if (fromType instanceof PsiArrayType) {
|
||||
final PsiClass atomicReferenceArrayClass =
|
||||
psiFacade.findClass(AtomicReferenceArray.class.getName(), GlobalSearchScope.allScope(project));
|
||||
if (atomicReferenceArrayClass == null) {//show warning
|
||||
return;
|
||||
}
|
||||
final Map<PsiTypeParameter, PsiType> substitutor = ContainerUtil.newHashMap();
|
||||
final PsiTypeParameter[] typeParameters = atomicReferenceArrayClass.getTypeParameters();
|
||||
if (typeParameters.length == 1) {
|
||||
PsiType componentType = ((PsiArrayType)fromType).getComponentType();
|
||||
if (componentType instanceof PsiPrimitiveType) componentType = ((PsiPrimitiveType)componentType).getBoxedType(element);
|
||||
substitutor.put(typeParameters[0], componentType);
|
||||
}
|
||||
toType = factory.createType(atomicReferenceArrayClass, factory.createSubstitutor(substitutor));
|
||||
}
|
||||
final Map<PsiTypeParameter, PsiType> substitutor = ContainerUtil.newHashMap();
|
||||
final PsiTypeParameter[] typeParameters = atomicReferenceArrayClass.getTypeParameters();
|
||||
if (typeParameters.length == 1) {
|
||||
PsiType componentType = ((PsiArrayType)fromType).getComponentType();
|
||||
if (componentType instanceof PsiPrimitiveType) componentType = ((PsiPrimitiveType)componentType).getBoxedType(element);
|
||||
substitutor.put(typeParameters[0], componentType);
|
||||
else {
|
||||
final PsiClass atomicReferenceClass = psiFacade.findClass(AtomicReference.class.getName(), GlobalSearchScope.allScope(project));
|
||||
if (atomicReferenceClass == null) {//show warning
|
||||
return;
|
||||
}
|
||||
final Map<PsiTypeParameter, PsiType> substitutor = ContainerUtil.newHashMap();
|
||||
final PsiTypeParameter[] typeParameters = atomicReferenceClass.getTypeParameters();
|
||||
if (typeParameters.length == 1) {
|
||||
PsiType type = fromType;
|
||||
if (type instanceof PsiPrimitiveType) type = ((PsiPrimitiveType)fromType).getBoxedType(element);
|
||||
substitutor.put(typeParameters[0], type);
|
||||
}
|
||||
toType = factory.createType(atomicReferenceClass, factory.createSubstitutor(substitutor));
|
||||
}
|
||||
toType = factory.createType(atomicReferenceArrayClass, factory.createSubstitutor(substitutor));
|
||||
}
|
||||
else {
|
||||
final PsiClass atomicReferenceClass = psiFacade.findClass(AtomicReference.class.getName(), GlobalSearchScope.allScope(project));
|
||||
if (atomicReferenceClass == null) {//show warning
|
||||
return;
|
||||
}
|
||||
final Map<PsiTypeParameter, PsiType> substitutor = ContainerUtil.newHashMap();
|
||||
final PsiTypeParameter[] typeParameters = atomicReferenceClass.getTypeParameters();
|
||||
if (typeParameters.length == 1) {
|
||||
PsiType type = fromType;
|
||||
if (type instanceof PsiPrimitiveType) type = ((PsiPrimitiveType)fromType).getBoxedType(element);
|
||||
substitutor.put(typeParameters[0], type);
|
||||
}
|
||||
toType = factory.createType(atomicReferenceClass, factory.createSubstitutor(substitutor));
|
||||
}
|
||||
|
||||
try {
|
||||
for (PsiReference reference : refs) {
|
||||
PsiElement refElement = reference.getElement();
|
||||
PsiElement psiElement = refElement;
|
||||
if (psiElement instanceof PsiExpression) {
|
||||
final PsiElement parent = psiElement.getParent();
|
||||
if (parent instanceof PsiExpression && !(parent instanceof PsiReferenceExpression || parent instanceof PsiPolyadicExpression)) {
|
||||
psiElement = parent;
|
||||
}
|
||||
if (psiElement instanceof PsiBinaryExpression) {
|
||||
PsiBinaryExpression binary = (PsiBinaryExpression)psiElement;
|
||||
if (isBinaryOpApplicable(binary.getOperationTokenType(), binary.getLOperand(), binary.getROperand(), refElement, toType)) {
|
||||
continue;
|
||||
try {
|
||||
for (PsiReference reference : refs) {
|
||||
PsiElement refElement = reference.getElement();
|
||||
PsiElement psiElement = refElement;
|
||||
if (psiElement instanceof PsiExpression) {
|
||||
final PsiElement parent = psiElement.getParent();
|
||||
if (parent instanceof PsiExpression && !(parent instanceof PsiReferenceExpression || parent instanceof PsiPolyadicExpression)) {
|
||||
psiElement = parent;
|
||||
}
|
||||
if (psiElement instanceof PsiBinaryExpression) {
|
||||
PsiBinaryExpression binary = (PsiBinaryExpression)psiElement;
|
||||
if (isBinaryOpApplicable(binary.getOperationTokenType(), binary.getLOperand(), binary.getROperand(), refElement, toType)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (psiElement instanceof PsiAssignmentExpression) {
|
||||
final PsiAssignmentExpression assignment = (PsiAssignmentExpression)psiElement;
|
||||
final IElementType opSign = TypeConversionUtil.convertEQtoOperation(assignment.getOperationTokenType());
|
||||
if (isBinaryOpApplicable(opSign, assignment.getLExpression(), assignment.getRExpression(), refElement, toType)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
final TypeConversionDescriptor directConversion = AtomicConversionRule.findDirectConversion(psiElement, toType, fromType);
|
||||
if (directConversion != null) {
|
||||
TypeMigrationReplacementUtil
|
||||
.replaceExpression((PsiExpression)psiElement, project, directConversion, new TypeEvaluator(null, null));
|
||||
}
|
||||
}
|
||||
else if (psiElement instanceof PsiAssignmentExpression) {
|
||||
final PsiAssignmentExpression assignment = (PsiAssignmentExpression)psiElement;
|
||||
final IElementType opSign = TypeConversionUtil.convertEQtoOperation(assignment.getOperationTokenType());
|
||||
if (isBinaryOpApplicable(opSign, assignment.getLExpression(), assignment.getRExpression(), refElement, toType)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
PsiExpression initializer = psiVariable.getInitializer();
|
||||
if (initializer != null) {
|
||||
if (initializer instanceof PsiArrayInitializerExpression) {
|
||||
PsiExpression normalizedExpr =
|
||||
RefactoringUtil.createNewExpressionFromArrayInitializer((PsiArrayInitializerExpression)initializer, psiVariable.getType());
|
||||
initializer = (PsiExpression)initializer.replace(normalizedExpr);
|
||||
}
|
||||
final TypeConversionDescriptor directConversion = AtomicConversionRule.findDirectConversion(psiElement, toType, fromType);
|
||||
final TypeConversionDescriptor directConversion =
|
||||
AtomicConversionRule.wrapWithNewExpression(toType, fromType, initializer, element);
|
||||
if (directConversion != null) {
|
||||
TypeMigrationReplacementUtil.replaceExpression((PsiExpression)psiElement, project, directConversion, new TypeEvaluator(null, null));
|
||||
TypeMigrationReplacementUtil.replaceExpression(initializer, project, directConversion, new TypeEvaluator(null, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!assertNotNull(psiVariable.getModifierList()).hasModifierProperty(PsiModifier.FINAL)) {
|
||||
final PsiExpression newInitializer = factory.createExpressionFromText("new " + toType.getCanonicalText() + "()", psiVariable);
|
||||
if (psiVariable instanceof PsiLocalVariable) {
|
||||
((PsiLocalVariable)psiVariable).setInitializer(newInitializer);
|
||||
}
|
||||
else if (psiVariable instanceof PsiField) {
|
||||
((PsiField)psiVariable).setInitializer(newInitializer);
|
||||
}
|
||||
JavaCodeStyleManager.getInstance(project).shortenClassReferences(psiVariable.getInitializer());
|
||||
}
|
||||
|
||||
PsiExpression initializer = psiVariable.getInitializer();
|
||||
if (initializer != null) {
|
||||
if (initializer instanceof PsiArrayInitializerExpression) {
|
||||
PsiExpression normalizedExpr =
|
||||
RefactoringUtil.createNewExpressionFromArrayInitializer((PsiArrayInitializerExpression)initializer, psiVariable.getType());
|
||||
initializer = (PsiExpression)initializer.replace(normalizedExpr);
|
||||
}
|
||||
final TypeConversionDescriptor directConversion = AtomicConversionRule.wrapWithNewExpression(toType, fromType, initializer, element);
|
||||
if (directConversion != null) {
|
||||
TypeMigrationReplacementUtil.replaceExpression(initializer, project, directConversion, new TypeEvaluator(null, null));
|
||||
}
|
||||
}
|
||||
else if (!assertNotNull(psiVariable.getModifierList()).hasModifierProperty(PsiModifier.FINAL)) {
|
||||
final PsiExpression newInitializer = factory.createExpressionFromText("new " + toType.getCanonicalText() + "()", psiVariable);
|
||||
if (psiVariable instanceof PsiLocalVariable) {
|
||||
((PsiLocalVariable)psiVariable).setInitializer(newInitializer);
|
||||
}
|
||||
else if (psiVariable instanceof PsiField) {
|
||||
((PsiField)psiVariable).setInitializer(newInitializer);
|
||||
}
|
||||
JavaCodeStyleManager.getInstance(project).shortenClassReferences(psiVariable.getInitializer());
|
||||
}
|
||||
PsiElement replaced = assertNotNull(psiVariable.getTypeElement()).replace(factory.createTypeElement(toType));
|
||||
JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced);
|
||||
|
||||
PsiElement replaced = assertNotNull(psiVariable.getTypeElement()).replace(factory.createTypeElement(toType));
|
||||
JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced);
|
||||
|
||||
if (psiVariable instanceof PsiField || CodeStyleSettingsManager.getSettings(project).GENERATE_FINAL_LOCALS) {
|
||||
final PsiModifierList modifierList = assertNotNull(psiVariable.getModifierList());
|
||||
modifierList.setModifierProperty(PsiModifier.FINAL, true);
|
||||
modifierList.setModifierProperty(PsiModifier.VOLATILE, false);
|
||||
if (psiVariable instanceof PsiField || CodeStyleSettingsManager.getSettings(project).GENERATE_FINAL_LOCALS) {
|
||||
final PsiModifierList modifierList = assertNotNull(psiVariable.getModifierList());
|
||||
modifierList.setModifierProperty(PsiModifier.FINAL, true);
|
||||
modifierList.setModifierProperty(PsiModifier.VOLATILE, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isBinaryOpApplicable(@Nullable IElementType opSign,
|
||||
|
||||
+72
-68
@@ -4,6 +4,7 @@ import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.intention.LowPriorityAction;
|
||||
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -73,88 +74,91 @@ public class ConvertFieldToThreadLocalIntention extends PsiElementBaseIntentionA
|
||||
elements.add(reference.getElement());
|
||||
}
|
||||
if (!FileModificationService.getInstance().preparePsiElementsForWrite(elements)) return;
|
||||
psiField.normalizeDeclaration();
|
||||
WriteAction.run(() -> {
|
||||
psiField.normalizeDeclaration();
|
||||
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
final PsiType fromType = psiField.getType();
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
final PsiType fromType = psiField.getType();
|
||||
|
||||
final PsiClass threadLocalClass = psiFacade.findClass(ThreadLocal.class.getName(), GlobalSearchScope.allScope(project));
|
||||
if (threadLocalClass == null) {//show warning
|
||||
return;
|
||||
}
|
||||
final Map<PsiTypeParameter, PsiType> substitutor = ContainerUtil.newHashMap();
|
||||
final PsiTypeParameter[] typeParameters = threadLocalClass.getTypeParameters();
|
||||
if (typeParameters.length == 1) {
|
||||
PsiType type = fromType;
|
||||
if (fromType instanceof PsiPrimitiveType) type = ((PsiPrimitiveType)fromType).getBoxedType(element);
|
||||
substitutor.put(typeParameters[0], type);
|
||||
}
|
||||
final PsiClassType toType = factory.createType(threadLocalClass, factory.createSubstitutor(substitutor));
|
||||
final PsiClass threadLocalClass = psiFacade.findClass(ThreadLocal.class.getName(), GlobalSearchScope.allScope(project));
|
||||
if (threadLocalClass == null) {//show warning
|
||||
return;
|
||||
}
|
||||
final Map<PsiTypeParameter, PsiType> substitutor = ContainerUtil.newHashMap();
|
||||
final PsiTypeParameter[] typeParameters = threadLocalClass.getTypeParameters();
|
||||
if (typeParameters.length == 1) {
|
||||
PsiType type = fromType;
|
||||
if (fromType instanceof PsiPrimitiveType) type = ((PsiPrimitiveType)fromType).getBoxedType(element);
|
||||
substitutor.put(typeParameters[0], type);
|
||||
}
|
||||
final PsiClassType toType = factory.createType(threadLocalClass, factory.createSubstitutor(substitutor));
|
||||
|
||||
try {
|
||||
final TypeMigrationRules rules = new TypeMigrationRules();
|
||||
rules.setBoundScope(GlobalSearchScope.fileScope(element.getContainingFile()));
|
||||
final TypeMigrationLabeler labeler = new TypeMigrationLabeler(rules, toType);
|
||||
labeler.getMigratedUsages(false, psiField);
|
||||
for (PsiReference reference : refs) {
|
||||
PsiElement psiElement = reference.getElement();
|
||||
if (psiElement instanceof PsiExpression) {
|
||||
final PsiElement parent = psiElement.getParent();
|
||||
if (parent instanceof PsiExpression && !(parent instanceof PsiReferenceExpression || parent instanceof PsiPolyadicExpression)) {
|
||||
psiElement = parent;
|
||||
}
|
||||
final TypeConversionDescriptor conversion = ThreadLocalConversionRule.findDirectConversion(psiElement, toType, fromType, labeler);
|
||||
if (conversion != null) {
|
||||
TypeMigrationReplacementUtil.replaceExpression((PsiExpression)psiElement, project, conversion, new TypeEvaluator(null, null));
|
||||
try {
|
||||
final TypeMigrationRules rules = new TypeMigrationRules();
|
||||
rules.setBoundScope(GlobalSearchScope.fileScope(element.getContainingFile()));
|
||||
final TypeMigrationLabeler labeler = new TypeMigrationLabeler(rules, toType);
|
||||
labeler.getMigratedUsages(false, psiField);
|
||||
for (PsiReference reference : refs) {
|
||||
PsiElement psiElement = reference.getElement();
|
||||
if (psiElement instanceof PsiExpression) {
|
||||
final PsiElement parent = psiElement.getParent();
|
||||
if (parent instanceof PsiExpression && !(parent instanceof PsiReferenceExpression || parent instanceof PsiPolyadicExpression)) {
|
||||
psiElement = parent;
|
||||
}
|
||||
final TypeConversionDescriptor conversion =
|
||||
ThreadLocalConversionRule.findDirectConversion(psiElement, toType, fromType, labeler);
|
||||
if (conversion != null) {
|
||||
TypeMigrationReplacementUtil.replaceExpression((PsiExpression)psiElement, project, conversion, new TypeEvaluator(null, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PsiExpression initializer = psiField.getInitializer();
|
||||
if (initializer == null) {
|
||||
final PsiType type = psiField.getType();
|
||||
String initializerText = null;
|
||||
if (PsiType.BOOLEAN.equals(type)) {
|
||||
initializerText = "false";
|
||||
PsiExpression initializer = psiField.getInitializer();
|
||||
if (initializer == null) {
|
||||
final PsiType type = psiField.getType();
|
||||
String initializerText = null;
|
||||
if (PsiType.BOOLEAN.equals(type)) {
|
||||
initializerText = "false";
|
||||
}
|
||||
else if (type instanceof PsiPrimitiveType) {
|
||||
initializerText = "0";
|
||||
}
|
||||
if (initializerText != null) {
|
||||
psiField.setInitializer(factory.createExpressionFromText(initializerText, psiField));
|
||||
initializer = psiField.getInitializer();
|
||||
}
|
||||
}
|
||||
else if (type instanceof PsiPrimitiveType) {
|
||||
initializerText = "0";
|
||||
if (initializer != null) {
|
||||
if (initializer instanceof PsiArrayInitializerExpression) {
|
||||
PsiExpression normalizedExpr =
|
||||
RefactoringUtil.createNewExpressionFromArrayInitializer((PsiArrayInitializerExpression)initializer, psiField.getType());
|
||||
initializer = (PsiExpression)initializer.replace(normalizedExpr);
|
||||
}
|
||||
final TypeConversionDescriptor conversion = ThreadLocalConversionRule.wrapWithNewExpression(toType, fromType, initializer);
|
||||
TypeMigrationReplacementUtil.replaceExpression(initializer, project, conversion, new TypeEvaluator(null, null));
|
||||
CodeStyleManager.getInstance(project).reformat(psiField);
|
||||
}
|
||||
if (initializerText != null) {
|
||||
psiField.setInitializer(factory.createExpressionFromText(initializerText, psiField));
|
||||
initializer = psiField.getInitializer();
|
||||
else if (!assertNotNull(psiField.getModifierList()).hasModifierProperty(PsiModifier.FINAL)) {
|
||||
final String text = "new " + PsiDiamondTypeUtil.getCollapsedType(toType, psiField) + "()";
|
||||
final PsiExpression newInitializer = factory.createExpressionFromText(text, psiField);
|
||||
psiField.setInitializer(newInitializer);
|
||||
}
|
||||
}
|
||||
if (initializer != null) {
|
||||
if (initializer instanceof PsiArrayInitializerExpression) {
|
||||
PsiExpression normalizedExpr =
|
||||
RefactoringUtil.createNewExpressionFromArrayInitializer((PsiArrayInitializerExpression)initializer, psiField.getType());
|
||||
initializer = (PsiExpression)initializer.replace(normalizedExpr);
|
||||
}
|
||||
final TypeConversionDescriptor conversion = ThreadLocalConversionRule.wrapWithNewExpression(toType, fromType, initializer);
|
||||
TypeMigrationReplacementUtil.replaceExpression(initializer, project, conversion, new TypeEvaluator(null, null));
|
||||
CodeStyleManager.getInstance(project).reformat(psiField);
|
||||
}
|
||||
else if (!assertNotNull(psiField.getModifierList()).hasModifierProperty(PsiModifier.FINAL)) {
|
||||
final String text = "new " + PsiDiamondTypeUtil.getCollapsedType(toType, psiField) + "()";
|
||||
final PsiExpression newInitializer = factory.createExpressionFromText(text, psiField);
|
||||
psiField.setInitializer(newInitializer);
|
||||
}
|
||||
|
||||
assertNotNull(psiField.getTypeElement()).replace(factory.createTypeElement(toType));
|
||||
assertNotNull(psiField.getTypeElement()).replace(factory.createTypeElement(toType));
|
||||
|
||||
final PsiModifierList modifierList = assertNotNull(psiField.getModifierList());
|
||||
modifierList.setModifierProperty(PsiModifier.FINAL, true);
|
||||
modifierList.setModifierProperty(PsiModifier.VOLATILE, false);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
final PsiModifierList modifierList = assertNotNull(psiField.getModifierList());
|
||||
modifierList.setModifierProperty(PsiModifier.FINAL, true);
|
||||
modifierList.setModifierProperty(PsiModifier.VOLATILE, false);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +101,15 @@ public abstract class RefactoringSupportProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return handler for introducing functional locals in this language
|
||||
* @see ContextAwareActionHandler
|
||||
* @see RefactoringActionHandler
|
||||
*/
|
||||
public RefactoringActionHandler getIntroduceFunctionalVariableHandler() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return handler for pulling up members in this language
|
||||
* @see com.intellij.refactoring.RefactoringActionHandler
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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 com.intellij.refactoring.actions;
|
||||
|
||||
import com.intellij.lang.refactoring.RefactoringSupportProvider;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.refactoring.RefactoringActionHandler;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class IntroduceFunctionalVariableAction extends BasePlatformRefactoringAction {
|
||||
public static final String REFACTORING_NAME = RefactoringBundle.message("introduce.functional.variable.title");
|
||||
|
||||
@Override
|
||||
protected boolean isAvailableInEditorOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabledOnElements(@NotNull PsiElement[] elements) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RefactoringActionHandler getRefactoringHandler(@NotNull RefactoringSupportProvider provider) {
|
||||
return provider.getIntroduceFunctionalVariableHandler();
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,7 @@ public class UnsafeUsagesDialog extends DialogWrapper {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
myMessagePane = new JEditorPane(UIUtil.HTML_MIME, "");
|
||||
myMessagePane.setEditable(false);
|
||||
myMessagePane.setEditorKit(UIUtil.getHTMLEditorKit());
|
||||
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myMessagePane);
|
||||
scrollPane.setPreferredSize(JBUI.size(500, 400));
|
||||
panel.add(new JLabel(RefactoringBundle.message("the.following.problems.were.found")), BorderLayout.NORTH);
|
||||
|
||||
@@ -674,7 +674,9 @@ action.IntroduceConstant.description=Replace selected expression with a constant
|
||||
action.IntroduceParameter.text=_Parameter...
|
||||
action.IntroduceParameter.description=Turn the selected expression into method parameter
|
||||
action.IntroduceFunctionalParameter.text=Functiona_l Parameter...
|
||||
action.IntroduceFunctionalParameter.description=Replace selected statements with a call to new functional method parameter
|
||||
action.IntroduceFunctionalParameter.description=Replace selected statements with a call to a new functional method parameter
|
||||
action.IntroduceFunctionalVariable.text=Functional Variable...
|
||||
action.IntroduceFunctionalVariable.description=Replace selected statements with a call to a new functional variable
|
||||
action.ExtractInterface.text=_Interface...
|
||||
action.ExtractInterface.description=Extract interface from the selected class
|
||||
action.ExtractModule.text=_Module...
|
||||
|
||||
@@ -805,6 +805,7 @@ enter.new.project.name=Enter new project name:
|
||||
rename.project=Rename Project
|
||||
renames.project=Renames project
|
||||
introduce.functional.parameter.title=Extract Functional Parameter
|
||||
introduce.functional.variable.title=Extract Functional Variable
|
||||
introduce.parameter.convert.lambda=&Convert to functional expression
|
||||
|
||||
expand.method.reference.warning=Method is used in method reference. Proceeding would result in conversion to lambda expression
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* Holds <a href="http://semver.org">Semantic Version</a>.
|
||||
*/
|
||||
public final class SemVer implements Comparable<SemVer> {
|
||||
/** @deprecated */
|
||||
public static final SemVer UNKNOWN = new SemVer("?", 0, 0, 0);
|
||||
|
||||
private final String myRawVersion;
|
||||
|
||||
@@ -73,7 +73,6 @@ import java.awt.event.KeyEvent;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.assertNotNull;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
@State(
|
||||
@@ -83,7 +82,7 @@ import static java.util.stream.Collectors.toList;
|
||||
public class ChangesViewManager implements ChangesViewI, ProjectComponent, PersistentStateComponent<ChangesViewManager.State> {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.ChangesViewManager");
|
||||
public static final String CHANGES_VIEW_PREVIEW_SPLITTER_PROPORTION = "ChangesViewManager.DETAILS_SPLITTER_PROPORTION";
|
||||
private static final String CHANGES_VIEW_PREVIEW_SPLITTER_PROPORTION = "ChangesViewManager.DETAILS_SPLITTER_PROPORTION";
|
||||
|
||||
@NotNull private final ChangesListView myView;
|
||||
private JPanel myProgressLabel;
|
||||
@@ -478,10 +477,14 @@ public class ChangesViewManager implements ChangesViewI, ProjectComponent, Persi
|
||||
private class ToggleDetailsAction extends ShowDiffPreviewAction {
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
super.setSelected(e, state);
|
||||
assertNotNull(mySplitterComponent).setDetailsOn(state);
|
||||
mySplitterComponent.setDetailsOn(state);
|
||||
VcsConfiguration.getInstance(myProject).LOCAL_CHANGES_DETAILS_PREVIEW_SHOWN = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return VcsConfiguration.getInstance(myProject).LOCAL_CHANGES_DETAILS_PREVIEW_SHOWN;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyChangeProcessor extends ChangeViewDiffRequestProcessor {
|
||||
|
||||
-13
@@ -16,24 +16,11 @@
|
||||
package com.intellij.openapi.vcs.changes.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.ToggleAction;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
|
||||
public abstract class ShowDiffPreviewAction extends ToggleAction implements DumbAware {
|
||||
private boolean myState;
|
||||
|
||||
public ShowDiffPreviewAction() {
|
||||
super("Preview Diff", null, AllIcons.Actions.DiffPreview);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return myState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
myState = state;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -245,7 +245,7 @@ public class DiffShelvedChangesActionProvider implements AnActionExtensionProvid
|
||||
DiffContentFactory contentFactory = DiffContentFactory.getInstance();
|
||||
DiffContent leftContent = withLocal
|
||||
? contentFactory.create(project, file)
|
||||
: contentFactory.create(project, patch.getSingleHunkPatchText());
|
||||
: contentFactory.create(project, patch.getSingleHunkPatchText(), file);
|
||||
return new SimpleDiffRequest(getName(), leftContent,
|
||||
contentFactory.createEmpty(),
|
||||
withLocal ? CURRENT_VERSION : SHELVED_VERSION, null);
|
||||
@@ -269,8 +269,8 @@ public class DiffShelvedChangesActionProvider implements AnActionExtensionProvid
|
||||
DiffContentFactory contentFactory = DiffContentFactory.getInstance();
|
||||
DiffContent leftContent = withLocal
|
||||
? contentFactory.create(project, file)
|
||||
: contentFactory.create(project, assertNotNull(texts.getBase()));
|
||||
return new SimpleDiffRequest(getName(), leftContent, contentFactory.create(project, texts.getPatched()),
|
||||
: contentFactory.create(project, assertNotNull(texts.getBase()), file);
|
||||
return new SimpleDiffRequest(getName(), leftContent, contentFactory.create(project, texts.getPatched(), file),
|
||||
withLocal ? CURRENT_VERSION : BASE_VERSION, SHELVED_VERSION);
|
||||
}
|
||||
else {
|
||||
|
||||
+17
-13
@@ -108,6 +108,7 @@ public class ShelvedChangesViewManager implements ProjectComponent {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(ShelvedChangesViewManager.class);
|
||||
@NonNls static final String SHELF_CONTEXT_MENU = "Vcs.Shelf.ContextMenu";
|
||||
private static final String SHELVE_PREVIEW_SPLITTER_PROPORTION = "ShelvedChangesViewManager.DETAILS_SPLITTER_PROPORTION";
|
||||
|
||||
private final ChangesViewContentManager myContentManager;
|
||||
private final ShelveChangesManager myShelveChangesManager;
|
||||
@@ -247,21 +248,11 @@ public class ShelvedChangesViewManager implements ProjectComponent {
|
||||
|
||||
DefaultActionGroup actionGroup = new DefaultActionGroup();
|
||||
actionGroup.addAll((ActionGroup)ActionManager.getInstance().getAction("ShelvedChangesToolbar"));
|
||||
ShowDiffPreviewAction diffPreviewAction = new ShowDiffPreviewAction() {
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
super.setSelected(e, state);
|
||||
assertNotNull(mySplitterComponent).setDetailsOn(state);
|
||||
VcsConfiguration.getInstance(myProject).SHELVE_DETAILS_PREVIEW_SHOWN = state;
|
||||
}
|
||||
};
|
||||
actionGroup.add(diffPreviewAction, new Constraints(AFTER, "ShelvedChanges.ShowHideDeleted"));
|
||||
actionGroup.add(new MyToggleDetailsAction(), new Constraints(AFTER, "ShelvedChanges.ShowHideDeleted"));
|
||||
|
||||
MyShelvedPreviewProcessor changeProcessor = new MyShelvedPreviewProcessor(myProject);
|
||||
mySplitterComponent =
|
||||
new PreviewDiffSplitterComponent(pane, changeProcessor, "ShelvedChangesViewManager.DETAILS_SPLITTER_PROPORTION",
|
||||
VcsConfiguration.getInstance(myProject).SHELVE_DETAILS_PREVIEW_SHOWN);
|
||||
diffPreviewAction.setSelected(null, mySplitterComponent.isDetailsOn());
|
||||
mySplitterComponent = new PreviewDiffSplitterComponent(pane, changeProcessor, SHELVE_PREVIEW_SPLITTER_PROPORTION,
|
||||
VcsConfiguration.getInstance(myProject).SHELVE_DETAILS_PREVIEW_SHOWN);
|
||||
ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar("ShelvedChanges", actionGroup, false);
|
||||
|
||||
JPanel rootPanel = new JPanel(new BorderLayout());
|
||||
@@ -742,6 +733,19 @@ public class ShelvedChangesViewManager implements ProjectComponent {
|
||||
return new DnDImage(image, new Point(-image.getWidth(null), -image.getHeight(null)));
|
||||
}
|
||||
|
||||
private class MyToggleDetailsAction extends ShowDiffPreviewAction {
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
mySplitterComponent.setDetailsOn(state);
|
||||
VcsConfiguration.getInstance(myProject).SHELVE_DETAILS_PREVIEW_SHOWN = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return VcsConfiguration.getInstance(myProject).SHELVE_DETAILS_PREVIEW_SHOWN;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyShelvedPreviewProcessor extends CacheDiffRequestProcessor<ShelvedWrapper> implements DiffPreviewUpdateProcessor {
|
||||
|
||||
@NotNull private final DiffShelvedChangesActionProvider.PatchesPreloader myPreloader;
|
||||
|
||||
+1
-1
@@ -1448,7 +1448,7 @@ integer.multiplication.implicit.cast.to.long.option=<html>Ignore compile time co
|
||||
wait.or.await.without.timeout.display.name='wait()' or 'await()' without timeout
|
||||
wait.or.await.without.timeout.problem.descriptor=<code>#ref</code> without timeout #loc
|
||||
method.return.always.constant.display.name=Method returns per-class constant
|
||||
method.return.always.constant.problem.descriptor=Method <code>#ref()</code> returns a per-class constant
|
||||
method.return.always.constant.problem.descriptor=Method <code>#ref()</code> and all it's derivables always return constants
|
||||
class.with.too.many.dependencies.display.name=Class with too many dependencies
|
||||
class.with.too.many.dependencies.problem.descriptor=Class ''{0}'' has too many dependencies ({1} > {2})
|
||||
class.with.too.many.transitive.dependencies.display.name=Class with too many transitive dependencies
|
||||
|
||||
+36
-32
@@ -17,9 +17,7 @@ package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.analysis.AnalysisScope;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.codeInspection.reference.RefEntity;
|
||||
import com.intellij.codeInspection.reference.RefMethod;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.codeInspection.reference.*;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
@@ -34,14 +32,10 @@ import java.util.Set;
|
||||
|
||||
public class MethodReturnAlwaysConstantInspection extends BaseGlobalInspection {
|
||||
|
||||
private static final Key<Boolean> ALWAYS_CONSTANT =
|
||||
Key.create("ALWAYS_CONSTANT");
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"method.return.always.constant.display.name");
|
||||
return InspectionGadgetsBundle.message("method.return.always.constant.display.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,35 +45,24 @@ public class MethodReturnAlwaysConstantInspection extends BaseGlobalInspection {
|
||||
if (!(refEntity instanceof RefMethod)) {
|
||||
return null;
|
||||
}
|
||||
final RefMethod refMethod = (RefMethod)refEntity;
|
||||
final Boolean alreadyProcessed = refMethod.getUserData(ALWAYS_CONSTANT);
|
||||
if (alreadyProcessed != null && alreadyProcessed.booleanValue()) {
|
||||
//don't warn on overriders
|
||||
if (((RefMethod)refEntity).hasSuperMethods()) {
|
||||
return null;
|
||||
}
|
||||
final RefMethod refMethod = (RefMethod)refEntity;
|
||||
if (!(refMethod.getElement() instanceof PsiMethod)) {
|
||||
return null;
|
||||
}
|
||||
final PsiMethod method = (PsiMethod)refMethod.getElement();
|
||||
if (method.getBody() == null) {
|
||||
return null; //we'll catch it on another method
|
||||
}
|
||||
if (!alwaysReturnsConstant(method)) {
|
||||
return null;
|
||||
}
|
||||
final Set<RefMethod> siblingMethods =
|
||||
MethodInheritanceUtils.calculateSiblingMethods(refMethod);
|
||||
for (RefMethod siblingMethod : siblingMethods) {
|
||||
final PsiMethod siblingPsiMethod =
|
||||
(PsiMethod)siblingMethod.getElement();
|
||||
if (method.getBody() != null &&
|
||||
!alwaysReturnsConstant(siblingPsiMethod)) {
|
||||
final Set<RefMethod> allScopeInheritors = MethodInheritanceUtils.calculateSiblingMethods(refMethod);
|
||||
for (RefMethod siblingMethod : allScopeInheritors) {
|
||||
final PsiMethod siblingPsiMethod = (PsiMethod)siblingMethod.getElement();
|
||||
if (siblingPsiMethod.getBody() != null && !alwaysReturnsConstant(siblingPsiMethod)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
final List<ProblemDescriptor> out = new ArrayList<>();
|
||||
for (RefMethod siblingRefMethod : siblingMethods) {
|
||||
final PsiMethod siblingMethod =
|
||||
(PsiMethod)siblingRefMethod.getElement();
|
||||
for (RefMethod siblingRefMethod : allScopeInheritors) {
|
||||
final PsiMethod siblingMethod = (PsiMethod)siblingRefMethod.getElement();
|
||||
final PsiIdentifier identifier = siblingMethod.getNameIdentifier();
|
||||
if (identifier == null) {
|
||||
continue;
|
||||
@@ -88,8 +71,6 @@ public class MethodReturnAlwaysConstantInspection extends BaseGlobalInspection {
|
||||
InspectionGadgetsBundle.message(
|
||||
"method.return.always.constant.problem.descriptor"), false, null,
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING));
|
||||
siblingRefMethod.putUserData(ALWAYS_CONSTANT,
|
||||
Boolean.valueOf(true));
|
||||
}
|
||||
return out.toArray(new ProblemDescriptor[out.size()]);
|
||||
}
|
||||
@@ -100,9 +81,32 @@ public class MethodReturnAlwaysConstantInspection extends BaseGlobalInspection {
|
||||
if (!(statement instanceof PsiReturnStatement)) {
|
||||
return false;
|
||||
}
|
||||
final PsiReturnStatement returnStatement =
|
||||
(PsiReturnStatement)statement;
|
||||
final PsiReturnStatement returnStatement = (PsiReturnStatement)statement;
|
||||
final PsiExpression value = returnStatement.getReturnValue();
|
||||
return value != null && PsiUtil.isConstantExpression(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean queryExternalUsagesRequests(@NotNull final RefManager manager, @NotNull final GlobalJavaInspectionContext globalContext,
|
||||
@NotNull final ProblemDescriptionsProcessor processor) {
|
||||
manager.iterate(new RefJavaVisitor() {
|
||||
@Override public void visitElement(@NotNull RefEntity refEntity) {
|
||||
if (refEntity instanceof RefElement && processor.getDescriptions(refEntity) != null) {
|
||||
refEntity.accept(new RefJavaVisitor() {
|
||||
@Override public void visitMethod(@NotNull final RefMethod refMethod) {
|
||||
globalContext.enqueueDerivedMethodsProcessor(refMethod, new GlobalJavaInspectionContext.DerivedMethodsProcessor() {
|
||||
@Override
|
||||
public boolean process(PsiMethod derivedMethod) {
|
||||
processor.ignoreElement(refMethod);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports methods which only ever return a constant.
|
||||
Reports methods which only ever return a constant, probably different for different inheritors.
|
||||
Because this inspection requires global code analysis it is only available for <em>Analyze|Inspect Code</em> or
|
||||
<em>Analyze|Run Inspection by Name</em> and it will not report in the editor.
|
||||
<!-- tooltip end -->
|
||||
|
||||
@@ -47,7 +47,7 @@ public class MakeMethodDefaultIntention extends BaseElementAtCaretIntentionActio
|
||||
if (psiMethod != null && PsiUtil.isLanguageLevel8OrHigher(psiMethod)) {
|
||||
if (psiMethod.getBody() == null && !psiMethod.hasModifierProperty(PsiModifier.DEFAULT)) {
|
||||
final PsiClass containingClass = psiMethod.getContainingClass();
|
||||
if (containingClass != null && containingClass.isInterface()) {
|
||||
if (containingClass != null && containingClass.isInterface() && !containingClass.isAnnotationType()) {
|
||||
text = "Make '" + psiMethod.getName() + "()' default";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
@interface I {
|
||||
String fo<caret>o() default "foo";
|
||||
}
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.siyeh.ipp.types;
|
||||
|
||||
import com.siyeh.IntentionPowerPackBundle;
|
||||
import com.siyeh.ipp.IPPTestCase;
|
||||
|
||||
public class MakeMethodDefaultTest extends IPPTestCase {
|
||||
@@ -41,4 +40,9 @@ public class MakeMethodDefaultTest extends IPPTestCase {
|
||||
public void testAlreadyHasBody() throws Exception {
|
||||
assertIntentionNotAvailable();
|
||||
}
|
||||
|
||||
public void testAnnotationType() throws Exception {
|
||||
assertIntentionNotAvailable();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.EditorTestUtil;
|
||||
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
|
||||
@@ -187,7 +188,7 @@ public abstract class CCTestCase extends LightPlatformCodeInsightFixtureTestCase
|
||||
|
||||
public Pair<Document, List<AnswerPlaceholder>> getPlaceholders(String name, boolean useLength, boolean removeMarkers) {
|
||||
try {
|
||||
String text = FileUtil.loadFile(new File(getBasePath(), name));
|
||||
String text = StringUtil.convertLineSeparators(FileUtil.loadFile(new File(getBasePath(), name)));
|
||||
Document tempDocument = EditorFactory.getInstance().createDocument(text);
|
||||
if (removeMarkers) {
|
||||
EditorTestUtil.extractCaretAndSelectionMarkers(tempDocument);
|
||||
|
||||
@@ -79,6 +79,10 @@
|
||||
<keyboard-shortcut first-keystroke="control shift alt P" keymap="$default"/>
|
||||
</action>
|
||||
|
||||
<action id="IntroduceFunctionalVariable" class="com.intellij.refactoring.actions.IntroduceFunctionalVariableAction">
|
||||
<add-to-group group-id="IntroduceActionsGroup" anchor="after" relative-to-action="IntroduceFunctionalParameter"/>
|
||||
</action>
|
||||
|
||||
<action id="RenameFile" class="com.intellij.refactoring.actions.RenameFileAction">
|
||||
<add-to-group group-id="RefactoringMenu" anchor="after" relative-to-action="RenameElement"/>
|
||||
<add-to-group group-id="EditorTabPopupMenuEx" anchor="after" relative-to-action="AddAllToFavorites"/>
|
||||
|
||||
Reference in New Issue
Block a user