mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+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();
|
||||
}
|
||||
|
||||
@@ -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<ModuleLevelBuilder>());
|
||||
}
|
||||
|
||||
final OwnServiceLoader<BuilderService> loader = OwnServiceLoader.load(BuilderService.class);
|
||||
|
||||
for (BuilderService service : loader) {
|
||||
for (BuilderService service : JpsServiceManager.getInstance().getExtensions(BuilderService.class)) {
|
||||
myProjectLevelBuilders.addAll(service.createProjectLevelBuilders());
|
||||
final List<? extends ModuleLevelBuilder> moduleLevelBuilders = service.createModuleLevelBuilders();
|
||||
for (ModuleLevelBuilder builder : moduleLevelBuilders) {
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
-19
@@ -3,7 +3,6 @@
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_5" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
@@ -11,29 +10,11 @@
|
||||
<orderEntry type="library" name="Groovy" level="project" />
|
||||
<orderEntry type="library" name="Ant" level="project" />
|
||||
<orderEntry type="module" module-name="antlayout" />
|
||||
<orderEntry type="module-library" exported="" scope="PROVIDED">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/lib/gant-1.9.5_groovy-1.7.10.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="library" name="asm4" level="project" />
|
||||
<orderEntry type="module" module-name="jps-model" exported="" />
|
||||
<orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="module" module-name="javac2" />
|
||||
<orderEntry type="module-library" scope="TEST">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/lib/junit-addons-1.4.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module" module-name="instrumentation-util" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public class JpsServiceManagerImpl extends JpsServiceManager {
|
||||
//noinspection unchecked
|
||||
T service = (T)myServices.get(serviceClass);
|
||||
if (service == null) {
|
||||
final Iterator<T> iterator = ServiceLoader.load(serviceClass).iterator();
|
||||
final Iterator<T> 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 <T> Iterable<T> getExtensions(Class<T> extensionClass) {
|
||||
List<?> cached = myExtensions.get(extensionClass);
|
||||
if (cached == null) {
|
||||
final ServiceLoader<T> loader = ServiceLoader.load(extensionClass);
|
||||
final ServiceLoader<T> loader = ServiceLoader.load(extensionClass, extensionClass.getClassLoader());
|
||||
List<T> extensions = new ArrayList<T>();
|
||||
for (T t : loader) {
|
||||
extensions.add(t);
|
||||
|
||||
@@ -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<String, String> pathVariables) {
|
||||
return loadFromPath(project, path, pathVariables, "")
|
||||
}
|
||||
|
||||
@@ -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<S> implements Iterable<S> {
|
||||
private Class<S> serviceClass;
|
||||
|
||||
private OwnServiceLoader(Class<S> serviceClass) {
|
||||
this.serviceClass = serviceClass;
|
||||
}
|
||||
|
||||
public static <S> OwnServiceLoader<S> load(Class<S> serviceClass) {
|
||||
return new OwnServiceLoader<S>(serviceClass);
|
||||
}
|
||||
|
||||
public Iterator<S> iterator() {
|
||||
return sun.misc.Service.providers(serviceClass);
|
||||
}
|
||||
}
|
||||
@@ -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:{}]
|
||||
}
|
||||
})
|
||||
@@ -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<String> modulesSet,
|
||||
List<String> artifactsList, final boolean includeTests) {
|
||||
final BuildRunner buildRunner = new BuildRunner(loader, modulesSet, buildType, artifactsList, Collections.<String>emptyList(), Collections.<String, String>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<String> modulesSet,
|
||||
List<String> artifactsList, final boolean includeTests, final MessageHandler messageHandler) throws Exception {
|
||||
final BuildRunner buildRunner = new BuildRunner(loader, modulesSet, buildType, artifactsList, Collections.<String>emptyList(), Collections.<String, String>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) {
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
@@ -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<String> modulesSet, boolean includeTests) {
|
||||
if (!myDryRun) {
|
||||
info("Starting build, caches are saved to " + myDataStorageRoot.getAbsolutePath());
|
||||
Standalone.runBuild(myModelLoader, myDataStorageRoot, BuildType.PROJECT_REBUILD, modulesSet, Collections.<String>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.<String>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));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -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<PsiElement> elements,
|
||||
Collection<? super RelatedItemLineMarkerInfo> 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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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();
|
||||
|
||||
@@ -113,6 +113,38 @@ public class UnixProcessManager {
|
||||
final ProcessInfo processInfo = new ProcessInfo();
|
||||
final List<Integer> childrenPids = new ArrayList<Integer>();
|
||||
|
||||
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<Integer> foundPid,
|
||||
final ProcessInfo processInfo, final List<Integer> childrenPids) {
|
||||
final Ref<Boolean> ourPidFound = Ref.create(false);
|
||||
processPSOutput(getPSCmd(false), new Processor<String>() {
|
||||
@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<String> processor) {
|
||||
|
||||
@@ -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,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);
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
+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