Merge remote-tracking branch 'origin/master'

This commit is contained in:
Vladimir.Orlov
2017-06-05 14:44:02 +03:00
51 changed files with 1083 additions and 341 deletions
+1 -1
View File
@@ -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);
}
@@ -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) {
@@ -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();
@@ -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
@@ -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;
}
}
@@ -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;
@@ -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;
}
}
}
@@ -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();
}
@@ -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;
@@ -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> { }
@@ -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();
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
@@ -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);
}
}
}
@@ -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();
}
}
@@ -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();
}
}
}
@@ -0,0 +1,5 @@
class Test {
void foo() {
if (true) System.out.println(<selection>"Hello, world"</selection>);
}
}
@@ -0,0 +1,5 @@
class Test {
void foo() {
System.out.println(<selection>"Hello, world"</selection>);
}
}
@@ -0,0 +1,6 @@
class Test {
String myName;
void foo() {
if (true) <selection>System.out.println("Hello, world " + myName);</selection>
}
}
@@ -0,0 +1,6 @@
class Test {
void foo(String name) {
System.out.println("Hello, ");
<selection>System.out.println(name);</selection>
}
}
@@ -0,0 +1,5 @@
class Test {
void foo(String s) {
if (true) <selection>System.out.println("Hello, world " + s);</selection>
}
}
@@ -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();
}
}
}
@@ -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(); }
@@ -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);
}
}
}
@@ -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,
@@ -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
@@ -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 {
@@ -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;
}
}
@@ -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 {
@@ -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;
@@ -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
@@ -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,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);
+4
View File
@@ -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"/>