diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 07f333106f6b..246565ab3cf0 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -229,9 +229,9 @@ public def layoutCommunityPlugins(String home) { fileset(dir: "$home/plugins/maven/maven2-server-impl/lib") } - layoutPlugin("rearranger") { - jar("rearranger.jar") { - module("rearranger") + layoutPlugin("gradle") { + jar("gradle.jar") { + module("gradle") } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java index 03081f89b239..890b0073449c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreatePropertyFromUsageFix.java @@ -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) { diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddOverrideAnnotationAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddOverrideAnnotationAction.java index 4db64387c0f1..b9bd7cd8b019 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddOverrideAnnotationAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddOverrideAnnotationAction.java @@ -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; diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index aee580a73761..aba0c13d4589 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -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 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 { private final PsiLambdaExpression myExpression; diff --git a/java/java-psi-api/src/com/intellij/psi/PsiResolveHelper.java b/java/java-psi-api/src/com/intellij/psi/PsiResolveHelper.java index 851137c0b88f..5a035acac1f6 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiResolveHelper.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiResolveHelper.java @@ -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() { } diff --git a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java index 1c640679f0af..02085303e9d8 100644 --- a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java +++ b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java @@ -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 CURRENT_CANDIDATE = Key.create("CURRENT_CANDIDATE"); + public static final ThreadLocal> CURRENT_CANDIDATE = new ThreadLocal>(); @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 map; + synchronized (LOCK) { + map = CURRENT_CANDIDATE.get(); + if (map == null) { + map = new ConcurrentWeakHashMap(); + CURRENT_CANDIDATE.set(map); + } + } + map.put(myArgumentList, getElement()); try { myCalcedSubstitutor = inferTypeArguments(DefaultParameterTypeInferencePolicy.INSTANCE); } finally { - myArgumentList.putUserData(CURRENT_CANDIDATE, null); + map.remove(myArgumentList); } } else { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java index c8bb43c3cd68..b409b9bdcb97 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java @@ -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 imple final PsiTypeElement typeElement = getTypeElement(); if (typeElement == null && isLambdaParameter()) { - return LambdaUtil.getLambdaParameterType(this); + return PsiLambdaExpressionImpl.getLambdaParameterType(this); } return JavaSharedImplUtil.getType(typeElement, getNameIdentifier(), this); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ProcessCandidateParameterTypeInferencePolicy.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ProcessCandidateParameterTypeInferencePolicy.java index 7dbc9b848a65..f67dba0e1a13 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ProcessCandidateParameterTypeInferencePolicy.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ProcessCandidateParameterTypeInferencePolicy.java @@ -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 type = PsiResolveHelper.ourGuard.doPreventingRecursion(innerMethodCall, true, new Computable() { @Override public PsiType compute() { return substitutor.substitute(finalParameter.getType()); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java index cb15a9b96d3d..62d12a4a38d9 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java @@ -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 currentSubstitution = getSubstitutionForTypeParameterConstraint(typeParameter, parameterType, - argumentType, true, PsiUtil.getLanguageLevel(typeParameter)); + final Pair 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 getFailedInferenceConstraint(final PsiTypeParameter typeParameter) { return new Pair(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 inferSubstitutionFromLambda(PsiTypeParameter typeParam, PsiLambdaExpressionType arg) { + private static Pair 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 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 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 constraint = null; final List expressions = lambdaExpression.getReturnExpressions(); for (final PsiExpression expression : expressions) { - PsiType exprType = ourGuard.doPreventingRecursion(lambdaExpression, true, new Computable() { + 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() { @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 constraint = + + if (exprType == null){ + return FAILED_INFERENCE; + } + + final Pair 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(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); + } } } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java index 4ce27f7fe214..70bfbcb92c35 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java @@ -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() { - @Override - public PsiType compute() { - return resolveResult.getSubstitutor().substitute(psiType); - } - }); + if (tryToSubstitute) { + final PsiType psiType = type; + type = PsiResolveHelper.ourGuard.doPreventingRecursion(expression, true, new Computable() { + @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); + } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/InferenceFromArgs.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/InferenceFromArgs.java index 480106817cfa..904c5045654b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/InferenceFromArgs.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/InferenceFromArgs.java @@ -22,7 +22,7 @@ class InferenceFromArgs { bar(b, (k, v) -> {Integer i = k; return v;}); bazz((k, v) -> v); - bazz((k, v) -> {int i = k; return v;}); + bazz((k, v) -> {int i = k; return v;}); } public static SameArgsI max() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility.java index eb2acb162cdd..b1d08e6f04ad 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility.java @@ -57,7 +57,7 @@ class ReturnTypeCompatibility { } public static void main(String[] args) { - call(i-> {return i;}); + call(i-> {return i;}); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistency.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistency.java index 03edf0154e8d..b70e4aa13a09 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistency.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistency.java @@ -15,3 +15,63 @@ class TypeArgsConsistency { I i3 = bar((i, j) -> "" + i + j); } } + +class TypeArgsConsistency1 { + + interface I { + int m(int i, T j); + } + + static void foo(I s) { } + + static I bar(I s) { return null; } + + { + I i1 = (i, j) -> i + j; + foo((i, j) -> i + j); + I i2 =bar((i, j) -> i) ; + I i3 = bar((i, j) -> "" + i + j); + } +} + +class TypeArgsConsistency2 { + static I bar(I i) {return null;} + static I1 bar1(I1 i) {return null;} + static I2 bar2(I2 i) {return i;} + + public static void main(String[] args) { + I i1 = bar(x -> x); + I1 i2 = bar1(x -> 1); + I2 aI2 = bar2(x -> ""); + I2 aI28 = bar2( x-> ""); + I2 i3 = bar2(x -> x); + I2 i4 = bar2(x -> foooI()); + System.out.println(i4.foo(2)); + } + + static K fooo(){return null;} + static int foooI(){return 0;} + + interface I { + X foo(X x); + } + interface I1 { + + int foo(X x); + } + + interface I2 { + 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 p); } + static T doIt1(T i, F1 f) { return f._(i);} +} + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistencyMisc1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistencyMisc1.java new file mode 100644 index 000000000000..19d7d09b152c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistencyMisc1.java @@ -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 foo(List list); + } + + static I bar(I i){return i;} + static void bar1(I i){} + static void bar2(T t, I i){} + static void bar3(I i, T t){} + + { + bar(x -> x); + bar1(x -> x); + + I lO = x->x; + bar2("", lO); + + I lS = x->x; + 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 foo(List list); + } + + static I bar(I i){return i;} + static void bar1(I i){} + static void bar2(T t, I i){} + static void bar3(I i, T t){} + + { + bar(x -> x); + bar1(x -> x); + bar2(1, x -> x); + bar2("", x -> x); + bar3(x -> x, ""); + } +} + +class Test3 { + + interface I { + List foo(List list); + } + + static I bar(I i){return i;} + static void bar1(I i){} + static void bar2(T t, I i){} + static void bar3(I i, T t){} + + { + bar(x -> x); + bar1(x -> x); + bar2(1, x -> x); + bar2("", x -> x); + + bar3(x -> x, ""); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistencyWithoutParams.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistencyWithoutParams.java new file mode 100644 index 000000000000..c0f95dcba9f9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistencyWithoutParams.java @@ -0,0 +1,36 @@ +import java.util.*; +class Test4 { + interface I { + List foo(); + } + + static void bar(I i){} + + { + bar(() -> null); + } +} + +class Test5 { + interface I { + void foo(K k); + } + + static void bar(I i){} + + { + bar(() -> null); + } +} +class Test6 { + interface I { + void foo(); + } + + static void bar(I i){} + + { + bar(() -> null); + bar(() -> {}); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java index 47a3cda02b47..03d0d87c7731 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java @@ -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(); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java index 829950b6ce85..5003ad3f27c0 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java @@ -1,7 +1,7 @@ package org.jetbrains.jps.incremental; import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.jps.idea.OwnServiceLoader; +import org.jetbrains.jps.service.JpsServiceManager; import java.util.*; @@ -25,9 +25,7 @@ public class BuilderRegistry { myModuleLevelBuilders.put(category, new ArrayList()); } - final OwnServiceLoader loader = OwnServiceLoader.load(BuilderService.class); - - for (BuilderService service : loader) { + for (BuilderService service : JpsServiceManager.getInstance().getExtensions(BuilderService.class)) { myProjectLevelBuilders.addAll(service.createProjectLevelBuilders()); final List moduleLevelBuilders = service.createModuleLevelBuilders(); for (ModuleLevelBuilder builder : moduleLevelBuilders) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java index c06efc0be481..bc3b2d80a5cf 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java @@ -5,13 +5,13 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ClassMap; import org.jetbrains.jps.JpsPathUtil; -import org.jetbrains.jps.idea.OwnServiceLoader; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactCompilerInstructionCreator; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactInstructionsBuilderContext; import org.jetbrains.jps.model.artifact.JpsArtifact; import org.jetbrains.jps.model.artifact.elements.*; import org.jetbrains.jps.model.java.JpsProductionModuleOutputPackagingElement; import org.jetbrains.jps.model.java.JpsTestModuleOutputPackagingElement; +import org.jetbrains.jps.service.JpsServiceManager; import java.io.File; import java.util.List; @@ -42,7 +42,7 @@ public class LayoutElementBuildersRegistry { for (LayoutElementBuilderService builder : standardBuilders) { myBuilders.put(builder.getElementClass(), builder); } - for (LayoutElementBuilderService builder : OwnServiceLoader.load(LayoutElementBuilderService.class)) { + for (LayoutElementBuilderService builder : JpsServiceManager.getInstance().getExtensions(LayoutElementBuilderService.class)) { myBuilders.put(builder.getElementClass(), builder); } } diff --git a/jps/jps.iml b/jps/jps.iml index 0865ffbd929e..da2dc806611e 100644 --- a/jps/jps.iml +++ b/jps/jps.iml @@ -3,7 +3,6 @@ - @@ -11,29 +10,11 @@ - - - - - - - - - - - - - - - - - - diff --git a/jps/model-api/src/org/jetbrains/jps/service/JpsServiceManager.java b/jps/model-api/src/org/jetbrains/jps/service/JpsServiceManager.java index 2f86a7898341..30a33f197f16 100644 --- a/jps/model-api/src/org/jetbrains/jps/service/JpsServiceManager.java +++ b/jps/model-api/src/org/jetbrains/jps/service/JpsServiceManager.java @@ -18,7 +18,7 @@ public abstract class JpsServiceManager { private static final JpsServiceManager INSTANCE; static { - INSTANCE = ServiceLoader.load(JpsServiceManager.class).iterator().next(); + INSTANCE = ServiceLoader.load(JpsServiceManager.class, JpsServiceManager.class.getClassLoader()).iterator().next(); } } } diff --git a/jps/model-impl/src/org/jetbrains/jps/service/impl/JpsServiceManagerImpl.java b/jps/model-impl/src/org/jetbrains/jps/service/impl/JpsServiceManagerImpl.java index 0b701a4ead7a..b455dc0d68a8 100644 --- a/jps/model-impl/src/org/jetbrains/jps/service/impl/JpsServiceManagerImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/service/impl/JpsServiceManagerImpl.java @@ -17,7 +17,7 @@ public class JpsServiceManagerImpl extends JpsServiceManager { //noinspection unchecked T service = (T)myServices.get(serviceClass); if (service == null) { - final Iterator iterator = ServiceLoader.load(serviceClass).iterator(); + final Iterator iterator = ServiceLoader.load(serviceClass, serviceClass.getClassLoader()).iterator(); if (!iterator.hasNext()) { throw new ServiceConfigurationError("Implementation for " + serviceClass + " not found"); } @@ -37,7 +37,7 @@ public class JpsServiceManagerImpl extends JpsServiceManager { public Iterable getExtensions(Class extensionClass) { List cached = myExtensions.get(extensionClass); if (cached == null) { - final ServiceLoader loader = ServiceLoader.load(extensionClass); + final ServiceLoader loader = ServiceLoader.load(extensionClass, extensionClass.getClassLoader()); List extensions = new ArrayList(); for (T t : loader) { extensions.add(t); diff --git a/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy b/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy index 3aa7f6e3cee6..5712014cf716 100644 --- a/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy +++ b/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy @@ -12,6 +12,20 @@ public class IdeaProjectLoader { private ProjectLoadingErrorReporter errorReporter private final XmlParser xmlParser = new XmlParser(false, false) + public static String guessHome(Script script) { + File home = new File(script["gant.file"].substring("file:".length())) + + while (home != null) { + if (home.isDirectory()) { + if (new File(home, ".idea").exists()) return home.getCanonicalPath() + } + + home = home.getParentFile() + } + + return null + } + public static ProjectMacroExpander loadFromPath(Project project, String path, Map pathVariables) { return loadFromPath(project, path, pathVariables, "") } diff --git a/jps/model/src/org/jetbrains/jps/idea/OwnServiceLoader.java b/jps/model/src/org/jetbrains/jps/idea/OwnServiceLoader.java deleted file mode 100644 index 440e19681721..000000000000 --- a/jps/model/src/org/jetbrains/jps/idea/OwnServiceLoader.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.jetbrains.jps.idea; - -import java.util.Iterator; - -/** - * This class should be used instead of {@link java.util.ServiceLoader} because the standard ServiceLoader - * is not available in JDK 1.5 - * - * @author nik - */ -public class OwnServiceLoader implements Iterable { - private Class serviceClass; - - private OwnServiceLoader(Class serviceClass) { - this.serviceClass = serviceClass; - } - - public static OwnServiceLoader load(Class serviceClass) { - return new OwnServiceLoader(serviceClass); - } - - public Iterator iterator() { - return sun.misc.Service.providers(serviceClass); - } -} diff --git a/jps/standalone-builder/src/jps.gdsl b/jps/standalone-builder/src/jps.gdsl new file mode 100644 index 000000000000..036c282793c7 --- /dev/null +++ b/jps/standalone-builder/src/jps.gdsl @@ -0,0 +1,16 @@ +def ctx = context(scope: scriptScope(), filetypes : ["gant"]) + +contributor ([ctx], { + property name:"project", type:"org.jetbrains.jps.model.JpsProject" + property name:"global", type:"org.jetbrains.jps.model.JpsGlobal" + property name:"projectBuilder", type:"org.jetbrains.jps.gant.JpsGantProjectBuilder" + method name:"jdk", type:"void", params:[name:"String", jdkPath:"String"] + method name:"jdk", type:"void", params:[name:"String", jdkPath:"String", initializer:{}] + + method name:"layout", type:"org.jetbrains.jps.gant.LayoutInfo", params: [name:"String", layout:{}] + method name:"module", type:"void", params: [name:"String"] + method name:"module", type:"void", params: [name:"String", layout:{}] + ["jar", "dir", "zip"].each { methodName -> + method name:methodName, type:"void", params: [name:"String", layout:{}] + } +}) diff --git a/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java b/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java index 6177464d31d7..2c68b43c0a3d 100644 --- a/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java +++ b/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java @@ -104,16 +104,8 @@ public class Standalone { return; } - runBuild(loader, dataStorageRoot, buildType, modulesSet, artifactsList, true); - } - - public static void runBuild(JpsModelLoader loader, final File dataStorageRoot, BuildType buildType, Set modulesSet, - List artifactsList, final boolean includeTests) { - final BuildRunner buildRunner = new BuildRunner(loader, modulesSet, buildType, artifactsList, Collections.emptyList(), Collections.emptyMap()); - final ConsoleMessageHandler messageHandler = new ConsoleMessageHandler(); try { - ProjectDescriptor descriptor = buildRunner.load(messageHandler, dataStorageRoot, new BuildFSState(true)); - buildRunner.runBuild(descriptor, CanceledStatus.NULL, null, messageHandler, includeTests); + runBuild(loader, dataStorageRoot, buildType, modulesSet, artifactsList, true, new ConsoleMessageHandler()); } catch (Throwable t) { System.err.println("Internal error: " + t.getMessage()); @@ -121,6 +113,13 @@ public class Standalone { } } + public static void runBuild(JpsModelLoader loader, final File dataStorageRoot, BuildType buildType, Set modulesSet, + List artifactsList, final boolean includeTests, final MessageHandler messageHandler) throws Exception { + final BuildRunner buildRunner = new BuildRunner(loader, modulesSet, buildType, artifactsList, Collections.emptyList(), Collections.emptyMap()); + ProjectDescriptor descriptor = buildRunner.load(messageHandler, dataStorageRoot, new BuildFSState(true)); + buildRunner.runBuild(descriptor, CanceledStatus.NULL, null, messageHandler, includeTests); + } + private static class ConsoleMessageHandler implements MessageHandler { @Override public void processMessage(BuildMessage msg) { diff --git a/jps/standalone-builder/src/org/jetbrains/jps/gant/DefaultBuildInfoPrinter.java b/jps/standalone-builder/src/org/jetbrains/jps/gant/DefaultBuildInfoPrinter.java new file mode 100644 index 000000000000..a81a135c9172 --- /dev/null +++ b/jps/standalone-builder/src/org/jetbrains/jps/gant/DefaultBuildInfoPrinter.java @@ -0,0 +1,24 @@ +package org.jetbrains.jps.gant; + +/** + * @author nik + */ +public class DefaultBuildInfoPrinter implements BuildInfoPrinter { + @Override + public void printProgressMessage(JpsGantProjectBuilder project, String message) { + project.info(message); + } + + @Override + public void printCompilationErrors(JpsGantProjectBuilder project, String compilerName, String messages) { + project.error(messages); + } + + @Override + public void printCompilationFinish(JpsGantProjectBuilder project, String compilerName) { + } + + @Override + public void printCompilationStart(JpsGantProjectBuilder project, String compilerName) { + } +} diff --git a/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantProjectBuilder.java b/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantProjectBuilder.java index 5032a8ae4a98..a497822a6e92 100644 --- a/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantProjectBuilder.java +++ b/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantProjectBuilder.java @@ -1,11 +1,18 @@ package org.jetbrains.jps.gant; +import com.intellij.openapi.diagnostic.DefaultLogger; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.api.BuildType; import org.jetbrains.jps.build.Standalone; import org.jetbrains.jps.cmdline.JpsModelLoader; +import org.jetbrains.jps.incremental.MessageHandler; +import org.jetbrains.jps.incremental.messages.BuildMessage; +import org.jetbrains.jps.incremental.messages.CompilerMessage; import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.java.JpsJavaClasspathKind; import org.jetbrains.jps.model.java.JpsJavaDependenciesEnumerator; @@ -26,7 +33,7 @@ public class JpsGantProjectBuilder { private File myDataStorageRoot; private JpsModelLoader myModelLoader; private boolean myDryRun; - private BuildInfoPrinter myBuildInfoPrinter; + private BuildInfoPrinter myBuildInfoPrinter = new DefaultBuildInfoPrinter(); public JpsGantProjectBuilder(Project project, JpsModel model, org.jetbrains.jps.Project oldProject) { myProject = project; @@ -66,11 +73,11 @@ public class JpsGantProjectBuilder { myBuildInfoPrinter = printer; } - public void setUseInProcessJavac() { + public void setUseInProcessJavac(boolean value) { //doesn't make sense for new builders } - public void setArrangeModuleCyclesOutputs() { + public void setArrangeModuleCyclesOutputs(boolean value) { //doesn't make sense for new builders } @@ -78,6 +85,10 @@ public class JpsGantProjectBuilder { throw new BuildException(message); } + public void error(Throwable t) { + throw new BuildException(t); + } + public void warning(String message) { myProject.log(message, Project.MSG_WARN); } @@ -87,12 +98,11 @@ public class JpsGantProjectBuilder { } public void stage(String message) { - if (myBuildInfoPrinter != null) { - myBuildInfoPrinter.printProgressMessage(this, message); - } - else { - myProject.log(message, Project.MSG_INFO); - } + myBuildInfoPrinter.printProgressMessage(this, message); + } + + public File getDataStorageRoot() { + return myDataStorageRoot; } public void setDataStorageRoot(File dataStorageRoot) { @@ -151,15 +161,30 @@ public class JpsGantProjectBuilder { private void runBuild(final Set modulesSet, boolean includeTests) { if (!myDryRun) { - info("Starting build, caches are saved to " + myDataStorageRoot.getAbsolutePath()); - Standalone.runBuild(myModelLoader, myDataStorageRoot, BuildType.PROJECT_REBUILD, modulesSet, Collections.emptyList(), - includeTests); + final AntMessageHandler messageHandler = new AntMessageHandler(); + Logger.setFactory(new AntLoggerFactory(messageHandler)); + info("Starting build: modules = " + modulesSet + ", caches are saved to " + myDataStorageRoot.getAbsolutePath()); + try { + Standalone.runBuild(myModelLoader, myDataStorageRoot, BuildType.PROJECT_REBUILD, modulesSet, Collections.emptyList(), + includeTests, messageHandler); + } + catch (Throwable e) { + error(e); + } } else { info("Building skipped as we're running dry"); } } + public String moduleOutput(JpsModule module) { + return getModuleOutput(module, false); + } + + public String moduleTestsOutput(JpsModule module) { + return getModuleOutput(module, true); + } + public String getModuleOutput(JpsModule module, boolean forTests) { File directory = JpsJavaExtensionService.getInstance().getOutputDirectory(module, forTests); return directory != null ? directory.getAbsolutePath() : null; @@ -174,4 +199,59 @@ public class JpsGantProjectBuilder { } return result; } + + private class AntMessageHandler implements MessageHandler { + @Override + public void processMessage(BuildMessage msg) { + BuildMessage.Kind kind = msg.getKind(); + String text = msg.getMessageText(); + switch (kind) { + case ERROR: + String compilerName = msg instanceof CompilerMessage ? ((CompilerMessage)msg).getCompilerName() : ""; + myBuildInfoPrinter.printCompilationErrors(JpsGantProjectBuilder.this, compilerName, text); + break; + case WARNING: + warning(text); + break; + case INFO: + if (!text.isEmpty()) { + info(text); + } + break; + case PROGRESS: + myBuildInfoPrinter.printProgressMessage(JpsGantProjectBuilder.this, text); + break; + } + } + } + + private class AntLoggerFactory implements Logger.Factory { + private static final String COMPILER_NAME = "build runner"; + + private final AntMessageHandler myMessageHandler; + + public AntLoggerFactory(AntMessageHandler messageHandler) { + myMessageHandler = messageHandler; + } + + @Override + public Logger getLoggerInstance(String category) { + return new DefaultLogger(category) { + @Override + public void error(@NonNls String message, @Nullable Throwable t, @NonNls String... details) { + if (t != null) { + myMessageHandler.processMessage(new CompilerMessage(COMPILER_NAME, t)); + } + else { + myMessageHandler.processMessage(new CompilerMessage(COMPILER_NAME, BuildMessage.Kind.ERROR, message)); + } + } + + @Override + public void warn(@NonNls String message, @Nullable Throwable t) { + myMessageHandler.processMessage(new CompilerMessage(COMPILER_NAME, BuildMessage.Kind.WARNING, message)); + } + }; + } + } } diff --git a/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantTool.groovy b/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantTool.groovy index d5caed6837ae..420fe178569f 100644 --- a/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantTool.groovy +++ b/jps/standalone-builder/src/org/jetbrains/jps/gant/JpsGantTool.groovy @@ -89,7 +89,10 @@ final class JpsGantTool { IdeaProjectLoader.loadFromPath(oldProject, path, [:]) JpsProjectLoader.loadProject(model.project, [:], path) builder.exportModuleOutputProperties(); - builder.setDataStorageRoot(Utils.getDataStorageRoot(path)) + if (builder.getDataStorageRoot() == null) { + builder.setDataStorageRoot(Utils.getDataStorageRoot(path)) + } + builder.info("Loaded project " + path + ": " + model.getProject().getModules().size() + " modules, " + model.getProject().getLibraryCollection().getLibraries().size() + " libraries") } private void createJavaSdk(JpsGlobal global, String name, String homePath, Closure initializer) { diff --git a/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.java b/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.java deleted file mode 100644 index e62a2e203555..000000000000 --- a/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.jetbrains.jps.idea; - -import groovy.lang.Script; -import org.jetbrains.jps.gant.JpsGantTool; - -/** - * @author nik - */ -public class IdeaProjectLoader { -//todo[nik] inline this method later - public static String guessHome(Script script) { - return JpsGantTool.guessHome(script); - } -} diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerProvider.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerProvider.java index ccda13a1dda5..28af427a227b 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerProvider.java +++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -42,7 +42,9 @@ public abstract class RelatedItemLineMarkerProvider implements LineMarkerProvide public void collectNavigationMarkers(List elements, Collection result, boolean forNavigation) { - for (PsiElement element : elements) { + //noinspection ForLoopReplaceableByForEach + for (int i = 0, size = elements.size(); i < size; i++) { + PsiElement element = elements.get(i); collectNavigationMarkers(element, result); if (forNavigation && element instanceof PsiNameIdentifierOwner) { PsiElement nameIdentifier = ((PsiNameIdentifierOwner)element).getNameIdentifier(); diff --git a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java index 2e5306315a6c..2acb8dde4a7a 100644 --- a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java +++ b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java @@ -129,7 +129,13 @@ public abstract class RemoteProcessSupport { } 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); } diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/EditBookmarkDescriptionAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/EditBookmarkDescriptionAction.java index 6860839c8510..086ad5fc70c6 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/EditBookmarkDescriptionAction.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/EditBookmarkDescriptionAction.java @@ -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) { diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffContent.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffContent.java index ffeabcc88176..79b751488f26 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DiffContent.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffContent.java @@ -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(); } diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DocumentContent.java b/platform/platform-api/src/com/intellij/openapi/diff/DocumentContent.java index 791f9efdb3f2..6d9f6494e535 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DocumentContent.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DocumentContent.java @@ -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)); + } } diff --git a/platform/platform-api/src/com/intellij/openapi/diff/FileContent.java b/platform/platform-api/src/com/intellij/openapi/diff/FileContent.java index 409bd9bda4de..54a17ad0ed78 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/FileContent.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/FileContent.java @@ -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)); + } + } diff --git a/platform/platform-api/src/com/intellij/openapi/diff/SimpleContent.java b/platform/platform-api/src/com/intellij/openapi/diff/SimpleContent.java index a3ee3b42e9fa..cffd4f8b02cc 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/SimpleContent.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/SimpleContent.java @@ -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; } diff --git a/platform/platform-impl/src/com/intellij/codeStyle/IdeaColorSchemesProvider.java b/platform/platform-impl/src/com/intellij/codeStyle/IdeaColorSchemesProvider.java index 88b0c366999c..132fe18eeba5 100644 --- a/platform/platform-impl/src/com/intellij/codeStyle/IdeaColorSchemesProvider.java +++ b/platform/platform-impl/src/com/intellij/codeStyle/IdeaColorSchemesProvider.java @@ -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 diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 2d1ced0ccfc3..17db4a5694a2 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -42,6 +42,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFilePathWrapper; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowManager; @@ -365,7 +366,7 @@ public class Switcher extends AnAction implements DumbAware { filesModel.addElement(editor); } - final VirtualFilesRenderer filesRenderer = new VirtualFilesRenderer(project, pinned) { + final VirtualFilesRenderer filesRenderer = new VirtualFilesRenderer(project) { JPanel myPanel = new JPanel(new BorderLayout()); JLabel myLabel = new JLabel() { @Override @@ -977,20 +978,20 @@ public class Switcher extends AnAction implements DumbAware { private static class VirtualFilesRenderer extends ColoredListCellRenderer { private final Project myProject; - private final boolean myPinned; boolean open; - public VirtualFilesRenderer(Project project, boolean pinned) { + public VirtualFilesRenderer(Project project) { myProject = project; - myPinned = pinned; } protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { if (value instanceof FileInfo) { VirtualFile virtualFile = ((FileInfo)value).getFirst(); - String name = UISettings.getInstance().SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES - ? UniqueVFilePathBuilder.getInstance().getUniqueVirtualFilePath(myProject, virtualFile) - : virtualFile.getName(); + String name = virtualFile instanceof VirtualFilePathWrapper + ? ((VirtualFilePathWrapper)virtualFile).getPresentablePath() + : UISettings.getInstance().SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES + ? UniqueVFilePathBuilder.getInstance().getUniqueVirtualFilePath(myProject, virtualFile) + : virtualFile.getName(); setIcon(IconUtil.getIcon(virtualFile, Iconable.ICON_FLAG_READ_STATUS, myProject)); FileStatus fileStatus = FileStatusManager.getInstance(myProject).getStatus(virtualFile); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/CompositeDiffPanel.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/CompositeDiffPanel.java index 89cfda72bf1e..7b9ba0108066 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/CompositeDiffPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/CompositeDiffPanel.java @@ -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()); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java index 2d5c01ef9473..39ef4bbb306e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java @@ -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) { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSideView.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSideView.java index 68c02c60e4d9..de59385798de 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSideView.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSideView.java @@ -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) { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/EmptyDiffViewer.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/EmptyDiffViewer.java index a3c66731f99c..ab942e674920 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/EmptyDiffViewer.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/EmptyDiffViewer.java @@ -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() { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/LabeledEditor.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/LabeledEditor.java index 4ac7a3f51e4a..10b0939e5929 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/LabeledEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/LabeledEditor.java @@ -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); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java index d40f6bcba74b..43be9583d087 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java @@ -127,7 +127,6 @@ public class FSRecords implements Forceable { w.lock(); if (!ourInitialized) { init(); - scanFreeRecords(); setupFlushing(); ourInitialized = true; } @@ -231,8 +230,9 @@ public class FSRecords implements Forceable { throw new IOException("FS repository wasn't safely shut down"); } markDirty(); + scanFreeRecords(); } - catch (IOException e) { + catch (Exception e) { // IOException, IllegalArgumentException LOG.info("Filesystem storage is corrupted or does not exist. [Re]Building. Reason: " + e.getMessage()); try { closeFiles(); diff --git a/platform/util/src/com/intellij/execution/process/UnixProcessManager.java b/platform/util/src/com/intellij/execution/process/UnixProcessManager.java index 9e2786de68d6..e507cbb9ad89 100644 --- a/platform/util/src/com/intellij/execution/process/UnixProcessManager.java +++ b/platform/util/src/com/intellij/execution/process/UnixProcessManager.java @@ -113,6 +113,38 @@ public class UnixProcessManager { final ProcessInfo processInfo = new ProcessInfo(); final List childrenPids = new ArrayList(); + findChildProcesses(our_pid, process_pid, foundPid, processInfo, childrenPids); + + boolean result; + if (!foundPid.isNull()) { + processInfo.killProcTree(foundPid.get(), signal, UNIX_KILLER); + result = true; + } + else { + for (Integer pid : childrenPids) { + processInfo.killProcTree(pid, signal, UNIX_KILLER); + } + result = !childrenPids.isEmpty(); //we've tried to kill at least one process + } + + if (result) { + foundPid.set(null); + childrenPids.clear(); + + findChildProcesses(our_pid, process_pid, foundPid, processInfo, childrenPids); + + return foundPid.isNull() && childrenPids.isEmpty(); //all processes have been killed + } + else { + return true; //the parent process was already killed + } + } + + private static void findChildProcesses(final int our_pid, + final int process_pid, + final Ref foundPid, + final ProcessInfo processInfo, final List childrenPids) { + final Ref ourPidFound = Ref.create(false); processPSOutput(getPSCmd(false), new Processor() { @Override public boolean process(String s) { @@ -127,32 +159,23 @@ public class UnixProcessManager { childrenPids.add(pid); } - if (pid == process_pid) { + if (pid == our_pid) { + ourPidFound.set(true); + } + else if (pid == process_pid) { if (parent_pid == our_pid) { foundPid.set(pid); } else { - throw new IllegalStateException("process is not our child"); + throw new IllegalStateException("Process (pid=" + process_pid + ") is not our child(our pid = " + our_pid + ")"); } } return false; } }); - - boolean result; - if (!foundPid.isNull()) { - processInfo.killProcTree(foundPid.get(), signal, UNIX_KILLER); - result = true; + if (!ourPidFound.get()) { + throw new IllegalStateException("IDE pid is not found in ps list(" + our_pid + ")"); } - else { - for (Integer pid : childrenPids) { - processInfo.killProcTree(pid, signal, UNIX_KILLER); - } - result = false; - } - - //TODO[traff]: check that processes were really terminated. - return result; } public static void processPSOutput(String[] cmd, Processor processor) { diff --git a/platform/util/src/com/intellij/util/LineSeparator.java b/platform/util/src/com/intellij/util/LineSeparator.java new file mode 100644 index 000000000000..32746332eee8 --- /dev/null +++ b/platform/util/src/com/intellij/util/LineSeparator.java @@ -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; + +/** + *

Identifies a line separator: + * either Unix ({@code \n}), Windows (@{code \r\n}) or (possible not actual anymore) Classic Mac ({@code \r}).

+ * + *

The intention is to use this class everywhere, where a line separator is needed, instead of just Strings.

+ * + * @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); + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java index 74b3c271b699..0d437c11f439 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java @@ -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,16 @@ public class DebuggerUIUtil { balloon.showInCenterOf(component); } else { - balloon.show(new RelativePoint(component, whereToShow), Balloon.Position.below); + //todo[kb] modify and move to BalloonImpl? + final Window window = SwingUtilities.windowForComponent(component); + final RelativePoint p = new RelativePoint(component, whereToShow); + if (window != null) { + final RelativePoint point = new RelativePoint(window, new Point(0, 0)); + if (p.getScreenPoint().getX() - point.getScreenPoint().getX() < 40) { // triangle + offsets is ~40px + p.getPoint().x += 40; + } + } + balloon.show(p, Balloon.Position.below); } BreakpointsMasterDetailPopupFactory.getInstance(project).setBalloonToHide(balloon, breakpoint); diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java index 7772f2e9426d..6aae8f716a95 100644 --- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java @@ -322,6 +322,14 @@ public class XDebuggerTestUtil { return breakpoint.get(); } + public static void removeAllBreakpoints(@NotNull final Project project) { + final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager(); + XBreakpoint[] breakpoints = breakpointManager.getAllBreakpoints(); + for (XBreakpoint b: breakpoints) { + breakpointManager.removeBreakpoint(b); + } + } + public static void setBreakpointCondition(Project project, int line, final String condition) { XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager(); for (XBreakpoint breakpoint : breakpointManager.getAllBreakpoints()) { diff --git a/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/support/jaxen/PsiDocumentNavigator.java b/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/support/jaxen/PsiDocumentNavigator.java index 5039707ad419..43c058041519 100644 --- a/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/support/jaxen/PsiDocumentNavigator.java +++ b/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/support/jaxen/PsiDocumentNavigator.java @@ -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);