mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+3
-1
@@ -315,7 +315,9 @@ public class CreatePropertyFromUsageFix extends CreateFromUsageBaseFix implement
|
||||
}
|
||||
|
||||
protected void beforeTemplateFinished(PsiClass aClass, PsiField field) {
|
||||
positionCursor(myMethodCall.getProject(), myMethodCall.getContainingFile(), myMethodCall);
|
||||
if (myMethodCall.isValid()) {
|
||||
positionCursor(myMethodCall.getProject(), myMethodCall.getContainingFile(), myMethodCall);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getVariableName(PsiMethodCallExpression methodCall, boolean isStatic) {
|
||||
|
||||
+1
@@ -48,6 +48,7 @@ public class AddOverrideAnnotationAction implements IntentionAction {
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
if (!PsiUtil.isLanguageLevel5OrHigher(file)) return false;
|
||||
if (!file.getManager().isInProject(file)) return false;
|
||||
PsiMethod method = findMethod(file, editor.getCaretModel().getOffset());
|
||||
if (method == null) return false;
|
||||
if (method.getModifierList().findAnnotation(JAVA_LANG_OVERRIDE) != null) return false;
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
package com.intellij.psi;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.RecursionGuard;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -95,79 +99,6 @@ public class LambdaUtil {
|
||||
return signatures.size() == 1 ? null : "Multiple non-overriding abstract methods found";
|
||||
}
|
||||
|
||||
|
||||
public static PsiType getLambdaParameterType(PsiParameter param) {
|
||||
final PsiElement paramParent = param.getParent();
|
||||
if (paramParent instanceof PsiParameterList) {
|
||||
final int parameterIndex = ((PsiParameterList)paramParent).getParameterIndex(param);
|
||||
if (parameterIndex > -1) {
|
||||
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(param, PsiLambdaExpression.class);
|
||||
final PsiType type = getFunctionInterfaceType(lambdaExpression);
|
||||
final PsiClassType.ClassResolveResult resolveResult = type instanceof PsiClassType ? ((PsiClassType)type).resolveGenerics() : null;
|
||||
if (resolveResult != null) {
|
||||
final MethodSignature methodSignature = getFunction(resolveResult.getElement());
|
||||
if (methodSignature != null) {
|
||||
final PsiType[] types = methodSignature.getParameterTypes();
|
||||
if (parameterIndex < types.length) {
|
||||
final PsiType psiType = resolveResult.getSubstitutor().substitute(types[parameterIndex]);
|
||||
if (psiType instanceof PsiWildcardType) {
|
||||
final PsiType bound = ((PsiWildcardType)psiType).getBound();
|
||||
if (bound != null) {
|
||||
return bound;
|
||||
}
|
||||
}
|
||||
return psiType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new PsiLambdaParameterType(param);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiType getFunctionInterfaceType(@Nullable PsiLambdaExpression lambdaExpression) {
|
||||
if (lambdaExpression != null) {
|
||||
final PsiElement parent = lambdaExpression.getParent();
|
||||
PsiType type = null;
|
||||
if (parent instanceof PsiTypeCastExpression) {
|
||||
type = ((PsiTypeCastExpression)parent).getType();
|
||||
}
|
||||
else if (parent instanceof PsiVariable) {
|
||||
type = ((PsiVariable)parent).getType();
|
||||
}
|
||||
else if (parent instanceof PsiAssignmentExpression) {
|
||||
final PsiExpression lExpression = ((PsiAssignmentExpression)parent).getLExpression();
|
||||
type = lExpression.getType();
|
||||
}
|
||||
else if (parent instanceof PsiExpressionList) {
|
||||
final PsiExpressionList expressionList = (PsiExpressionList)parent;
|
||||
final int lambdaIdx = getLambdaIdx(expressionList, lambdaExpression);
|
||||
if (lambdaIdx > -1) {
|
||||
final PsiElement gParent = expressionList.getParent();
|
||||
if (gParent instanceof PsiMethodCallExpression) {
|
||||
final JavaResolveResult resolveResult = ((PsiMethodCallExpression)gParent).resolveMethodGenerics();
|
||||
final PsiElement resolve = resolveResult.getElement();
|
||||
if (resolve instanceof PsiMethod) {
|
||||
final PsiParameter[] parameters = ((PsiMethod)resolve).getParameterList().getParameters();
|
||||
if (lambdaIdx < parameters.length) {
|
||||
type = resolveResult.getSubstitutor().substitute(parameters[lambdaIdx].getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (parent instanceof PsiReturnStatement) {
|
||||
final PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class);
|
||||
if (method != null) {
|
||||
type = method.getReturnType();
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isAcceptable(PsiLambdaExpression lambdaExpression, final PsiType leftType) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(leftType);
|
||||
final PsiClass psiClass = resolveResult.getElement();
|
||||
@@ -195,22 +126,29 @@ public class LambdaUtil {
|
||||
}
|
||||
LOG.assertTrue(psiClass != null);
|
||||
PsiType methodReturnType = getReturnType(psiClass, methodSignature);
|
||||
if (methodReturnType != null && methodReturnType != PsiType.VOID) {
|
||||
methodReturnType = resolveResult.getSubstitutor().substitute(methodSignature.getSubstitutor().substitute(methodReturnType));
|
||||
final PsiElement body = lambdaExpression.getBody();
|
||||
if (body instanceof PsiCodeBlock) {
|
||||
final PsiCodeBlock block = (PsiCodeBlock)body;
|
||||
for (PsiStatement statement : block.getStatements()) {
|
||||
if (statement instanceof PsiReturnStatement) {
|
||||
final PsiExpression returnValue = ((PsiReturnStatement)statement).getReturnValue();
|
||||
if (returnValue != null) {
|
||||
if (!checkReturnTypeAssignability(returnValue.getType(), parameterTypes, lambdaExpression, methodReturnType)) return false;
|
||||
if (methodReturnType != null) {
|
||||
if (methodReturnType != PsiType.VOID) {
|
||||
methodReturnType = resolveResult.getSubstitutor().substitute(methodSignature.getSubstitutor().substitute(methodReturnType));
|
||||
final PsiElement body = lambdaExpression.getBody();
|
||||
if (body instanceof PsiCodeBlock) {
|
||||
final PsiCodeBlock block = (PsiCodeBlock)body;
|
||||
for (PsiStatement statement : block.getStatements()) {
|
||||
if (statement instanceof PsiReturnStatement) {
|
||||
final PsiExpression returnValue = ((PsiReturnStatement)statement).getReturnValue();
|
||||
if (returnValue != null) {
|
||||
if (!checkReturnTypeAssignability(returnValue.getType(), parameterTypes, lambdaExpression, methodReturnType)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (body instanceof PsiExpression) {
|
||||
return checkReturnTypeAssignability(((PsiExpression)body).getType(), parameterTypes, lambdaExpression, methodReturnType);
|
||||
else if (body instanceof PsiExpression) {
|
||||
return checkReturnTypeAssignability(((PsiExpression)body).getType(), parameterTypes, lambdaExpression, methodReturnType);
|
||||
}
|
||||
} else {
|
||||
final List<PsiExpression> returnExpressions = lambdaExpression.getReturnExpressions();
|
||||
for (PsiExpression returnValue : returnExpressions) {
|
||||
if (returnValue.getType() != PsiType.VOID) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -331,6 +269,37 @@ public class LambdaUtil {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static boolean dependsOnTypeParams(PsiType type, PsiLambdaExpression expr) {
|
||||
final Boolean accept = type.accept(new TypeParamsChecker(expr));
|
||||
return accept != null && accept.booleanValue();
|
||||
}
|
||||
|
||||
public static boolean isFreeFromTypeInferenceArgs(final PsiParameter[] methodParameters,
|
||||
final PsiLambdaExpression lambdaExpression,
|
||||
final PsiExpression expression) {
|
||||
final PsiParameter[] lambdaParams = lambdaExpression.getParameterList().getParameters();
|
||||
final boolean [] independent = new boolean[]{true};
|
||||
expression.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
int usedParamIdx = -1;
|
||||
for (int i = 0; i < lambdaParams.length; i++) {
|
||||
PsiParameter param = lambdaParams[i];
|
||||
if (expression.isReferenceTo(param)) {
|
||||
usedParamIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (usedParamIdx > -1 && dependsOnTypeParams(methodParameters[usedParamIdx].getType(), lambdaExpression)) {
|
||||
independent[0] = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return independent[0];
|
||||
}
|
||||
|
||||
private static class TypeParamsChecker extends PsiTypeVisitor<Boolean> {
|
||||
private final PsiLambdaExpression myExpression;
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ package com.intellij.psi;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.RecursionGuard;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
@@ -29,6 +31,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @see JavaPsiFacade#getResolveHelper()
|
||||
*/
|
||||
public interface PsiResolveHelper {
|
||||
RecursionGuard ourGuard = RecursionManager.createGuard("typeArgInference");
|
||||
|
||||
class SERVICE {
|
||||
private SERVICE() {
|
||||
}
|
||||
|
||||
@@ -21,20 +21,26 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
|
||||
import com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.containers.ConcurrentHashMap;
|
||||
import com.intellij.util.containers.ConcurrentWeakHashMap;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author ik, dsl
|
||||
*/
|
||||
public class MethodCandidateInfo extends CandidateInfo{
|
||||
public static final Key<PsiMethod> CURRENT_CANDIDATE = Key.create("CURRENT_CANDIDATE");
|
||||
public static final ThreadLocal<Map<PsiElement, PsiMethod>> CURRENT_CANDIDATE = new ThreadLocal<Map<PsiElement, PsiMethod>>();
|
||||
@ApplicabilityLevelConstant private int myApplicabilityLevel = 0;
|
||||
private final PsiElement myArgumentList;
|
||||
private final PsiType[] myArgumentTypes;
|
||||
private final PsiType[] myTypeArguments;
|
||||
private PsiSubstitutor myCalcedSubstitutor = null;
|
||||
private final LanguageLevel myLanguageLevel;
|
||||
private static final Object LOCK = new Object();
|
||||
|
||||
public MethodCandidateInfo(PsiElement candidate,
|
||||
PsiSubstitutor substitutor,
|
||||
@@ -92,12 +98,20 @@ public class MethodCandidateInfo extends CandidateInfo{
|
||||
PsiSubstitutor incompleteSubstitutor = super.getSubstitutor();
|
||||
PsiMethod method = getElement();
|
||||
if (myTypeArguments == null) {
|
||||
myArgumentList.putUserData(CURRENT_CANDIDATE, getElement());
|
||||
Map<PsiElement, PsiMethod> map;
|
||||
synchronized (LOCK) {
|
||||
map = CURRENT_CANDIDATE.get();
|
||||
if (map == null) {
|
||||
map = new ConcurrentWeakHashMap<PsiElement, PsiMethod>();
|
||||
CURRENT_CANDIDATE.set(map);
|
||||
}
|
||||
}
|
||||
map.put(myArgumentList, getElement());
|
||||
try {
|
||||
myCalcedSubstitutor = inferTypeArguments(DefaultParameterTypeInferencePolicy.INSTANCE);
|
||||
}
|
||||
finally {
|
||||
myArgumentList.putUserData(CURRENT_CANDIDATE, null);
|
||||
map.remove(myArgumentList);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -29,7 +29,7 @@ import com.intellij.psi.impl.java.stubs.PsiParameterStub;
|
||||
import com.intellij.psi.impl.source.tree.ChildRole;
|
||||
import com.intellij.psi.impl.source.tree.CompositeElement;
|
||||
import com.intellij.psi.impl.source.tree.JavaSharedImplUtil;
|
||||
import com.intellij.psi.LambdaUtil;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiLambdaExpressionImpl;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.ui.RowIcon;
|
||||
@@ -122,7 +122,7 @@ public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> imple
|
||||
|
||||
final PsiTypeElement typeElement = getTypeElement();
|
||||
if (typeElement == null && isLambdaParameter()) {
|
||||
return LambdaUtil.getLambdaParameterType(this);
|
||||
return PsiLambdaExpressionImpl.getLambdaParameterType(this);
|
||||
}
|
||||
|
||||
return JavaSharedImplUtil.getType(typeElement, getNameIdentifier(), this);
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ public class ProcessCandidateParameterTypeInferencePolicy extends DefaultParamet
|
||||
}
|
||||
if (parameter != null) {
|
||||
final PsiParameter finalParameter = parameter;
|
||||
PsiType type = PsiResolveHelperImpl.ourGuard.doPreventingRecursion(innerMethodCall, true, new Computable<PsiType>() {
|
||||
PsiType type = PsiResolveHelper.ourGuard.doPreventingRecursion(innerMethodCall, true, new Computable<PsiType>() {
|
||||
@Override
|
||||
public PsiType compute() {
|
||||
return substitutor.substitute(finalParameter.getType());
|
||||
|
||||
+83
-29
@@ -17,8 +17,6 @@ package com.intellij.psi.impl.source.resolve;
|
||||
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.RecursionGuard;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiLambdaExpressionImpl;
|
||||
@@ -38,9 +36,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
static final RecursionGuard ourGuard = RecursionManager.createGuard("typeArgInference");
|
||||
private final PsiManager myManager;
|
||||
|
||||
public PsiResolveHelperImpl(PsiManager manager) {
|
||||
@@ -130,7 +128,8 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
@NotNull PsiElement place,
|
||||
@Nullable PsiClass accessObjectClass,
|
||||
final PsiElement currentFileResolveScope) {
|
||||
return JavaResolveUtil.isAccessible(member, member.getContainingClass(), modifierList, place, accessObjectClass, currentFileResolveScope);
|
||||
return JavaResolveUtil.isAccessible(member, member.getContainingClass(), modifierList, place, accessObjectClass,
|
||||
currentFileResolveScope);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,9 +165,11 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
paramTypes[j] = parameter.getType();
|
||||
if (paramTypes[j] instanceof PsiEllipsisType) {
|
||||
paramTypes[j] = ((PsiEllipsisType)paramTypes[j]).getComponentType();
|
||||
if (arguments.length == parameters.length && argTypes[j] instanceof PsiArrayType && !(((PsiArrayType)argTypes[j]).getComponentType() instanceof PsiPrimitiveType)) {
|
||||
argTypes[j] = ((PsiArrayType)argTypes[j]).getComponentType();
|
||||
}
|
||||
if (arguments.length == parameters.length &&
|
||||
argTypes[j] instanceof PsiArrayType &&
|
||||
!(((PsiArrayType)argTypes[j]).getComponentType() instanceof PsiPrimitiveType)) {
|
||||
argTypes[j] = ((PsiArrayType)argTypes[j]).getComponentType();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,6 +186,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
PsiType lowerBound = PsiType.NULL;
|
||||
PsiType upperBound = PsiType.NULL;
|
||||
if (paramTypes.length > 0) {
|
||||
sortLambdaExpressionsLast(paramTypes, argTypes);
|
||||
for (int j = 0; j < argTypes.length; j++) {
|
||||
PsiType argumentType = argTypes[j];
|
||||
if (argumentType == null) continue;
|
||||
@@ -199,8 +201,13 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
argumentType = ((PsiArrayType)argumentType).getComponentType();
|
||||
}
|
||||
}
|
||||
final Pair<PsiType,ConstraintType> currentSubstitution = getSubstitutionForTypeParameterConstraint(typeParameter, parameterType,
|
||||
argumentType, true, PsiUtil.getLanguageLevel(typeParameter));
|
||||
final Pair<PsiType,ConstraintType> currentSubstitution;
|
||||
if (argumentType instanceof PsiLambdaExpressionType) {
|
||||
currentSubstitution = inferSubstitutionFromLambda(typeParameter, (PsiLambdaExpressionType)argumentType, lowerBound);
|
||||
} else {
|
||||
currentSubstitution = getSubstitutionForTypeParameterConstraint(typeParameter, parameterType,
|
||||
argumentType, true, PsiUtil.getLanguageLevel(typeParameter));
|
||||
}
|
||||
if (currentSubstitution == null) continue;
|
||||
if (currentSubstitution == FAILED_INFERENCE) {
|
||||
return getFailedInferenceConstraint(typeParameter);
|
||||
@@ -268,6 +275,23 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void sortLambdaExpressionsLast(PsiType[] paramTypes, PsiType[] argTypes) {
|
||||
for (int i = 0; i < argTypes.length; i++) {
|
||||
PsiType argType = argTypes[i];
|
||||
if (argType instanceof PsiLambdaExpressionType && i < argTypes.length - 1) {
|
||||
int k = i + 1;
|
||||
while(argTypes[k] instanceof PsiLambdaExpressionType && k < argTypes.length - 1) {
|
||||
k++;
|
||||
}
|
||||
if (!(argTypes[k] instanceof PsiLambdaExpressionType)) {
|
||||
ArrayUtil.swap(paramTypes, i, k);
|
||||
ArrayUtil.swap(argTypes, i, k);
|
||||
i = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Pair<PsiType, ConstraintType> getFailedInferenceConstraint(final PsiTypeParameter typeParameter) {
|
||||
return new Pair<PsiType, ConstraintType>(JavaPsiFacade.getInstance(typeParameter.getProject()).getElementFactory().createType(typeParameter), ConstraintType.EQUALS);
|
||||
}
|
||||
@@ -509,10 +533,6 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
}
|
||||
if (paramClass == null) return null;
|
||||
|
||||
if (arg instanceof PsiLambdaExpressionType) {
|
||||
return inferSubstitutionFromLambda(typeParam, (PsiLambdaExpressionType)arg);
|
||||
}
|
||||
|
||||
if (!(arg instanceof PsiClassType)) return null;
|
||||
|
||||
JavaResolveResult argResult = ((PsiClassType)arg).resolveGenerics();
|
||||
@@ -536,24 +556,26 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Pair<PsiType, ConstraintType> inferSubstitutionFromLambda(PsiTypeParameter typeParam, PsiLambdaExpressionType arg) {
|
||||
private static Pair<PsiType, ConstraintType> inferSubstitutionFromLambda(PsiTypeParameter typeParam,
|
||||
PsiLambdaExpressionType arg,
|
||||
PsiType lowerBound) {
|
||||
final PsiLambdaExpression lambdaExpression = arg.getExpression();
|
||||
if (PsiUtil.getLanguageLevel(lambdaExpression).isAtLeast(LanguageLevel.JDK_1_8)) {
|
||||
final PsiElement parent = skipParenthesizedExprUp(lambdaExpression.getParent());
|
||||
if (parent instanceof PsiExpressionList) {
|
||||
final PsiExpressionList expressionList = (PsiExpressionList)parent;
|
||||
final PsiMethod method = expressionList.getUserData(MethodCandidateInfo.CURRENT_CANDIDATE);
|
||||
final Map<PsiElement,PsiMethod> methodMap = MethodCandidateInfo.CURRENT_CANDIDATE.get();
|
||||
final PsiMethod method = methodMap != null ? methodMap.get(expressionList) : null;
|
||||
if (method != null) {
|
||||
final int i = LambdaUtil.getLambdaIdx(expressionList,
|
||||
((PsiLambdaExpressionImpl)lambdaExpression));
|
||||
final int i = LambdaUtil.getLambdaIdx(expressionList, lambdaExpression);
|
||||
if (i < 0) return null;
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (parameters.length <= i) return null;
|
||||
return inferConstraintFromFunctionalInterfaceMethod(typeParam, lambdaExpression, parameters[i].getType());
|
||||
return inferConstraintFromFunctionalInterfaceMethod(typeParam, lambdaExpression, parameters[i].getType(), lowerBound);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return inferConstraintFromFunctionalInterfaceMethod(typeParam, lambdaExpression, lambdaExpression.getFunctionalInterfaceType());
|
||||
return inferConstraintFromFunctionalInterfaceMethod(typeParam, lambdaExpression, lambdaExpression.getFunctionalInterfaceType(), lowerBound);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -561,8 +583,9 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
|
||||
@Nullable
|
||||
private static Pair<PsiType, ConstraintType> inferConstraintFromFunctionalInterfaceMethod(PsiTypeParameter typeParam,
|
||||
PsiLambdaExpression lambdaExpression,
|
||||
PsiType functionalInterfaceType) {
|
||||
final PsiLambdaExpression lambdaExpression,
|
||||
final PsiType functionalInterfaceType,
|
||||
PsiType lowerBound) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
|
||||
final PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType);
|
||||
if (method != null) {
|
||||
@@ -573,9 +596,14 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
final PsiSubstitutor subst = resolveResult.getSubstitutor();
|
||||
final PsiType returnType = subst.substitute(method.getReturnType());
|
||||
if (returnType != null && returnType != PsiType.VOID) {
|
||||
Pair<PsiType, ConstraintType> constraint = null;
|
||||
final List<PsiExpression> expressions = lambdaExpression.getReturnExpressions();
|
||||
for (final PsiExpression expression : expressions) {
|
||||
PsiType exprType = ourGuard.doPreventingRecursion(lambdaExpression, true, new Computable<PsiType>() {
|
||||
final boolean independent = LambdaUtil.isFreeFromTypeInferenceArgs(methodParameters, lambdaExpression, expression);
|
||||
if (!independent && lowerBound != PsiType.NULL) {
|
||||
return null;
|
||||
}
|
||||
PsiType exprType = independent ? expression.getType() : ourGuard.doPreventingRecursion(lambdaExpression, true, new Computable<PsiType>() {
|
||||
@Override
|
||||
public PsiType compute() {
|
||||
return expression.getType();
|
||||
@@ -588,15 +616,32 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
exprType = subst.substitute(methodParameters[parameterIndex].getType());
|
||||
}
|
||||
} else if (exprType instanceof PsiLambdaExpressionType) {
|
||||
return inferConstraintFromFunctionalInterfaceMethod(typeParam, ((PsiLambdaExpressionType)exprType).getExpression(), returnType);
|
||||
return inferConstraintFromFunctionalInterfaceMethod(typeParam, ((PsiLambdaExpressionType)exprType).getExpression(), returnType,
|
||||
lowerBound);
|
||||
}
|
||||
if (exprType == null) return null;
|
||||
Pair<PsiType, ConstraintType> constraint =
|
||||
|
||||
if (exprType == null){
|
||||
return FAILED_INFERENCE;
|
||||
}
|
||||
|
||||
final Pair<PsiType, ConstraintType> returnExprConstraint =
|
||||
getSubstitutionForTypeParameterConstraint(typeParam, returnType, exprType, false, PsiUtil.getLanguageLevel(method));
|
||||
if (constraint != null) {
|
||||
return constraint; //todo check that all return statements lead to the same inference
|
||||
if (returnExprConstraint != null) {
|
||||
if (returnExprConstraint == FAILED_INFERENCE) return returnExprConstraint;
|
||||
if (constraint != null) {
|
||||
final PsiType leastUpperBound = GenericsUtil.getLeastUpperBound(constraint.getFirst(), returnExprConstraint.getFirst(), typeParam.getManager());
|
||||
constraint = new Pair<PsiType, ConstraintType>(leastUpperBound, ConstraintType.SUPERTYPE);
|
||||
} else {
|
||||
constraint = returnExprConstraint;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (constraint != null) return constraint;
|
||||
}
|
||||
for (PsiParameter parameter : methodParameters) {
|
||||
if (LambdaUtil.dependsOnTypeParams(parameter.getType(), lambdaExpression)) {
|
||||
return getFailedInferenceConstraint(typeParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -793,6 +838,9 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
}
|
||||
} else if (parent instanceof PsiLambdaExpression) {
|
||||
expectedType = LambdaUtil.getFunctionalInterfaceReturnType(((PsiLambdaExpression)parent).getFunctionalInterfaceType());
|
||||
if (expectedType == null) {
|
||||
return getFailedInferenceConstraint(typeParameter);
|
||||
}
|
||||
}
|
||||
|
||||
final PsiManager manager = typeParameter.getManager();
|
||||
@@ -829,8 +877,14 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
final PsiExpressionList argumentList = methodCall.getArgumentList();
|
||||
if (argumentList != null && PsiUtil.getLanguageLevel(argumentList).isAtLeast(LanguageLevel.JDK_1_8)) {
|
||||
for (PsiExpression expression : argumentList.getExpressions()) {
|
||||
if (expression instanceof PsiLambdaExpression){
|
||||
return getFailedInferenceConstraint(typeParameter);
|
||||
if (expression instanceof PsiLambdaExpression) {
|
||||
if (((PsiLambdaExpression)expression).getParameterList().getParametersCount() > 0){
|
||||
return getFailedInferenceConstraint(typeParameter);
|
||||
}
|
||||
final PsiType functionalInterfaceType = PsiLambdaExpressionImpl.getFunctionalInterfaceType(((PsiLambdaExpression)expression), false);
|
||||
if (functionalInterfaceType == null || PsiUtil.resolveClassInType(functionalInterfaceType) == typeParameter){
|
||||
return getFailedInferenceConstraint(typeParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+51
-11
@@ -20,6 +20,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -29,7 +30,6 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements PsiLambdaExpression {
|
||||
public static RecursionGuard ourGuard = RecursionManager.createGuard("Lambda");
|
||||
|
||||
public PsiLambdaExpressionImpl() {
|
||||
super(JavaElementType.LAMBDA_EXPRESSION);
|
||||
@@ -76,7 +76,12 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getFunctionalInterfaceType() {
|
||||
PsiElement parent = getParent();
|
||||
return getFunctionalInterfaceType(this, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiType getFunctionalInterfaceType(PsiLambdaExpression expression, final boolean tryToSubstitute) {
|
||||
PsiElement parent = expression.getParent();
|
||||
while (parent instanceof PsiParenthesizedExpression) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
@@ -93,8 +98,7 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
|
||||
}
|
||||
else if (parent instanceof PsiExpressionList) {
|
||||
final PsiExpressionList expressionList = (PsiExpressionList)parent;
|
||||
int lambdaIdx = LambdaUtil.getLambdaIdx(expressionList, this);
|
||||
|
||||
int lambdaIdx = LambdaUtil.getLambdaIdx(expressionList, expression);
|
||||
if (lambdaIdx > -1) {
|
||||
final PsiElement gParent = expressionList.getParent();
|
||||
if (gParent instanceof PsiMethodCallExpression) {
|
||||
@@ -105,13 +109,15 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
|
||||
final PsiParameter[] parameters = ((PsiMethod)resolve).getParameterList().getParameters();
|
||||
if (lambdaIdx < parameters.length) {
|
||||
type = parameters[lambdaIdx].getType();
|
||||
final PsiType psiType = type;
|
||||
type = ourGuard.doPreventingRecursion(this, true, new Computable<PsiType>() {
|
||||
@Override
|
||||
public PsiType compute() {
|
||||
return resolveResult.getSubstitutor().substitute(psiType);
|
||||
}
|
||||
});
|
||||
if (tryToSubstitute) {
|
||||
final PsiType psiType = type;
|
||||
type = PsiResolveHelper.ourGuard.doPreventingRecursion(expression, true, new Computable<PsiType>() {
|
||||
@Override
|
||||
public PsiType compute() {
|
||||
return resolveResult.getSubstitutor().substitute(psiType);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,4 +165,38 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
|
||||
public String toString() {
|
||||
return "PsiLambdaExpression:" + getText();
|
||||
}
|
||||
|
||||
public static PsiType getLambdaParameterType(PsiParameter param) {
|
||||
final PsiElement paramParent = param.getParent();
|
||||
if (paramParent instanceof PsiParameterList) {
|
||||
final int parameterIndex = ((PsiParameterList)paramParent).getParameterIndex(param);
|
||||
if (parameterIndex > -1) {
|
||||
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(param, PsiLambdaExpression.class);
|
||||
PsiType type = getFunctionalInterfaceType(lambdaExpression, true);
|
||||
if (type == null) {
|
||||
type = getFunctionalInterfaceType(lambdaExpression, false);
|
||||
}
|
||||
final PsiClassType.ClassResolveResult resolveResult = type instanceof PsiClassType ? ((PsiClassType)type).resolveGenerics() : null;
|
||||
if (resolveResult != null) {
|
||||
final PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(type);
|
||||
if (method != null) {
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (parameterIndex < parameters.length) {
|
||||
final PsiType psiType = resolveResult.getSubstitutor().substitute(parameters[parameterIndex].getType());
|
||||
if (!LambdaUtil.dependsOnTypeParams(psiType, lambdaExpression)) {
|
||||
if (psiType instanceof PsiWildcardType) {
|
||||
final PsiType bound = ((PsiWildcardType)psiType).getBound();
|
||||
if (bound != null) {
|
||||
return bound;
|
||||
}
|
||||
}
|
||||
return psiType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new PsiLambdaParameterType(param);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ class InferenceFromArgs {
|
||||
bar(b, (k, v) -> {Integer i = k; return v;});
|
||||
|
||||
bazz(<error descr="Cyclic inference">(k, v) -> v</error>);
|
||||
bazz((k, v) -> {<error descr="Incompatible types. Found: 'E', required: 'int'">int i = k;</error> return v;});
|
||||
bazz((k, v) -> {<error descr="Incompatible types. Found: '<lambda parameter>', required: 'int'">int i = k;</error> return v;});
|
||||
}
|
||||
|
||||
public static <T> SameArgsI<T> max() {
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ class ReturnTypeCompatibility {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
call(<error descr="Cyclic inference">i-> {return i;}</error>);
|
||||
<error descr="Cannot resolve method 'call(<lambda expression>)'">call</error>(i-> {return i;});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+60
@@ -15,3 +15,63 @@ class TypeArgsConsistency {
|
||||
<error descr="Incompatible types. Found: 'TypeArgsConsistency.I<java.lang.String>', required: 'TypeArgsConsistency.I<java.lang.Integer>'">I<Integer> i3 = bar((i, j) -> "" + i + j);</error>
|
||||
}
|
||||
}
|
||||
|
||||
class TypeArgsConsistency1 {
|
||||
|
||||
interface I<T> {
|
||||
int m(int i, T j);
|
||||
}
|
||||
|
||||
static void foo(I<Integer> s) { }
|
||||
|
||||
static <X> I<X> bar(I<X> s) { return null; }
|
||||
|
||||
{
|
||||
I<Integer> i1 = (i, j) -> i + j;
|
||||
foo((i, j) -> i + j);
|
||||
I<Integer> i2 =bar(<error descr="Cyclic inference">(i, j) -> i</error>) ;
|
||||
I<Integer> i3 = bar(<error descr="Cyclic inference">(i, j) -> "" + i + j</error>);
|
||||
}
|
||||
}
|
||||
|
||||
class TypeArgsConsistency2 {
|
||||
static <T> I<T> bar(I<T> i) {return null;}
|
||||
static <T> I1<T> bar1(I1<T> i) {return null;}
|
||||
static <T> I2<T> bar2(I2<T> i) {return i;}
|
||||
|
||||
public static void main(String[] args) {
|
||||
I<Integer> i1 = bar(<error descr="Cyclic inference">x -> x</error>);
|
||||
I1<Integer> i2 = bar1(<error descr="Cyclic inference">x -> 1</error>);
|
||||
I2<String> aI2 = bar2(x -> "");
|
||||
<error descr="Incompatible types. Found: 'TypeArgsConsistency2.I2<java.lang.String>', required: 'TypeArgsConsistency2.I2<java.lang.Integer>'">I2<Integer> aI28 = bar2( x-> "");</error>
|
||||
I2<Integer> i3 = bar2(x -> x);
|
||||
I2<Integer> i4 = bar2(x -> foooI());
|
||||
System.out.println(i4.foo(2));
|
||||
}
|
||||
|
||||
static <K> K fooo(){return null;}
|
||||
static int foooI(){return 0;}
|
||||
|
||||
interface I<X> {
|
||||
X foo(X x);
|
||||
}
|
||||
interface I1<X> {
|
||||
|
||||
int foo(X x);
|
||||
}
|
||||
|
||||
interface I2<X> {
|
||||
X foo(int x);
|
||||
}
|
||||
}
|
||||
|
||||
class TypeArgsConsistency3 {
|
||||
public static void main(String[] args) {
|
||||
doIt1(1, x -> doIt1(x, y -> x * y));
|
||||
doIt1(1, x -> x);
|
||||
doIt1(1, x -> x * x);
|
||||
}
|
||||
interface F1<ResultType, P1> { ResultType _(P1 p); }
|
||||
static <T> T doIt1(T i, F1<T,T> f) { return f._(i);}
|
||||
}
|
||||
|
||||
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.
|
||||
*/
|
||||
import java.util.List;
|
||||
class Test1 {
|
||||
|
||||
interface I<X> {
|
||||
X foo(List<String> list);
|
||||
}
|
||||
|
||||
static <T> I<T> bar(I<T> i){return i;}
|
||||
static <T> void bar1(I<T> i){}
|
||||
static <T> void bar2(T t, I<T> i){}
|
||||
static <T> void bar3(I<T> i, T t){}
|
||||
|
||||
{
|
||||
bar(x -> x);
|
||||
bar1(x -> x);
|
||||
|
||||
I<Object> lO = x->x;
|
||||
bar2("", lO);
|
||||
|
||||
<error descr="Incompatible types. Found: '<lambda expression>', required: 'Test1.I<java.lang.String>'">I<String> lS = x->x;</error>
|
||||
bar2("", lS);
|
||||
|
||||
bar2("", x -> x);
|
||||
|
||||
bar3(x -> x, "");
|
||||
|
||||
int ixc = 42;
|
||||
bar(x -> {
|
||||
if (ixc == 2) return "aaa";
|
||||
return x;
|
||||
});
|
||||
bar(x -> {
|
||||
if (ixc == 2) return x;
|
||||
return x;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Test2 {
|
||||
|
||||
interface I<X> {
|
||||
X foo(List<X> list);
|
||||
}
|
||||
|
||||
static <T> I<T> bar(I<T> i){return i;}
|
||||
static <T> void bar1(I<T> i){}
|
||||
static <T> void bar2(T t, I<T> i){}
|
||||
static <T> void bar3(I<T> i, T t){}
|
||||
|
||||
{
|
||||
bar(<error descr="Cyclic inference">x -> x</error>);
|
||||
bar1(<error descr="Cyclic inference">x -> x</error>);
|
||||
bar2<error descr="'bar2(java.lang.Integer, Test2.I<java.lang.Integer>)' in 'Test2' cannot be applied to '(int, <lambda expression>)'">(1, x -> x)</error>;
|
||||
bar2<error descr="'bar2(java.lang.String, Test2.I<java.lang.String>)' in 'Test2' cannot be applied to '(java.lang.String, <lambda expression>)'">("", x -> x)</error>;
|
||||
bar3<error descr="'bar3(Test2.I<java.lang.String>, java.lang.String)' in 'Test2' cannot be applied to '(<lambda expression>, java.lang.String)'">(x -> x, "")</error>;
|
||||
}
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
|
||||
interface I<X> {
|
||||
List<X> foo(List<X> list);
|
||||
}
|
||||
|
||||
static <T> I<T> bar(I<T> i){return i;}
|
||||
static <T> void bar1(I<T> i){}
|
||||
static <T> void bar2(T t, I<T> i){}
|
||||
static <T> void bar3(I<T> i, T t){}
|
||||
|
||||
{
|
||||
bar(<error descr="Cyclic inference">x -> x</error>);
|
||||
bar1(<error descr="Cyclic inference">x -> x</error>);
|
||||
bar2(1, x -> x);
|
||||
bar2("", x -> x);
|
||||
|
||||
bar3(x -> x, "");
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
import java.util.*;
|
||||
class Test4 {
|
||||
interface I<K> {
|
||||
List<K> foo();
|
||||
}
|
||||
|
||||
static <T> void bar(I<T> i){}
|
||||
|
||||
{
|
||||
bar(() -> null);
|
||||
}
|
||||
}
|
||||
|
||||
class Test5 {
|
||||
interface I<K> {
|
||||
void foo(K k);
|
||||
}
|
||||
|
||||
static <T> void bar(I<T> i){}
|
||||
|
||||
{
|
||||
bar<error descr="'bar(Test5.I<T>)' in 'Test5' cannot be applied to '(<lambda expression>)'">(() -> null)</error>;
|
||||
}
|
||||
}
|
||||
class Test6 {
|
||||
interface I<K> {
|
||||
void foo();
|
||||
}
|
||||
|
||||
static <T> void bar(I<T> i){}
|
||||
|
||||
{
|
||||
bar<error descr="'bar(Test6.I<java.lang.Object>)' in 'Test6' cannot be applied to '(<lambda expression>)'">(() -> null)</error>;
|
||||
bar(() -> {});
|
||||
}
|
||||
}
|
||||
+8
@@ -45,6 +45,14 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testTypeArgsConsistencyMisc1() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testTypeArgsConsistencyWithoutParams() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testWildcardBounds() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@@ -129,7 +129,13 @@ public abstract class RemoteProcessSupport<Target, EntryPoint, Parameters> {
|
||||
}
|
||||
if (ref.isNull()) throw new RuntimeException("Unable to acquire remote proxy for: " + getName(target));
|
||||
RunningInfo info = ref.get();
|
||||
if (info.handler == null) throw new ExecutionException(info.name);
|
||||
if (info.handler == null) {
|
||||
String message = info.name;
|
||||
if (message != null && message.startsWith("ERROR: transport error 202:")) {
|
||||
message = "Unable to start java process in debug mode: -Xdebug parameters are already in use.";
|
||||
}
|
||||
throw new ExecutionException(message);
|
||||
}
|
||||
return acquire(info);
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -66,7 +66,10 @@ class EditBookmarkDescriptionAction extends DumbAwareAction {
|
||||
BookmarkManager.getInstance(myProject).setDescription(b, description);
|
||||
|
||||
myPopup.setUiVisible(true);
|
||||
myPopup.setSize(myPopup.getContent().getPreferredSize());
|
||||
final JComponent content = myPopup.getContent();
|
||||
if (content != null) {
|
||||
myPopup.setSize(content.getPreferredSize());
|
||||
}
|
||||
}
|
||||
|
||||
public void setPopup(JBPopup popup) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.LineSeparator;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -128,6 +129,14 @@ public abstract class DiffContent {
|
||||
return new DocumentContent(project, document);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return line separator used in this content, or null if it is unknown.
|
||||
*/
|
||||
@Nullable
|
||||
public LineSeparator getLineSeparator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void contentInvalid();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.LineSeparator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DocumentContent extends DiffContent {
|
||||
@@ -28,6 +29,7 @@ public class DocumentContent extends DiffContent {
|
||||
private final VirtualFile myFile;
|
||||
private final FileType myOverridenType;
|
||||
private Project myProject;
|
||||
private FileDocumentManager myDocumentManager;
|
||||
|
||||
public DocumentContent(Project project, Document document) {
|
||||
this(project, document, null);
|
||||
@@ -36,7 +38,8 @@ public class DocumentContent extends DiffContent {
|
||||
public DocumentContent(Project project, @NotNull Document document, FileType type) {
|
||||
myProject = project;
|
||||
myDocument = document;
|
||||
myFile = FileDocumentManager.getInstance().getFile(document);
|
||||
myDocumentManager = FileDocumentManager.getInstance();
|
||||
myFile = myDocumentManager.getFile(document);
|
||||
myOverridenType = type;
|
||||
}
|
||||
|
||||
@@ -70,4 +73,10 @@ public class DocumentContent extends DiffContent {
|
||||
public byte[] getBytes() {
|
||||
return myDocument.getText().getBytes();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LineSeparator getLineSeparator() {
|
||||
return LineSeparator.fromString(myDocumentManager.getLineSeparator(myFile, myProject));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.LineSeparator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
@@ -34,10 +35,12 @@ public class FileContent extends DiffContent {
|
||||
private final VirtualFile myFile;
|
||||
private Document myDocument;
|
||||
private final Project myProject;
|
||||
private final FileDocumentManager myDocumentManager;
|
||||
|
||||
public FileContent(Project project, @NotNull VirtualFile file) {
|
||||
myProject = project;
|
||||
myFile = file;
|
||||
myDocumentManager = FileDocumentManager.getInstance();
|
||||
}
|
||||
|
||||
public Document getDocument() {
|
||||
@@ -82,4 +85,11 @@ public class FileContent extends DiffContent {
|
||||
}
|
||||
throw new IOException("Can not create temp file for revision content");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LineSeparator getLineSeparator() {
|
||||
return LineSeparator.fromString(myDocumentManager.getLineSeparator(myFile, myProject));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.LineSeparator;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -135,6 +136,12 @@ public class SimpleContent extends DiffContent {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LineSeparator getLineSeparator() {
|
||||
return LineSeparator.fromString(myLineSeparators.mySeparator);
|
||||
}
|
||||
|
||||
public Charset getCharset() {
|
||||
return myCharset;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.codeStyle;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.colors.impl.BundledColorSchemesProvider;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
@@ -29,7 +30,9 @@ public class IdeaColorSchemesProvider implements BundledColorSchemesProvider {
|
||||
@Override
|
||||
public String[] getBundledSchemesRelativePaths() {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) return null;
|
||||
return PATHS;
|
||||
if (PlatformUtils.isCommunity() || PlatformUtils.isIdea()) return PATHS;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,9 +18,7 @@ package com.intellij.openapi.diff.impl;
|
||||
import com.intellij.execution.ui.RunnerLayoutUi;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.diff.DiffRequest;
|
||||
import com.intellij.openapi.diff.DiffViewer;
|
||||
import com.intellij.openapi.diff.DiffViewerType;
|
||||
import com.intellij.openapi.diff.*;
|
||||
import com.intellij.openapi.diff.impl.external.DiscloseMultiRequest;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
@@ -97,6 +95,7 @@ public class CompositeDiffPanel implements DiffViewer {
|
||||
|
||||
if (myMap.isEmpty()) {
|
||||
final EmptyDiffViewer emptyDiffViewer = new EmptyDiffViewer();
|
||||
emptyDiffViewer.setDiffRequest(request);
|
||||
myMap.put(FICTIVE_KEY, emptyDiffViewer);
|
||||
final Content content = myUi.createContent(FICTIVE_KEY, emptyDiffViewer.getComponent(), FICTIVE_KEY, null,
|
||||
emptyDiffViewer.getPreferredFocusedComponent());
|
||||
|
||||
@@ -48,7 +48,6 @@ import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
|
||||
import com.intellij.openapi.editor.ex.EditorMarkupModel;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.UIBasedFileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
@@ -61,6 +60,7 @@ import com.intellij.pom.Navigatable;
|
||||
import com.intellij.ui.EditorNotificationPanel;
|
||||
import com.intellij.ui.PopupHandler;
|
||||
import com.intellij.ui.border.CustomLineBorder;
|
||||
import com.intellij.util.LineSeparator;
|
||||
import com.intellij.util.containers.CacheOneStepIterator;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.diff.FilesTooBigForDiffException;
|
||||
@@ -120,8 +120,8 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
|
||||
myOwnerWindow = owner;
|
||||
myIsSyncScroll = true;
|
||||
final boolean v = !horizontal;
|
||||
myLeftSide = new DiffSideView("", this, new CustomLineBorder(UIUtil.getBorderColor(), 1, 0, v ? 0 : 1, v ? 0 : 1));
|
||||
myRightSide = new DiffSideView("", this, new CustomLineBorder(UIUtil.getBorderColor(), v ? 0 : 1, v ? 0 : 1, 1, 0));
|
||||
myLeftSide = new DiffSideView(this, new CustomLineBorder(UIUtil.getBorderColor(), 1, 0, v ? 0 : 1, v ? 0 : 1));
|
||||
myRightSide = new DiffSideView(this, new CustomLineBorder(UIUtil.getBorderColor(), v ? 0 : 1, v ? 0 : 1, 1, 0));
|
||||
myLeftSide.becomeMaster();
|
||||
myDiffUpdater = new Rediffers(this);
|
||||
|
||||
@@ -307,11 +307,35 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
|
||||
}
|
||||
|
||||
public void setTitle1(String title) {
|
||||
myLeftSide.setTitle(title);
|
||||
setTitle(title, true);
|
||||
}
|
||||
|
||||
private void setTitle(String title, boolean left) {
|
||||
Editor editor = left ? getEditor1() : getEditor2();
|
||||
if (editor == null) return;
|
||||
title = addReadOnly(title, editor);
|
||||
JLabel label = new JLabel(title);
|
||||
if (left) {
|
||||
myLeftSide.setTitle(label);
|
||||
}
|
||||
else {
|
||||
myRightSide.setTitle(label);
|
||||
}
|
||||
}
|
||||
|
||||
private static String addReadOnly(@NotNull String title, @Nullable Editor editor) {
|
||||
if (editor == null) {
|
||||
return title;
|
||||
}
|
||||
boolean readonly = editor.isViewer() || !editor.getDocument().isWritable();
|
||||
if (readonly) {
|
||||
title += " " + DiffBundle.message("diff.content.read.only.content.title.suffix");
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle2(String title) {
|
||||
myRightSide.setTitle(title);
|
||||
setTitle(title, false);
|
||||
}
|
||||
|
||||
private void setLineBlocks(LineBlocks blocks) {
|
||||
@@ -490,6 +514,18 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
|
||||
|
||||
public LineBlocks getLineBlocks() { return myLineBlocks; }
|
||||
|
||||
static JComponent createComponentForTitle(@NotNull String title, @NotNull final LineSeparator separator, boolean left) {
|
||||
JPanel bottomPanel = new JPanel(new BorderLayout());
|
||||
JLabel sepLabel = new JLabel(separator.name());
|
||||
sepLabel.setForeground(separator.equals(LineSeparator.CRLF) ? Color.RED : Color.BLUE);
|
||||
bottomPanel.add(sepLabel, left ? BorderLayout.EAST : BorderLayout.WEST);
|
||||
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.add(new JLabel(title));
|
||||
panel.add(bottomPanel, BorderLayout.SOUTH);
|
||||
return panel;
|
||||
}
|
||||
|
||||
public void setDiffRequest(DiffRequest data) {
|
||||
myDiffRequest = data;
|
||||
if (data.getHints().contains(DiffTool.HINT_DO_NOT_IGNORE_WHITESPACES)) {
|
||||
@@ -497,24 +533,13 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
|
||||
}
|
||||
myDataProvider.putData(myDiffRequest.getGenericData());
|
||||
|
||||
IdeFocusManager fm = IdeFocusManager.getInstance(myProject);
|
||||
boolean isEditor1Focused = getEditor1() != null
|
||||
&& fm.getFocusedDescendantFor(getEditor1().getComponent()) != null;
|
||||
DiffContent content1 = data.getContents()[0];
|
||||
DiffContent content2 = data.getContents()[1];
|
||||
|
||||
boolean isEditor2Focused = myData.getContent2() != null
|
||||
&& getEditor2() != null
|
||||
&& fm.getFocusedDescendantFor(getEditor2().getComponent()) != null;
|
||||
setContents(content1, content2);
|
||||
setTitles(data);
|
||||
|
||||
setContents(data.getContents()[0], data.getContents()[1]);
|
||||
setTitle1(data.getContentTitles()[0]);
|
||||
setTitle2(data.getContentTitles()[1]);
|
||||
setWindowTitle(myOwnerWindow, data.getWindowTitle());
|
||||
//if (isBinaryOrUIEditors(data)) {
|
||||
// myPanel.removeStatusBar();
|
||||
// //myPanel.disableToolbar(true);
|
||||
//} else {
|
||||
// myPanel.addStatusBar();
|
||||
//}
|
||||
data.customizeToolbar(myPanel.resetToolbar());
|
||||
myPanel.registerToolbarActions();
|
||||
|
||||
@@ -527,6 +552,14 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
|
||||
|
||||
|
||||
if (myIsRequestFocus) {
|
||||
IdeFocusManager fm = IdeFocusManager.getInstance(myProject);
|
||||
boolean isEditor1Focused = getEditor1() != null
|
||||
&& fm.getFocusedDescendantFor(getEditor1().getComponent()) != null;
|
||||
|
||||
boolean isEditor2Focused = myData.getContent2() != null
|
||||
&& getEditor2() != null
|
||||
&& fm.getFocusedDescendantFor(getEditor2().getComponent()) != null;
|
||||
|
||||
if (isEditor1Focused || isEditor2Focused) {
|
||||
Editor e = isEditor2Focused ? getEditor2() : getEditor1();
|
||||
if (e != null) {
|
||||
@@ -538,12 +571,29 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBinaryOrUIEditors(DiffRequest data) {
|
||||
final DiffContent[] contents = data.getContents();
|
||||
return contents[0].isBinary()
|
||||
|| contents[1].isBinary()
|
||||
|| contents[0].getContentType() instanceof UIBasedFileType
|
||||
|| contents[1].getContentType() instanceof UIBasedFileType;
|
||||
private void setTitles(@NotNull DiffRequest data) {
|
||||
LineSeparator sep1 = data.getContents()[0].getLineSeparator();
|
||||
LineSeparator sep2 = data.getContents()[1].getLineSeparator();
|
||||
|
||||
String title1 = addReadOnly(data.getContentTitles()[0], myLeftSide.getEditor());
|
||||
String title2 = addReadOnly(data.getContentTitles()[1], myRightSide.getEditor());
|
||||
|
||||
if (sep1 != null && sep2 != null && !sep1.equals(sep2)) {
|
||||
setTitle1(createComponentForTitle(title1, sep1, true));
|
||||
setTitle2(createComponentForTitle(title2, sep2, false));
|
||||
}
|
||||
else {
|
||||
setTitle1(title1);
|
||||
setTitle2(title2);
|
||||
}
|
||||
}
|
||||
|
||||
private void setTitle1(JComponent title) {
|
||||
myLeftSide.setTitle(title);
|
||||
}
|
||||
|
||||
private void setTitle2(JComponent title) {
|
||||
myRightSide.setTitle(title);
|
||||
}
|
||||
|
||||
private static void setWindowTitle(Window window, String title) {
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.IJSwingUtilities;
|
||||
import com.intellij.util.ui.ScrollUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -60,19 +61,14 @@ public class DiffSideView {
|
||||
private DiffHighlighterFactory myHighlighterFactory = DUMMY_HIGHLIGHTER_FACTORY;
|
||||
private EditorSource myEditorSource = EditorSource.NULL;
|
||||
private boolean myIsMaster = false;
|
||||
private String myTitle;
|
||||
private JComponent myTitle = new JLabel();
|
||||
|
||||
public DiffSideView(String title, DiffSidesContainer container, @Nullable Border editorBorder) {
|
||||
myTitle = title;
|
||||
public DiffSideView(DiffSidesContainer container, @Nullable Border editorBorder) {
|
||||
myContainer = container;
|
||||
myPanel = new LabeledEditor(editorBorder);
|
||||
insertComponent(MOCK_COMPONENT);
|
||||
}
|
||||
|
||||
public DiffSideView(String title, DiffSidesContainer container) {
|
||||
this(title, container, null);
|
||||
}
|
||||
|
||||
public JComponent getComponent() {
|
||||
return myPanel;
|
||||
}
|
||||
@@ -127,12 +123,9 @@ public class DiffSideView {
|
||||
editor.getColorsScheme().setColor(EditorColors.CARET_ROW_COLOR, null);
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
public void setTitle(@NotNull JComponent title) {
|
||||
myTitle = title;
|
||||
Editor editor = getEditor();
|
||||
if (editor == null) return;
|
||||
boolean readonly = editor.isViewer() || !editor.getDocument().isWritable();
|
||||
myPanel.updateTitle(myTitle, readonly);
|
||||
myPanel.updateTitle(myTitle);
|
||||
}
|
||||
|
||||
private void setMouseListeners(EditorSource source) {
|
||||
|
||||
@@ -15,38 +15,84 @@
|
||||
*/
|
||||
package com.intellij.openapi.diff.impl;
|
||||
|
||||
import com.intellij.openapi.diff.DiffBundle;
|
||||
import com.intellij.openapi.diff.DiffRequest;
|
||||
import com.intellij.openapi.diff.DiffViewer;
|
||||
import com.intellij.openapi.diff.DiffViewerType;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.openapi.diff.*;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.util.LineSeparator;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: Irina.Chernushina
|
||||
* Date: 3/7/12
|
||||
* Time: 7:45 PM
|
||||
* This viewer is shown, when the compared contents are equal or differ only in line separators.
|
||||
*
|
||||
* @author Irina.Chernushina
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class EmptyDiffViewer implements DiffViewer {
|
||||
private DiffRequest myRequest;
|
||||
|
||||
@Override
|
||||
public void setDiffRequest(DiffRequest request) {
|
||||
myRequest = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
final JLabel label = new JLabel(DiffBundle.message("diff.contents.are.identical.message.text"));
|
||||
DiffContent content1 = myRequest.getContents()[0];
|
||||
DiffContent content2 = myRequest.getContents()[1];
|
||||
|
||||
LineSeparator sep1 = content1.getLineSeparator();
|
||||
LineSeparator sep2 = content2.getLineSeparator();
|
||||
|
||||
final JPanel messagePanel = createMessagePanel(sep1, sep2);
|
||||
|
||||
if (LineSeparator.knownAndDifferent(sep1, sep2)) {
|
||||
assert sep1 != null && sep2 != null: "Separators should have been checked for nullity. sep1: " + sep1 + ", sep2: " + sep2;
|
||||
|
||||
JComponent title1 = createTitleComponent(myRequest.getContentTitles()[0], sep1, true);
|
||||
JComponent title2 = createTitleComponent(myRequest.getContentTitles()[1], sep2, false);
|
||||
|
||||
Splitter titlePanel = new Splitter(false, 0.5F, 0.5F, 0.5F);
|
||||
titlePanel.setFirstComponent(title1);
|
||||
titlePanel.setSecondComponent(title2);
|
||||
titlePanel.setDividerWidth(1);
|
||||
|
||||
JPanel rootPanel = new JPanel(new BorderLayout());
|
||||
rootPanel.add(titlePanel, BorderLayout.NORTH);
|
||||
rootPanel.add(messagePanel);
|
||||
return rootPanel;
|
||||
}
|
||||
else {
|
||||
return messagePanel;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JPanel createMessagePanel(@Nullable LineSeparator sep1, @Nullable LineSeparator sep2) {
|
||||
String message;
|
||||
if (LineSeparator.knownAndDifferent(sep1, sep2)) {
|
||||
message = DiffBundle.message("diff.contents.have.differences.only.in.line.separators.message.text");
|
||||
}
|
||||
else {
|
||||
message = DiffBundle.message("diff.contents.are.identical.message.text");
|
||||
}
|
||||
|
||||
final JLabel label = new JLabel(message);
|
||||
label.setForeground(UIUtil.getInactiveTextColor());
|
||||
final JPanel wrapper = new JPanel(new GridBagLayout());
|
||||
wrapper.add(label, new GridBagConstraints(0,0,1,1,0,0,GridBagConstraints.CENTER, GridBagConstraints.NONE,
|
||||
new Insets(1,1,1,1), 0,0));
|
||||
wrapper.add(label, new GridBagConstraints(0,0,1,1,0,0,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(1,1,1,1), 0,0));
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
private static JComponent createTitleComponent(String title, LineSeparator sep1, boolean left) {
|
||||
JComponent panel = DiffPanelImpl.createComponentForTitle(title, sep1, left);
|
||||
panel.setBorder(BorderFactory.createEmptyBorder(UIUtil.DEFAULT_VGAP, UIUtil.DEFAULT_HGAP, UIUtil.DEFAULT_VGAP, UIUtil.DEFAULT_HGAP));
|
||||
return panel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.diff.impl.util;
|
||||
|
||||
import com.intellij.openapi.diff.DiffBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -23,12 +23,12 @@ import javax.swing.border.Border;
|
||||
import java.awt.*;
|
||||
|
||||
public class LabeledEditor extends JPanel {
|
||||
private final JLabel myLabel = new JLabel();
|
||||
|
||||
private final Border myEditorBorder;
|
||||
private JComponent myMainComponent;
|
||||
|
||||
public LabeledEditor(@Nullable Border editorBorder) {
|
||||
super(new BorderLayout());
|
||||
myLabel.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 0));
|
||||
myEditorBorder = editorBorder;
|
||||
}
|
||||
|
||||
@@ -36,31 +36,25 @@ public class LabeledEditor extends JPanel {
|
||||
this(null);
|
||||
}
|
||||
|
||||
|
||||
private static String addReadOnly(String title, boolean readonly) {
|
||||
if (readonly) title += " " + DiffBundle.message("diff.content.read.only.content.title.suffix");
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setComponent(JComponent component, String title) {
|
||||
public void setComponent(@NotNull JComponent component, @NotNull JComponent titleComponent) {
|
||||
myMainComponent = component;
|
||||
removeAll();
|
||||
|
||||
JPanel title = new JPanel(new BorderLayout());
|
||||
title.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 0));
|
||||
title.add(titleComponent);
|
||||
revalidate();
|
||||
|
||||
final JPanel p = new JPanel(new BorderLayout());
|
||||
if (myEditorBorder != null) {
|
||||
p.setBorder(myEditorBorder);
|
||||
}
|
||||
p.add(component, BorderLayout.CENTER);
|
||||
add(p, BorderLayout.CENTER);
|
||||
add(myLabel, BorderLayout.NORTH);
|
||||
setLabelTitle(title);
|
||||
revalidate();
|
||||
add(title, BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
private void setLabelTitle(String title) {
|
||||
myLabel.setText(title);
|
||||
myLabel.setToolTipText(title);
|
||||
}
|
||||
|
||||
public void updateTitle(String title, boolean readonly) {
|
||||
setLabelTitle(addReadOnly(title, readonly));
|
||||
public void updateTitle(JComponent title) {
|
||||
setComponent(myMainComponent, title);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.util;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* <p>Identifies a line separator:
|
||||
* either Unix ({@code \n}), Windows (@{code \r\n}) or (possible not actual anymore) Classic Mac ({@code \r}).</p>
|
||||
*
|
||||
* <p>The intention is to use this class everywhere, where a line separator is needed, instead of just Strings.</p>
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public enum LineSeparator {
|
||||
LF("\n"),
|
||||
CRLF("\r\n"),
|
||||
CR("\r");
|
||||
|
||||
private final String mySeparatorString;
|
||||
|
||||
LineSeparator(String separatorString) {
|
||||
mySeparatorString = separatorString;
|
||||
}
|
||||
|
||||
public static LineSeparator fromString(String string) {
|
||||
for (LineSeparator separator : values()) {
|
||||
if (separator.getSeparatorString().equals(string)) {
|
||||
return separator;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid string for line separator: " + string);
|
||||
}
|
||||
|
||||
public String getSeparatorString() {
|
||||
return mySeparatorString;
|
||||
}
|
||||
|
||||
public static boolean knownAndDifferent(@Nullable LineSeparator separator1, @Nullable LineSeparator separator2) {
|
||||
return separator1 != null && separator2 != null && !separator1.equals(separator2);
|
||||
}
|
||||
}
|
||||
@@ -268,8 +268,9 @@ public class DebuggerUIUtil {
|
||||
editor.setPropertiesPanel(mainPanel);
|
||||
editor.setShowMoreOptionsLink(true);
|
||||
|
||||
final JPanel panel = editor.getMainPanel();
|
||||
final Balloon balloon = JBPopupFactory.getInstance()
|
||||
.createDialogBalloonBuilder(editor.getMainPanel(), null)
|
||||
.createDialogBalloonBuilder(panel, null)
|
||||
.setHideOnClickOutside(true)
|
||||
.setCloseButtonEnabled(false)
|
||||
.setAnimationCycle(0)
|
||||
@@ -295,7 +296,8 @@ public class DebuggerUIUtil {
|
||||
balloon.showInCenterOf(component);
|
||||
}
|
||||
else {
|
||||
balloon.show(new RelativePoint(component, whereToShow), Balloon.Position.below);
|
||||
final Point p = new Point(whereToShow.x + panel.getPreferredSize().width / 2, whereToShow.y);
|
||||
balloon.show(new RelativePoint(component, p), Balloon.Position.below);
|
||||
}
|
||||
|
||||
BreakpointsMasterDetailPopupFactory.getInstance(project).setBalloonToHide(balloon, breakpoint);
|
||||
|
||||
+4
-2
@@ -198,8 +198,10 @@ public class PsiDocumentNavigator extends DefaultNavigator {
|
||||
final XmlTag context = (XmlTag)element;
|
||||
final String namespaceUri = context.getNamespace();
|
||||
if (!MyPsiUtil.isInDeclaredNamespace(context, namespaceUri, context.getNamespacePrefix())) {
|
||||
LOG.info("getElementNamespaceUri: not returning implicit namespace uri: " + namespaceUri);
|
||||
return "";
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("getElementNamespaceUri: not returning implicit namespace uri: " + namespaceUri);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("enter: getElementNamespaceUri: " + namespaceUri);
|
||||
|
||||
Reference in New Issue
Block a user