Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2016-10-20 09:45:42 +02:00
1552 changed files with 183072 additions and 2459 deletions
@@ -12,6 +12,8 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementDecorator;
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.codeInsight.template.*;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
@@ -124,7 +126,7 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
PsiDocumentManager.getInstance(file.getProject()).commitDocument(document);
reformatEnclosingExpressionListAtOffset(file, offset);
if (promptTypeOrConstructorArgs(context, delegate, context.getOffset(insideRef))) return;
if (promptTypeOrConstructorArgs(context, delegate, insideRef, insideBraces)) return;
editor.getCaretModel().moveToOffset(context.getOffset(insideBraces));
context.setLaterRunnable(generateAnonymousBody(editor, file));
@@ -142,17 +144,36 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
if (mySmart) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW);
}
promptTypeOrConstructorArgs(context, delegate, context.getOffset(insideRef));
promptTypeOrConstructorArgs(context, delegate, insideRef, null);
}
}
private static boolean promptTypeOrConstructorArgs(InsertionContext context, LookupElement delegate, int refOffset) {
if (shouldFillTypeArgs(context, delegate) && JavaCompletionUtil.promptTypeArgs(context, refOffset)) {
private static boolean promptTypeOrConstructorArgs(InsertionContext context, LookupElement delegate, OffsetKey refOffset, @Nullable OffsetKey insideBraces) {
if (shouldFillTypeArgs(context, delegate) && JavaCompletionUtil.promptTypeArgs(context, context.getOffset(refOffset))) {
return true;
}
PsiMethod constructor = JavaConstructorCallElement.extractCalledConstructor(delegate);
return constructor != null && JavaMethodCallElement.startArgumentLiveTemplate(context, constructor);
if (constructor != null && JavaMethodCallElement.startArgumentLiveTemplate(context, constructor)) {
implementMethodsWhenTemplateIsFinished(context, insideBraces);
return true;
}
return false;
}
private static void implementMethodsWhenTemplateIsFinished(InsertionContext context, @Nullable final OffsetKey insideBraces) {
TemplateState state = TemplateManagerImpl.getTemplateState(context.getEditor());
if (state != null && insideBraces != null) {
state.addTemplateStateListener(new TemplateEditingAdapter() {
@Override
public void templateFinished(Template template, boolean brokenOff) {
if (!brokenOff) {
context.getEditor().getCaretModel().moveToOffset(context.getOffset(insideBraces));
createOverrideRunnable(context.getEditor(), context.getFile(), context.getProject()).run();
}
}
});
}
}
private static boolean shouldFillTypeArgs(InsertionContext context, LookupElement delegate) {
@@ -214,9 +235,11 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
return false;
}
PsiMethod constructor = JavaConstructorCallElement.extractCalledConstructor(delegate);
final PsiElement place = context.getFile().findElementAt(context.getStartOffset());
assert place != null;
boolean hasParams = hasConstructorParameters(psiClass, place);
boolean hasParams = constructor != null ? constructor.getParameterList().getParametersCount() > 0 : hasConstructorParameters(psiClass, place);
JavaCompletionUtil.insertParentheses(context, delegate, false, hasParams, forAnonymous);
@@ -49,8 +49,6 @@ public class JavaConstructorCallElement extends LookupElementDecorator<LookupEle
myConstructor = constructor;
myType = type;
mySubstitutor = myType.resolveGenerics().getSubstitutor();
markClassItemWrapped(classItem);
}
private void markClassItemWrapped(@NotNull LookupElement classItem) {
@@ -62,6 +60,12 @@ public class JavaConstructorCallElement extends LookupElementDecorator<LookupEle
}
}
@Override
public void handleInsert(InsertionContext context) {
markClassItemWrapped(getDelegate());
super.handleInsert(context);
}
@NotNull
@Override
public PsiMethod getObject() {
@@ -73,7 +73,7 @@ public class InlineStreamMapAction extends PsiElementBaseIntentionAction {
final PsiExpression[] expressions = argumentList.getExpressions();
if (!name.startsWith("map") && expressions.length == 0) return true;
if (expressions.length != 1) return false;
if (!isSupportedForConversion(expressions[0], true)) return false;
if (!StreamRefactoringUtil.isRefactoringCandidate(expressions[0], true)) return false;
final PsiMethod method = methodCallExpression.resolveMethod();
if (method == null) return false;
@@ -81,17 +81,6 @@ public class InlineStreamMapAction extends PsiElementBaseIntentionAction {
return InheritanceUtil.isInheritor(containingClass, CommonClassNames.JAVA_UTIL_STREAM_BASE_STREAM);
}
private static boolean isSupportedForConversion(PsiExpression expression, boolean requireExpressionLambda) {
if(expression instanceof PsiLambdaExpression) {
PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)expression;
return lambdaExpression.getParameterList().getParametersCount() == 1 &&
(!requireExpressionLambda || LambdaUtil.extractSingleExpressionFromBody(lambdaExpression.getBody()) != null);
} else if(expression instanceof PsiMethodReferenceExpression) {
return LambdaRefactoringUtil.canConvertToLambda((PsiMethodReferenceExpression)expression);
}
return false;
}
@Nullable
private static PsiMethodCallExpression getNextExpressionToMerge(PsiMethodCallExpression methodCallExpression) {
PsiElement parent = methodCallExpression.getParent();
@@ -107,7 +96,7 @@ public class InlineStreamMapAction extends PsiElementBaseIntentionAction {
if (!nextName.equals("boxed") && !nextName.equals("asLongStream") && !nextName.equals("asDoubleStream")) return null;
return nextCall;
}
if (expressions.length != 1 || !isSupportedForConversion(expressions[0], false)) return null;
if (expressions.length != 1 || !StreamRefactoringUtil.isRefactoringCandidate(expressions[0], false)) return null;
return nextCall;
}
@@ -27,9 +27,11 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.util.LambdaRefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
@@ -49,6 +51,7 @@ public class MergeFilterChainAction extends PsiElementBaseIntentionAction {
return getFilterToMerge((PsiMethodCallExpression)gParent) != null;
}
@Nullable
private static PsiMethodCallExpression getFilterToMerge(PsiMethodCallExpression methodCallExpression) {
final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression();
if (qualifierExpression instanceof PsiMethodCallExpression && isFilterCall((PsiMethodCallExpression)qualifierExpression)) {
@@ -67,26 +70,20 @@ public class MergeFilterChainAction extends PsiElementBaseIntentionAction {
}
public static boolean isFilterCall(PsiMethodCallExpression methodCallExpression) {
if (!"filter".equals(methodCallExpression.getMethodExpression().getReferenceName())) return false;
String name = methodCallExpression.getMethodExpression().getReferenceName();
if (!"filter".equals(name) && !"anyMatch".equals(name)) return false;
final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
final PsiExpression[] expressions = argumentList.getExpressions();
if (expressions.length != 1) return false;
if (!(expressions[0] instanceof PsiLambdaExpression)) return false;
final PsiElement lambdaBody = ((PsiLambdaExpression)expressions[0]).getBody();
if (!(lambdaBody instanceof PsiExpression)) return false;
if (!StreamRefactoringUtil.isRefactoringCandidate(expressions[0], true)) return false;
final PsiMethod method = methodCallExpression.resolveMethod();
if (method == null) return false;
final PsiClass containingClass = method.getContainingClass();
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length == 1 &&
InheritanceUtil.isInheritor(containingClass, false, CommonClassNames.JAVA_UTIL_STREAM_STREAM) &&
InheritanceUtil.isInheritor(parameters[0].getType(), CommonClassNames.JAVA_UTIL_FUNCTION_PREDICATE)) {
return true;
}
return false;
return parameters.length == 1 &&
InheritanceUtil.isInheritor(containingClass, false, CommonClassNames.JAVA_UTIL_STREAM_BASE_STREAM);
}
@NotNull
@@ -101,6 +98,19 @@ public class MergeFilterChainAction extends PsiElementBaseIntentionAction {
return CodeInsightBundle.message("intention.merge.filter.family");
}
@Nullable
private static PsiLambdaExpression getLambda(PsiMethodCallExpression call) {
PsiExpression[] expressions = call.getArgumentList().getExpressions();
if(expressions.length != 1) return null;
PsiExpression expression = expressions[0];
if(expression instanceof PsiLambdaExpression) return (PsiLambdaExpression)expression;
if (expression instanceof PsiMethodReferenceExpression) {
return LambdaRefactoringUtil
.convertMethodReferenceToLambda((PsiMethodReferenceExpression)expression, false, true);
}
return null;
}
@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
try {
@@ -115,11 +125,16 @@ public class MergeFilterChainAction extends PsiElementBaseIntentionAction {
final PsiMethodCallExpression callToStay = filterCall.getTextLength() < filterToMerge.getTextLength() ? filterCall : filterToMerge;
final PsiMethodCallExpression callToEliminate = callToStay == filterCall ? filterToMerge : filterCall;
final PsiLambdaExpression targetLambda = (PsiLambdaExpression)callToStay.getArgumentList().getExpressions()[0];
String resultingOperation = callToEliminate.getMethodExpression().getReferenceName();
LOG.assertTrue(resultingOperation != null);
final PsiLambdaExpression targetLambda = getLambda(callToStay);
LOG.assertTrue(targetLambda != null, callToStay);
final PsiParameter[] parameters = targetLambda.getParameterList().getParameters();
final String name = parameters.length > 0 ? parameters[0].getName() : null;
final PsiLambdaExpression sourceLambda = (PsiLambdaExpression)callToEliminate.getArgumentList().getExpressions()[0];
final PsiLambdaExpression sourceLambda = getLambda(callToEliminate);
LOG.assertTrue(sourceLambda != null, callToEliminate);
if (name != null) {
final PsiParameter[] sourceLambdaParams = sourceLambda.getParameterList().getParameters();
if (sourceLambdaParams.length > 0 && !name.equals(sourceLambdaParams[0].getName())) {
@@ -132,14 +147,20 @@ public class MergeFilterChainAction extends PsiElementBaseIntentionAction {
}
}
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
PsiElement nameElement = callToStay.getMethodExpression().getReferenceNameElement();
LOG.assertTrue(nameElement != null);
if(!resultingOperation.equals(nameElement.getText())) {
nameElement.replace(factory.createIdentifier(resultingOperation));
}
PsiElement targetBody = targetLambda.getBody();
LOG.assertTrue(targetBody instanceof PsiExpression);
final PsiElement sourceLambdaBody = sourceLambda.getBody();
LOG.assertTrue(sourceLambdaBody instanceof PsiExpression);
final PsiExpression compoundExpression = JavaPsiFacade.getElementFactory(project)
final PsiExpression compoundExpression = factory
.createExpressionFromText(
ParenthesesUtils.getText((PsiExpression)targetBody, ParenthesesUtils.OR_PRECEDENCE) + " && " +
ParenthesesUtils.getText((PsiExpression)sourceLambdaBody, ParenthesesUtils.OR_PRECEDENCE), sourceLambda);
@@ -0,0 +1,38 @@
/*
* Copyright 2000-2016 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.codeInsight.intention.impl;
import com.intellij.psi.LambdaUtil;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiLambdaExpression;
import com.intellij.psi.PsiMethodReferenceExpression;
import com.intellij.refactoring.util.LambdaRefactoringUtil;
/**
* @author Tagir Valeev
*/
public class StreamRefactoringUtil {
static boolean isRefactoringCandidate(PsiExpression expression, boolean requireExpressionLambda) {
if(expression instanceof PsiLambdaExpression) {
PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)expression;
return lambdaExpression.getParameterList().getParametersCount() == 1 &&
(!requireExpressionLambda || LambdaUtil.extractSingleExpressionFromBody(lambdaExpression.getBody()) != null);
} else if(expression instanceof PsiMethodReferenceExpression) {
return LambdaRefactoringUtil.canConvertToLambda((PsiMethodReferenceExpression)expression);
}
return false;
}
}