diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/DefaultCodeFragmentFactory.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/DefaultCodeFragmentFactory.java
index bec0848383fb..053f4448e1d2 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/DefaultCodeFragmentFactory.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/DefaultCodeFragmentFactory.java
@@ -79,7 +79,7 @@ public class DefaultCodeFragmentFactory extends CodeFragmentFactory {
return null;
}
- if (parameters.getInvocationCount() <= 1 && JavaCompletionUtil.containsMethodCalls(expression)) {
+ if (parameters.getInvocationCount() <= 1 && JavaCompletionUtil.mayHaveSideEffects(expression)) {
final CompletionService service = CompletionService.getCompletionService();
if (service.getAdvertisementText() == null && parameters.getInvocationCount() < 2) {
service.setAdvertisementText("Invoke completion once more to see runtime type variants");
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
index a97e1316b6ed..2e168b6291ab 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
@@ -677,18 +677,19 @@ public class JavaCompletionUtil {
return ret;
}
- @Nullable
- static PsiElement getQualifier(final PsiElement element) {
- return element instanceof PsiJavaCodeReferenceElement ? ((PsiJavaCodeReferenceElement)element).getQualifier() : null;
- }
-
- public static boolean containsMethodCalls(@Nullable final PsiElement qualifier) {
- if (qualifier == null) return false;
- if (qualifier instanceof PsiMethodCallExpression || qualifier instanceof PsiNewExpression) return true;
- if (qualifier instanceof PsiArrayAccessExpression) {
- return containsMethodCalls(((PsiArrayAccessExpression)qualifier).getArrayExpression());
+ public static boolean mayHaveSideEffects(@Nullable final PsiElement element) {
+ if (element == null) return false;
+ if (element instanceof PsiMethodCallExpression || element instanceof PsiNewExpression) return true;
+ if (element instanceof PsiTypeCastExpression) {
+ return mayHaveSideEffects(((PsiTypeCastExpression)element).getOperand());
}
- return containsMethodCalls(getQualifier(qualifier));
+ if (element instanceof PsiArrayAccessExpression) {
+ return mayHaveSideEffects(((PsiArrayAccessExpression)element).getArrayExpression());
+ }
+ if (element instanceof PsiJavaCodeReferenceElement) {
+ return mayHaveSideEffects(((PsiJavaCodeReferenceElement)element).getQualifier());
+ }
+ return true;
}
public static void insertClassReference(@NotNull PsiClass psiClass, @NotNull PsiFile file, int offset) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java
index 454fcf02d7b1..b164555b8576 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java
@@ -274,7 +274,9 @@ public class ReferenceExpressionCompletionContributor {
}
if (itemType == null) return;
- final PsiElement qualifier = JavaCompletionUtil.getQualifier(reference.getElement());
+ final PsiElement element1 = reference.getElement();
+ final PsiElement qualifier =
+ element1 instanceof PsiJavaCodeReferenceElement ? ((PsiJavaCodeReferenceElement)element1).getQualifier() : null;
final PsiType expectedType = parameters.getExpectedType();
if (!OBJECT_METHOD_PATTERN.accepts(object) || allowGetClass(object, parameters)) {
if (parameters.getParameters().getInvocationCount() >= 3 || !itemType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
@@ -398,7 +400,7 @@ public class ReferenceExpressionCompletionContributor {
}
final String bracketSpace = getSpace(CodeStyleSettingsManager.getSettings(element.getProject()).SPACE_WITHIN_BRACKETS);
- if (object instanceof PsiVariable && !JavaCompletionUtil.containsMethodCalls(qualifier)) {
+ if (object instanceof PsiVariable && !JavaCompletionUtil.mayHaveSideEffects(qualifier)) {
final PsiVariable variable = (PsiVariable)object;
addToArrayConversion(element, prefix,
"new " + componentType.getCanonicalText() +
diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
index f51ac1972979..51e886a9d872 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
@@ -1075,38 +1075,33 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
startElement(expression);
DfaValue dfaValue = myFactory.create(expression);
- if (dfaValue != null) {
- addInstruction(new PushInstruction(dfaValue, expression));
- }
- else {
- PsiExpression condition = expression.getCondition();
+ PsiExpression condition = expression.getCondition();
- PsiExpression thenExpression = expression.getThenExpression();
- PsiExpression elseExpression = expression.getElseExpression();
+ PsiExpression thenExpression = expression.getThenExpression();
+ PsiExpression elseExpression = expression.getElseExpression();
- final int elseOffset = elseExpression == null ? getEndOffset(expression) - 1 : getStartOffset(elseExpression);
- if (thenExpression != null) {
- condition.accept(this);
- generateBoxingUnboxingInstructionFor(condition, PsiType.BOOLEAN);
- PsiType type = expression.getType();
- addInstruction(new ConditionalGotoInstruction(elseOffset, true, condition));
- thenExpression.accept(this);
- generateBoxingUnboxingInstructionFor(thenExpression,type);
+ final int elseOffset = elseExpression == null ? getEndOffset(expression) - 1 : getStartOffset(elseExpression);
+ if (thenExpression != null) {
+ condition.accept(this);
+ generateBoxingUnboxingInstructionFor(condition, PsiType.BOOLEAN);
+ PsiType type = expression.getType();
+ addInstruction(new ConditionalGotoInstruction(elseOffset, true, condition));
+ thenExpression.accept(this);
+ generateBoxingUnboxingInstructionFor(thenExpression,type);
- addInstruction(new GotoInstruction(getEndOffset(expression)));
+ addInstruction(new GotoInstruction(getEndOffset(expression)));
- if (elseExpression != null) {
- elseExpression.accept(this);
- generateBoxingUnboxingInstructionFor(elseExpression,type);
- }
- else {
- pushUnknown();
- }
+ if (elseExpression != null) {
+ elseExpression.accept(this);
+ generateBoxingUnboxingInstructionFor(elseExpression,type);
}
else {
pushUnknown();
}
}
+ else {
+ pushUnknown();
+ }
finishElement(expression);
}
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java
index 8da301fb80c6..c1ab84ce0bb0 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java
@@ -125,13 +125,13 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
if (node == null) {
return true;
}
+
final IElementType type = node.getElementType();
- if (type == JavaDocTokenType.DOC_TAG_VALUE_TOKEN) {
+ if (type == JavaDocElementType.DOC_TAG_VALUE_ELEMENT) {
return PsiTreeUtil.getParentOfType(parent, PsiDocMethodOrFieldRef.class) != null;
}
- return type == JavaDocElementType.DOC_COMMENT || type == JavaDocElementType.DOC_TAG
- || type == JavaDocElementType.DOC_INLINE_TAG;
+ return type == JavaDocElementType.DOC_COMMENT || type == JavaDocElementType.DOC_TAG || type == JavaDocElementType.DOC_INLINE_TAG;
}
private void init(final ASTNode child) {
@@ -1096,9 +1096,8 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
else if (myRole1 == ChildRole.OPERATION_SIGN) {
createSpaceInCode(mySettings.SPACE_AROUND_UNARY_OPERATOR);
}
- else if (myChild1.getElementType() == JavaDocTokenType.DOC_TAG_VALUE_TOKEN
- && myChild2.getElementType() == JavaDocTokenType.DOC_TAG_VALUE_TOKEN)
- {
+ else if ((myType1 == JavaDocTokenType.DOC_TAG_VALUE_TOKEN || myType1 == JavaDocElementType.DOC_TAG_VALUE_ELEMENT) &&
+ (myType2 == JavaDocTokenType.DOC_TAG_VALUE_TOKEN || myType2 == JavaDocElementType.DOC_TAG_VALUE_ELEMENT)) {
createSpaceInCode(true);
}
else if (myRole1 == ChildRole.COMMA) {
@@ -1516,7 +1515,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
}
@Override public void visitDocTag(PsiDocTag tag) {
- if (myChild1.getElementType() == JavaDocTokenType.DOC_TAG_NAME && myChild2.getElementType() == JavaDocTokenType.DOC_TAG_VALUE_TOKEN) {
+ if (myType1 == JavaDocTokenType.DOC_TAG_NAME && myType2 == JavaDocElementType.DOC_TAG_VALUE_ELEMENT) {
myResult = Spacing.createSpacing(1, 1, 0, false, 0);
}
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaASTFactory.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaASTFactory.java
index 9549f72b7ed1..20f7ab1e2f44 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaASTFactory.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaASTFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 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.
@@ -22,10 +22,9 @@ import com.intellij.psi.tree.IElementType;
* @author max
*/
public class JavaASTFactory extends CoreJavaASTFactory {
-
@Override
public CompositeElement createComposite(final IElementType type) {
- if (type == DOC_TAG_VALUE_TOKEN) {
+ if (type == DOC_TAG_VALUE_ELEMENT) {
return new PsiDocTagValueImpl();
}
diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavadocParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavadocParser.java
index b72e4a88d0d5..78abd7fd19e5 100644
--- a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavadocParser.java
+++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavadocParser.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.
@@ -147,7 +147,7 @@ public class JavadocParser {
final PsiBuilder.Marker tagValue = builder.mark();
builder.remapCurrentToken(JavaDocElementType.DOC_REFERENCE_HOLDER);
builder.advanceLexer();
- tagValue.done(JavaDocTokenType.DOC_TAG_VALUE_TOKEN);
+ tagValue.done(JavaDocElementType.DOC_TAG_VALUE_ELEMENT);
}
else if (!isInline && tagName != null && tagName.equals(PARAM_TAG)) {
parseSimpleTagValue(builder, true);
@@ -187,7 +187,7 @@ public class JavadocParser {
else {
final PsiBuilder.Marker tagValue = builder.mark();
builder.advanceLexer();
- tagValue.done(JavaDocTokenType.DOC_TAG_VALUE_TOKEN);
+ tagValue.done(JavaDocElementType.DOC_TAG_VALUE_ELEMENT);
}
}
@@ -217,7 +217,7 @@ public class JavadocParser {
}
}
else if (tokenType == JavaDocTokenType.DOC_TAG_VALUE_RPAREN) {
- subValue.done(JavaDocTokenType.DOC_TAG_VALUE_TOKEN);
+ subValue.done(JavaDocElementType.DOC_TAG_VALUE_ELEMENT);
builder.advanceLexer();
refStart.done(JavaDocElementType.DOC_METHOD_OR_FIELD_REF);
return;
@@ -227,7 +227,7 @@ public class JavadocParser {
}
}
- subValue.done(JavaDocTokenType.DOC_TAG_VALUE_TOKEN);
+ subValue.done(JavaDocElementType.DOC_TAG_VALUE_ELEMENT);
}
refStart.done(JavaDocElementType.DOC_METHOD_OR_FIELD_REF);
@@ -238,7 +238,7 @@ public class JavadocParser {
while (TAG_VALUES_SET.contains(getTokenType(builder))) {
builder.advanceLexer();
}
- tagValue.done(parameter ? JavaDocElementType.DOC_PARAMETER_REF : JavaDocTokenType.DOC_TAG_VALUE_TOKEN);
+ tagValue.done(parameter ? JavaDocElementType.DOC_PARAMETER_REF : JavaDocElementType.DOC_TAG_VALUE_ELEMENT);
}
@Nullable
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java
index c4e790fa9485..f69fdf7127ea 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 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.
@@ -99,7 +99,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
i == JavaElementType.THIS_EXPRESSION ||
i == JavaElementType.SUPER_EXPRESSION ||
i == JavaDocElementType.DOC_METHOD_OR_FIELD_REF ||
- i == JavaDocTokenType.DOC_TAG_VALUE_TOKEN ||
+ i == JavaDocElementType.DOC_TAG_VALUE_ELEMENT ||
i == JavaElementType.REFERENCE_PARAMETER_LIST ||
i == JavaElementType.ANNOTATION) {
if (isQualified()) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/CorePsiDocTagValueImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/CorePsiDocTagValueImpl.java
index bf790cb612cc..d79afae2c1cc 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/CorePsiDocTagValueImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/CorePsiDocTagValueImpl.java
@@ -21,6 +21,7 @@ import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
+import com.intellij.psi.impl.source.tree.JavaDocElementType;
import com.intellij.psi.javadoc.PsiDocTagValue;
import org.jetbrains.annotations.NotNull;
@@ -29,7 +30,7 @@ import org.jetbrains.annotations.NotNull;
*/
public class CorePsiDocTagValueImpl extends CompositePsiElement implements PsiDocTagValue {
public CorePsiDocTagValueImpl() {
- super(JavaDocTokenType.DOC_TAG_VALUE_TOKEN);
+ super(JavaDocElementType.DOC_TAG_VALUE_ELEMENT);
}
@Override
@@ -47,6 +48,7 @@ public class CorePsiDocTagValueImpl extends CompositePsiElement implements PsiDo
if (child.getElementType() == JavaDocTokenType.DOC_TAG_VALUE_COMMA) {
return ChildRole.COMMA;
}
+
return super.getChildRole(child);
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocParamRef.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocParamRef.java
index 4fb485baf727..36f7c61047f5 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocParamRef.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocParamRef.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 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.
@@ -18,11 +18,7 @@ package com.intellij.psi.impl.source.javadoc;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
-import com.intellij.psi.impl.source.Constants;
-import com.intellij.psi.impl.source.tree.CompositePsiElement;
-import com.intellij.psi.impl.source.tree.Factory;
-import com.intellij.psi.impl.source.tree.LeafElement;
-import com.intellij.psi.impl.source.tree.SharedImplUtil;
+import com.intellij.psi.impl.source.tree.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTag;
@@ -43,9 +39,8 @@ import java.util.Set;
* @author mike
*/
public class PsiDocParamRef extends CompositePsiElement implements PsiDocTagValue {
-
public PsiDocParamRef() {
- super(Constants.DOC_PARAMETER_REF);
+ super(JavaDocElementType.DOC_PARAMETER_REF);
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocTagImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocTagImpl.java
index ae89a54207ee..9f2b59ec5538 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocTagImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocTagImpl.java
@@ -16,13 +16,9 @@
package com.intellij.psi.impl.source.javadoc;
import com.intellij.lang.ASTNode;
-import com.intellij.psi.JavaElementVisitor;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiElementVisitor;
-import com.intellij.psi.PsiReference;
+import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.Constants;
-import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
@@ -37,9 +33,10 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
public class PsiDocTagImpl extends CompositePsiElement implements PsiDocTag, Constants {
- private static final TokenSet VALUE_BIT_SET = TokenSet.create(
- JAVA_CODE_REFERENCE, DOC_TAG_VALUE_TOKEN, DOC_METHOD_OR_FIELD_REF, DOC_PARAMETER_REF,
- DOC_COMMENT_DATA, DOC_INLINE_TAG, DOC_REFERENCE_HOLDER);
+ private static final TokenSet TAG_VALUE_BIT_SET = TokenSet.create(
+ DOC_TAG_VALUE_ELEMENT, DOC_METHOD_OR_FIELD_REF, DOC_PARAMETER_REF);
+ private static final TokenSet VALUE_BIT_SET = TokenSet.orSet(TAG_VALUE_BIT_SET, TokenSet.create(
+ DOC_TAG_VALUE_TOKEN, JAVA_CODE_REFERENCE, DOC_COMMENT_DATA, DOC_INLINE_TAG, DOC_REFERENCE_HOLDER));
public PsiDocTagImpl() {
super(DOC_TAG);
@@ -47,17 +44,17 @@ public class PsiDocTagImpl extends CompositePsiElement implements PsiDocTag, Con
@Override
public PsiDocComment getContainingComment() {
- return (PsiDocComment)SourceTreeToPsiMap.treeElementToPsi(getTreeParent());
+ return (PsiDocComment)getParent();
}
@Override
public PsiElement getNameElement() {
- return findChildByRoleAsPsiElement(ChildRole.DOC_TAG_NAME);
+ return findPsiChildByType(DOC_TAG_NAME);
}
@Override
public PsiDocTagValue getValueElement() {
- return (PsiDocTagValue)findChildByRoleAsPsiElement(ChildRole.DOC_TAG_VALUE);
+ return (PsiDocTagValue)findPsiChildByType(TAG_VALUE_BIT_SET);
}
@Override
@@ -65,6 +62,7 @@ public class PsiDocTagImpl extends CompositePsiElement implements PsiDocTag, Con
return getChildrenAsPsiElements(VALUE_BIT_SET, PsiElement.ARRAY_FACTORY);
}
+ @NotNull
@Override
public String getName() {
if (getNameElement() == null) return "";
@@ -79,7 +77,7 @@ public class PsiDocTagImpl extends CompositePsiElement implements PsiDocTag, Con
@Override
public int getChildRole(ASTNode child) {
- assert (child.getTreeParent() == this);
+ assert child.getTreeParent() == this : child.getTreeParent();
IElementType i = child.getElementType();
if (i == DOC_TAG_NAME) {
return ChildRole.DOC_TAG_NAME;
@@ -90,10 +88,7 @@ public class PsiDocTagImpl extends CompositePsiElement implements PsiDocTag, Con
else if (i == DOC_COMMENT_LEADING_ASTERISKS) {
return ChildRole.DOC_COMMENT_ASTERISKS;
}
- else if (i == DOC_TAG_VALUE_TOKEN) {
- return ChildRole.DOC_TAG_VALUE;
- }
- else if (i == DOC_METHOD_OR_FIELD_REF || i == DOC_PARAMETER_REF) {
+ else if (TAG_VALUE_BIT_SET.contains(i)) {
return ChildRole.DOC_TAG_VALUE;
}
else {
@@ -104,7 +99,7 @@ public class PsiDocTagImpl extends CompositePsiElement implements PsiDocTag, Con
@Override
@NotNull
public PsiReference[] getReferences() {
- return ReferenceProvidersRegistry.getReferencesFromProviders(this, PsiDocTag.class);
+ return ReferenceProvidersRegistry.getReferencesFromProviders(this, PsiReferenceService.Hints.NO_HINTS);
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiInlineDocTagImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiInlineDocTagImpl.java
similarity index 81%
rename from java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiInlineDocTagImpl.java
rename to java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiInlineDocTagImpl.java
index 5e6e534a1f78..38466a5f6cb1 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiInlineDocTagImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiInlineDocTagImpl.java
@@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.psi.impl.source.tree.java;
+package com.intellij.psi.impl.source.javadoc;
import com.intellij.lang.ASTNode;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
@@ -36,11 +35,10 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
public class PsiInlineDocTagImpl extends CompositePsiElement implements PsiInlineDocTag, Constants {
- private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiInlineDocTagImpl");
-
- private static final TokenSet VALUE_BIT_SET = TokenSet.create(
- JAVA_CODE_REFERENCE, DOC_TAG_VALUE_TOKEN, DOC_METHOD_OR_FIELD_REF, DOC_COMMENT_DATA, DOC_INLINE_TAG,
- DOC_REFERENCE_HOLDER, WHITE_SPACE, DOC_COMMENT_BAD_CHARACTER);
+ private static final TokenSet TAG_VALUE_BIT_SET = TokenSet.create(
+ DOC_TAG_VALUE_ELEMENT, DOC_METHOD_OR_FIELD_REF);
+ private static final TokenSet VALUE_BIT_SET = TokenSet.orSet(TAG_VALUE_BIT_SET, TokenSet.create(
+ JAVA_CODE_REFERENCE, DOC_TAG_VALUE_TOKEN, DOC_COMMENT_DATA, DOC_INLINE_TAG, DOC_REFERENCE_HOLDER, WHITE_SPACE, DOC_COMMENT_BAD_CHARACTER));
public PsiInlineDocTagImpl() {
super(DOC_INLINE_TAG);
@@ -57,7 +55,7 @@ public class PsiInlineDocTagImpl extends CompositePsiElement implements PsiInlin
@Override
public PsiElement getNameElement() {
- return findChildByRoleAsPsiElement(ChildRole.DOC_TAG_NAME);
+ return findPsiChildByType(DOC_TAG_NAME);
}
@Override
@@ -67,7 +65,7 @@ public class PsiInlineDocTagImpl extends CompositePsiElement implements PsiInlin
@Override
public PsiDocTagValue getValueElement() {
- return (PsiDocTagValue)findChildByRoleAsPsiElement(ChildRole.DOC_TAG_VALUE);
+ return (PsiDocTagValue)findPsiChildByType(TAG_VALUE_BIT_SET);
}
@Override
@@ -79,7 +77,7 @@ public class PsiInlineDocTagImpl extends CompositePsiElement implements PsiInlin
@Override
public int getChildRole(ASTNode child) {
- LOG.assertTrue(child.getTreeParent() == this);
+ assert child.getTreeParent() == this : child.getTreeParent();
IElementType i = child.getElementType();
if (i == DOC_TAG_NAME) {
return ChildRole.DOC_TAG_NAME;
@@ -93,10 +91,7 @@ public class PsiInlineDocTagImpl extends CompositePsiElement implements PsiInlin
else if (i == DOC_INLINE_TAG_END) {
return ChildRole.DOC_INLINE_TAG_END;
}
- else if (i == DOC_TAG_VALUE_TOKEN) {
- return ChildRole.DOC_TAG_VALUE;
- }
- else if (i == DOC_METHOD_OR_FIELD_REF) {
+ else if (TAG_VALUE_BIT_SET.contains(i)) {
return ChildRole.DOC_TAG_VALUE;
}
else {
@@ -124,4 +119,4 @@ public class PsiInlineDocTagImpl extends CompositePsiElement implements PsiInlin
PsiImplUtil.setName(getNameElement(), name);
return this;
}
-}
\ No newline at end of file
+}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/CoreJavaASTFactory.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/CoreJavaASTFactory.java
index c9b6e5552676..dc7b6e576871 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/CoreJavaASTFactory.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/CoreJavaASTFactory.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.
@@ -49,6 +49,7 @@ public class CoreJavaASTFactory extends ASTFactory implements Constants {
return new PsiJavaTokenImpl(type, text);
}
else if (type instanceof IJavaDocElementType) {
+ assert type != DOC_TAG_VALUE_ELEMENT;
return new PsiDocTokenImpl(type, text);
}
@@ -57,7 +58,7 @@ public class CoreJavaASTFactory extends ASTFactory implements Constants {
@Override
public CompositeElement createComposite(IElementType type) {
- if (type == DOC_TAG_VALUE_TOKEN) {
+ if (type == DOC_TAG_VALUE_ELEMENT) {
return new CorePsiDocTagValueImpl();
}
return null;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaDocElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaDocElementType.java
index 4c4776cb1653..71df6027483e 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaDocElementType.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaDocElementType.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.
@@ -29,7 +29,7 @@ import com.intellij.psi.impl.source.javadoc.PsiDocCommentImpl;
import com.intellij.psi.impl.source.javadoc.PsiDocMethodOrFieldRef;
import com.intellij.psi.impl.source.javadoc.PsiDocParamRef;
import com.intellij.psi.impl.source.javadoc.PsiDocTagImpl;
-import com.intellij.psi.impl.source.tree.java.PsiInlineDocTagImpl;
+import com.intellij.psi.impl.source.javadoc.PsiInlineDocTagImpl;
import com.intellij.psi.tree.*;
import com.intellij.psi.tree.java.IJavaDocElementType;
import com.intellij.util.ReflectionUtil;
@@ -70,6 +70,7 @@ public interface JavaDocElementType {
IElementType DOC_INLINE_TAG = new JavaDocCompositeElementType("DOC_INLINE_TAG", PsiInlineDocTagImpl.class);
IElementType DOC_METHOD_OR_FIELD_REF = new JavaDocCompositeElementType("DOC_METHOD_OR_FIELD_REF", PsiDocMethodOrFieldRef.class);
IElementType DOC_PARAMETER_REF = new JavaDocCompositeElementType("DOC_PARAMETER_REF", PsiDocParamRef.class);
+ IElementType DOC_TAG_VALUE_ELEMENT = new IJavaDocElementType("DOC_TAG_VALUE_ELEMENT");
ILazyParseableElementType DOC_REFERENCE_HOLDER = new JavaDocLazyElementType("DOC_REFERENCE_HOLDER") {
private final JavaParserUtil.ParserWrapper myParser = new JavaParserUtil.ParserWrapper() {
@@ -135,6 +136,6 @@ public interface JavaDocElementType {
};
TokenSet ALL_JAVADOC_ELEMENTS = TokenSet.create(
- DOC_TAG, DOC_INLINE_TAG, DOC_METHOD_OR_FIELD_REF, DOC_PARAMETER_REF, DOC_REFERENCE_HOLDER, DOC_TYPE_HOLDER, DOC_COMMENT
- );
+ DOC_TAG, DOC_INLINE_TAG, DOC_METHOD_OR_FIELD_REF, DOC_PARAMETER_REF, DOC_TAG_VALUE_ELEMENT,
+ DOC_REFERENCE_HOLDER, DOC_TYPE_HOLDER, DOC_COMMENT);
}
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/StringTernaryAlwaysTrue.java b/java/java-tests/testData/inspection/dataFlow/fixture/StringTernaryAlwaysTrue.java
new file mode 100644
index 000000000000..93255d9a79b8
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/StringTernaryAlwaysTrue.java
@@ -0,0 +1,12 @@
+class Foo {
+ public void foo() {
+ final boolean flag = true;
+
+ bar(flag ? "a" : "b",
+ flag ? new String[]{"aa"} : new String[]{"bb"}
+ );
+ }
+
+ void bar(String b, String[] a) {
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/Exception0.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/Exception0.txt
index 9254cba2a145..b3935666fc28 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/Exception0.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/Exception0.txt
@@ -25,7 +25,7 @@ PsiJavaFile:Exception0.java
PsiDocTag:@throws
PsiDocToken:DOC_TAG_NAME('@throws')
PsiWhiteSpace(' ')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiElement(DOC_REFERENCE_HOLDER)
PsiJavaCodeReferenceElement:java.lang.Exception
PsiJavaCodeReferenceElement:java.lang
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/InlineTag1.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/InlineTag1.txt
index 983c2c305f61..1975d6a75cf5 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/InlineTag1.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/InlineTag1.txt
@@ -15,7 +15,7 @@ PsiJavaFile:InlineTag1.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('somefunc')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiElement(DOC_TYPE_HOLDER)
PsiTypeElement:String
PsiJavaCodeReferenceElement:String
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/InlineTag2.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/InlineTag2.txt
index 9bba0d6bc228..9165b8960367 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/InlineTag2.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/InlineTag2.txt
@@ -15,7 +15,7 @@ PsiJavaFile:InlineTag2.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('somefunc')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiElement(DOC_TYPE_HOLDER)
PsiTypeElement:String
PsiJavaCodeReferenceElement:String
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/InlineTag3.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/InlineTag3.txt
index e74ee40b22bd..fb591f4269c2 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/InlineTag3.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/InlineTag3.txt
@@ -15,7 +15,7 @@ PsiJavaFile:InlineTag3.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('somefunc')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiElement(DOC_TYPE_HOLDER)
PsiTypeElement:String
PsiJavaCodeReferenceElement:String
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkPlainTag1.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkPlainTag1.txt
index b1bae863f3b4..d7f6a22bf259 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkPlainTag1.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkPlainTag1.txt
@@ -30,7 +30,7 @@ PsiJavaFile:LinkPlainTag1.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('equals')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiElement(DOC_TYPE_HOLDER)
PsiTypeElement:java.lang.Object
PsiJavaCodeReferenceElement:java.lang.Object
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkPlainTag2.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkPlainTag2.txt
index ba779cc5e45a..79e2ec31d002 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkPlainTag2.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkPlainTag2.txt
@@ -10,7 +10,7 @@ PsiJavaFile:LinkPlainTag2.java
PsiDocTag:@linkplain
PsiDocToken:DOC_TAG_NAME('@linkplain')
PsiWhiteSpace(' ')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiDocToken:DOC_TAG_VALUE_TOKEN('java.lang.String')
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('equals')
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag1.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag1.txt
index 588adbae3d2e..f5fde4f3d333 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag1.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag1.txt
@@ -30,7 +30,7 @@ PsiJavaFile:LinkTag1.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('equals')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiElement(DOC_TYPE_HOLDER)
PsiTypeElement:java.lang.Object
PsiJavaCodeReferenceElement:java.lang.Object
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag2.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag2.txt
index 5bb0d66a89f3..af4cf7d2b185 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag2.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag2.txt
@@ -10,7 +10,7 @@ PsiJavaFile:LinkTag2.java
PsiDocTag:@link
PsiDocToken:DOC_TAG_NAME('@link')
PsiWhiteSpace(' ')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiDocToken:DOC_TAG_VALUE_TOKEN('java.lang.String')
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('equals')
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag3.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag3.txt
index 8a8940b8e0b3..b1ea51c9d1af 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag3.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag3.txt
@@ -17,7 +17,7 @@ PsiJavaFile:LinkTag3.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('foo')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiDocToken:DOC_TAG_VALUE_RPAREN(')')
PsiDocToken:DOC_INLINE_TAG_END('}')
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag4.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag4.txt
index 93a0946316fc..a08d012cd2f2 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag4.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag4.txt
@@ -16,7 +16,7 @@ PsiJavaFile:LinkTag4.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('foo')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiDocToken:DOC_TAG_VALUE_RPAREN(')')
PsiDocToken:DOC_INLINE_TAG_END('}')
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag5.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag5.txt
index 6fe4b9bb0d46..6aeebb155f30 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag5.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag5.txt
@@ -15,7 +15,7 @@ PsiJavaFile:LinkTag5.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('foo')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiDocToken:DOC_TAG_VALUE_RPAREN(')')
PsiDocToken:DOC_INLINE_TAG_END('}')
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag6.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag6.txt
index 24d4ab93bb89..1cc176462b4e 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag6.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/LinkTag6.txt
@@ -15,7 +15,7 @@ PsiJavaFile:LinkTag6.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('foo')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiDocToken:DOC_TAG_VALUE_RPAREN(')')
PsiDocToken:DOC_INLINE_TAG_END('}')
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag10.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag10.txt
index 94bc09223507..95b2f7f607a3 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag10.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag10.txt
@@ -29,7 +29,7 @@ PsiJavaFile:SeeTag10.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('equals')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiElement(DOC_TYPE_HOLDER)
PsiTypeElement:java.lang.Object
PsiJavaCodeReferenceElement:java.lang.Object
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag11.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag11.txt
index fec603ea5b39..f58d76b72fd8 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag11.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag11.txt
@@ -29,7 +29,7 @@ PsiJavaFile:SeeTag11.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('wait')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiDocToken:DOC_TAG_VALUE_RPAREN(')')
PsiWhiteSpace('\n ')
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag12.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag12.txt
index 6ef08071804c..ac4dd62c07d2 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag12.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag12.txt
@@ -14,7 +14,7 @@ PsiJavaFile:SeeTag12.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('wait')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiDocToken:DOC_TAG_VALUE_RPAREN(')')
PsiWhiteSpace('\n ')
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag14.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag14.txt
index 9d930ec9c238..08f90474c3a7 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag14.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag14.txt
@@ -29,7 +29,7 @@ PsiJavaFile:SeeTag14.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('append')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiElement(DOC_TYPE_HOLDER)
PsiTypeElement:char[]
PsiTypeElement:char
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag15.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag15.txt
index a535a82cc44f..fa79b853c1a4 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag15.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag15.txt
@@ -29,7 +29,7 @@ PsiJavaFile:SeeTag15.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('append')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiElement(DOC_TYPE_HOLDER)
PsiTypeElement:java.lang.Object
PsiJavaCodeReferenceElement:java.lang.Object
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag16.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag16.txt
index d7f1d3d5157a..3d1fa26a8169 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag16.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag16.txt
@@ -19,7 +19,7 @@ PsiJavaFile:SeeTag16.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('equals')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiElement(DOC_TYPE_HOLDER)
PsiTypeElement:int
PsiKeyword:int('int')
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag3.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag3.txt
index a2a28c9a945a..f018c5af50c1 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag3.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag3.txt
@@ -19,7 +19,7 @@ PsiJavaFile:SeeTag3.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('equals')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiElement(DOC_TYPE_HOLDER)
PsiTypeElement:Object
PsiJavaCodeReferenceElement:Object
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag5.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag5.txt
index 977e65124359..9903e7c37d6b 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag5.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag5.txt
@@ -29,7 +29,7 @@ PsiJavaFile:SeeTag5.java
PsiDocToken:DOC_TAG_VALUE_SHARP_TOKEN('#')
PsiDocToken:DOC_TAG_VALUE_TOKEN('wait')
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiElement(DOC_TYPE_HOLDER)
PsiTypeElement:long
PsiKeyword:long('long')
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag9.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag9.txt
index 75968a87205e..7b2b10a6a7ce 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag9.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/SeeTag9.txt
@@ -15,16 +15,16 @@ PsiJavaFile:SeeTag9.java
PsiIdentifier:equals('equals')
PsiReferenceParameterList
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiDocToken:DOC_TAG_VALUE_LPAREN('(')
PsiElement(DOC_REFERENCE_HOLDER)
PsiKeyword:long('long')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiDocToken:DOC_TAG_VALUE_COMMA(',')
PsiWhiteSpace(' ')
PsiElement(DOC_REFERENCE_HOLDER)
PsiKeyword:long('long')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiDocToken:DOC_TAG_VALUE_RPAREN(')')
PsiWhiteSpace('\n ')
PsiDocToken:DOC_COMMENT_END('*/')
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/Tag2.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/Tag2.txt
index 45c260fa5f51..83308bc7bd6b 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/Tag2.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/Tag2.txt
@@ -23,7 +23,7 @@ PsiJavaFile:Tag2.java
PsiDocTag:@return
PsiDocToken:DOC_TAG_NAME('@return')
PsiWhiteSpace(' ')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiDocToken:DOC_TAG_VALUE_TOKEN('value')
PsiWhiteSpace(' ')
PsiDocToken:DOC_COMMENT_DATA('value')
diff --git a/java/java-tests/testData/psi/parser-full/javadocParsing/Tag5.txt b/java/java-tests/testData/psi/parser-full/javadocParsing/Tag5.txt
index eb44d58a94e9..c6a9b80b47b6 100644
--- a/java/java-tests/testData/psi/parser-full/javadocParsing/Tag5.txt
+++ b/java/java-tests/testData/psi/parser-full/javadocParsing/Tag5.txt
@@ -10,7 +10,7 @@ PsiJavaFile:Tag5.java
PsiDocTag:@ejb:bean
PsiDocToken:DOC_TAG_NAME('@ejb:bean')
PsiWhiteSpace(' ')
- PsiElement(DOC_TAG_VALUE_TOKEN)
+ PsiElement(DOC_TAG_VALUE_ELEMENT)
PsiDocToken:DOC_TAG_VALUE_TOKEN('this')
PsiWhiteSpace(' ')
PsiDocToken:DOC_COMMENT_DATA('is an EJB ')
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java
index b8c5012f562e..768679bdb501 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java
@@ -62,5 +62,6 @@ public class DataFlowInspectionFixtureTest extends JavaCodeInsightFixtureTestCas
public void testIDEA84489() throws Throwable { doTest(); }
public void testComparingToNotNullShouldNotAffectNullity() throws Throwable { doTest(); }
+ public void testStringTernaryAlwaysTrue() throws Throwable { doTest(); }
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java
index 16fb8dd3c01c..63fcd6b60215 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java
@@ -1,3 +1,18 @@
+/*
+ * 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.psi.formatter.java;
import com.intellij.openapi.application.ApplicationManager;
@@ -529,12 +544,12 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
public void testJavaDocLinksWithParameterNames() throws Exception {
// See IDEADEV-8332
doTextTest("/**\n" +
- "* @return if ( x1 == x1 ) then retrun {@link #cmp(String y1,int y2)}\n" +
+ "* @return if ( x1 == x1 ) then return {@link #cmp(String y1,int y2)}\n" +
"* otherwise return {@link #cmp(int x1,int x2)}\n" +
"*/\n" +
"class X {\n" +
"}\n", "/**\n" +
- " * @return if ( x1 == x1 ) then retrun {@link #cmp(String y1, int y2)}\n" +
+ " * @return if ( x1 == x1 ) then return {@link #cmp(String y1, int y2)}\n" +
" * otherwise return {@link #cmp(int x1, int x2)}\n" +
" */\n" +
"class X {\n" +
diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java
index be62585412c8..f90f00941c1f 100644
--- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java
+++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java
@@ -86,7 +86,7 @@ public class Mappings {
myChangedFiles = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
myDeletedClasses = new HashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
myDeltaIsTransient = base.myDeltaIsTransient;
- myRootDir = new File(FileUtil.toSystemIndependentName(base.myRootDir.getAbsolutePath()) + File.separatorChar + "delta");
+ myRootDir = new File(FileUtil.toSystemIndependentName(base.myRootDir.getAbsolutePath()) + File.separatorChar + "myDelta");
myContext = base.myContext;
myInitName = myContext.get("");
myEmptyName = myContext.get("");
@@ -232,7 +232,6 @@ public class Mappings {
private final List myPostPasses;
-
private void addPostPass(final PostPass p) {
myPostPasses.add(p);
}
@@ -672,7 +671,7 @@ public class Mappings {
final File theFile = new File(myContext.getValue(depFile));
if (filter == null || filter.accept(theFile)) {
- affectedFiles.add(theFile);
+ affectedFiles.add(theFile);
}
}
return true;
@@ -846,773 +845,270 @@ public class Mappings {
boolean accept(File file);
}
- public boolean differentiate(final Mappings delta,
- final Collection removed,
- final Collection filesToCompile,
- final Collection compiledFiles,
- final Collection affectedFiles,
- final DependentFilesFilter filter,
- @Nullable final Callbacks.ConstantAffectionResolver constantSearch) {
- synchronized (myLock) {
+ private class Differential {
+ final int DESPERATE_MASK = Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
- class DelayedWorks {
- class Triple {
- final int owner;
- final FieldRepr field;
- @Nullable
- final Future affection;
+ final Mappings myDelta;
+ final Collection myRemoved;
+ final Collection myFilesToCompile;
+ final Collection myCompiledFiles;
+ final Collection myAffectedFiles;
+ final DependentFilesFilter myFilter;
+ @Nullable final Callbacks.ConstantAffectionResolver myConstantSearch;
+ final DelayedWorks myDelayedWorks;
- private Triple(final int owner, final FieldRepr field, @Nullable final Future affection) {
- this.owner = owner;
- this.field = field;
- this.affection = affection;
- }
+ final Util myUpdated;
+ final Util mySelf;
+ final Util myOriginal;
- Callbacks.ConstantAffection getAffection() {
- try {
- return affection != null ? affection.get() : Callbacks.ConstantAffection.EMPTY;
- }
- catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
+ private class DelayedWorks {
+ class Triple {
+ final int owner;
+ final FieldRepr field;
+ @Nullable
+ final Future affection;
+
+ private Triple(final int owner, final FieldRepr field, @Nullable final Future affection) {
+ this.owner = owner;
+ this.field = field;
+ this.affection = affection;
}
- final Collection myQueue = new LinkedList();
-
- void addConstantWork(final int ownerClass, final FieldRepr changedField, final boolean isRemoved, boolean accessChanged) {
- final Future future;
- if (constantSearch == null) {
- future = null;
+ Callbacks.ConstantAffection getAffection() {
+ try {
+ return affection != null ? affection.get() : Callbacks.ConstantAffection.EMPTY;
}
- else {
- final String className = myContext.getValue(ownerClass);
- final String fieldName = myContext.getValue(changedField.name);
- future = constantSearch.request(className.replace('/', '.'), fieldName, changedField.access, isRemoved, accessChanged);
+ catch (Exception e) {
+ throw new RuntimeException(e);
}
- myQueue.add(new Triple(ownerClass, changedField, future));
- }
-
- boolean doWork(final Collection affectedFiles) {
- if (!myQueue.isEmpty()) {
- debug("Starting delayed works.");
-
- for (final Triple t : myQueue) {
- final Callbacks.ConstantAffection affection = t.getAffection();
-
- debug("Class: ", t.owner);
- debug("Field: ", t.field.name);
-
- if (!affection.isKnown()) {
- debug("No external dependency information available.");
- debug("Trying to soften non-incremental decision.");
- if (!incrementalDecision(t.owner, t.field, affectedFiles, filter)) {
- debug("No luck.");
- debug("End of delayed work, returning false.");
- return false;
- }
- }
- else {
- debug("External dependency information retrieved.");
- affectedFiles.addAll(affection.getAffectedFiles());
- }
- }
-
- debug("End of delayed work, returning true.");
- }
- return true;
}
}
- final DelayedWorks works = new DelayedWorks();
+ final Collection myQueue = new LinkedList();
- debug("Begin of Differentiate:");
+ void addConstantWork(final int ownerClass, final FieldRepr changedField, final boolean isRemoved, boolean accessChanged) {
+ final Future future;
+ if (myConstantSearch == null) {
+ future = null;
+ }
+ else {
+ final String className = myContext.getValue(ownerClass);
+ final String fieldName = myContext.getValue(changedField.name);
+ future = myConstantSearch.request(className.replace('/', '.'), fieldName, changedField.access, isRemoved, accessChanged);
+ }
+ myQueue.add(new Triple(ownerClass, changedField, future));
+ }
- delta.runPostPasses();
- delta.compensateRemovedContent(filesToCompile);
+ boolean doWork(final Collection affectedFiles) {
+ if (!myQueue.isEmpty()) {
+ debug("Starting delayed works.");
- final Util u = new Util(delta);
- final Util self = new Util(this);
- final Util o = new Util();
+ for (final Triple t : myQueue) {
+ final Callbacks.ConstantAffection affection = t.getAffection();
- if (removed != null) {
- for (String file : removed) {
+ debug("Class: ", t.owner);
+ debug("Field: ", t.field.name);
+
+ if (!affection.isKnown()) {
+ debug("No external dependency information available.");
+ debug("Trying to soften non-incremental decision.");
+ if (!incrementalDecision(t.owner, t.field, affectedFiles, myFilter)) {
+ debug("No luck.");
+ debug("End of delayed work, returning false.");
+ return false;
+ }
+ }
+ else {
+ debug("External dependency information retrieved.");
+ affectedFiles.addAll(affection.getAffectedFiles());
+ }
+ }
+
+ debug("End of delayed work, returning true.");
+ }
+ return true;
+ }
+ }
+
+ private class FileClasses {
+ final int fileName;
+ final Set fileClasses;
+
+ FileClasses(int fileName, Collection fileClasses) {
+ this.fileName = fileName;
+ this.fileClasses = new HashSet(fileClasses);
+ }
+ }
+
+ private class DiffState {
+ final public TIntHashSet dependants = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
+
+ final public Set affectedUsages = new HashSet();
+ final public Set annotationQuery = new HashSet();
+ final public Map usageConstraints = new HashMap();
+
+ final Difference.Specifier classDiff;
+
+ private DiffState(Difference.Specifier classDiff) {
+ this.classDiff = classDiff;
+ }
+ }
+
+ private Differential(final Mappings delta,
+ final Collection removed,
+ final Collection filesToCompile,
+ final Collection compiledFiles,
+ final Collection affectedFiles,
+ final DependentFilesFilter filter,
+ @Nullable final Callbacks.ConstantAffectionResolver constantSearch) {
+ this.myDelta = delta;
+ this.myRemoved = removed;
+ this.myFilesToCompile = filesToCompile;
+ this.myCompiledFiles = compiledFiles;
+ this.myAffectedFiles = affectedFiles;
+ this.myFilter = filter;
+ this.myConstantSearch = constantSearch;
+
+ myDelayedWorks = new DelayedWorks();
+
+ myUpdated = new Util(myDelta);
+ mySelf = new Util(Mappings.this);
+ myOriginal = new Util();
+ }
+
+ private void processDisappearedClasses() {
+ myDelta.runPostPasses();
+ myDelta.compensateRemovedContent(myFilesToCompile);
+
+ if (myRemoved != null) {
+ for (String file : myRemoved) {
final Collection classes = mySourceFileToClasses.get(myContext.get(file));
if (classes != null) {
for (ClassRepr c : classes) {
debug("Affecting usages of removed class ", c.name);
- u.affectAll(c.name, affectedFiles, filter);
+ myUpdated.affectAll(c.name, myAffectedFiles, myFilter);
}
}
}
}
+ }
- class FileClasses {
- final int fileName;
- final Set fileClasses;
+ private void processAddedMethods (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
+ debug("Processing added methods: ");
+ for (final MethodRepr m : diff.methods().added()) {
+ debug("Method: ", m.name);
- FileClasses(int fileName, Collection fileClasses) {
- this.fileName = fileName;
- this.fileClasses = new HashSet(fileClasses);
+ if (it.isAnnotation()) {
+ debug("Class is annotation, skipping method analysis");
+ continue;
}
- }
- final List newClasses = new ArrayList();
- delta.mySourceFileToClasses.forEachEntry(new TIntObjectProcedure>() {
- @Override
- public boolean execute(int fileName, Collection classes) {
- newClasses.add(new FileClasses(fileName, classes));
- return true;
+ if ((it.access & Opcodes.ACC_INTERFACE) > 0 ||
+ (it.access & Opcodes.ACC_ABSTRACT) > 0 ||
+ (m.access & Opcodes.ACC_ABSTRACT) > 0) {
+ debug("Class is abstract, or is interface, or added method in abstract => affecting all subclasses");
+ myUpdated.affectSubclasses(it.name, myAffectedFiles, state.affectedUsages, state.dependants, false);
}
- });
- for (final FileClasses compiledFile : newClasses) {
- final int fileName = compiledFile.fileName;
- final Set classes = compiledFile.fileClasses;
- final Set pastClasses = (Set)mySourceFileToClasses.get(fileName);
- final TIntHashSet dependants = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
+ TIntHashSet propagated = null;
- final Set affectedUsages = new HashSet();
- final Set annotationQuery = new HashSet();
- final Map usageConstraints = new HashMap();
+ if ((m.access & Opcodes.ACC_PRIVATE) == 0 && m.name != myInitName) {
+ final ClassRepr oldIt = getReprByName(it.name);
- final Difference.Specifier classDiff = Difference.make(pastClasses, classes);
+ if (oldIt != null && mySelf.findOverridenMethods(m, oldIt).size() > 0) {
- debug("Processing changed classes:");
- for (final Pair changed : classDiff.changed()) {
- final ClassRepr it = changed.first;
- final ClassRepr.Diff diff = (ClassRepr.Diff)changed.second;
+ }
+ else {
+ if (m.argumentTypes.length > 0) {
+ propagated = myUpdated.propagateMethodAccess(m.name, it.name);
+ debug("Conservative case on overriding methods, affecting method usages");
+ myUpdated.affectMethodUsages(m, propagated, m.createMetaUsage(myContext, it.name), state.affectedUsages, state.dependants);
+ }
+ }
+ }
- self.appendDependents(it, dependants);
+ if ((m.access & Opcodes.ACC_PRIVATE) == 0) {
+ final Collection> affectedMethods = myUpdated.findAllMethodsBySpecificity(m, it);
+ final MethodRepr.Predicate overrides = MethodRepr.equalByJavaRules(m);
- delta.addChangedClass(it.name);
-
- debug("Changed: ", it.name);
-
- final int addedModifiers = diff.addedModifiers();
-
- final boolean superClassChanged = (diff.base() & Difference.SUPERCLASS) > 0;
- final boolean interfacesChanged = !diff.interfaces().unchanged();
- final boolean signatureChanged = (diff.base() & Difference.SIGNATURE) > 0;
-
- if (superClassChanged || interfacesChanged || signatureChanged) {
- debug("Superclass changed: ", superClassChanged);
- debug("Interfaces changed: ", interfacesChanged);
- debug("Signature changed ", signatureChanged);
-
- final boolean extendsChanged = superClassChanged && !diff.extendsAdded();
- final boolean interfacesRemoved = interfacesChanged && !diff.interfaces().removed().isEmpty();
-
- debug("Extends changed: ", extendsChanged);
- debug("Interfaces removed: ", interfacesRemoved);
-
- u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, extendsChanged || interfacesRemoved || signatureChanged);
+ if (propagated == null) {
+ propagated = myUpdated.propagateMethodAccess(m.name, it.name);
}
- if ((diff.addedModifiers() & Opcodes.ACC_INTERFACE) > 0 || (diff.removedModifiers() & Opcodes.ACC_INTERFACE) > 0) {
- debug("Class-to-interface or interface-to-class conversion detected, added class usage to affected usages");
- affectedUsages.add(it.createUsage());
- }
+ final Collection lessSpecific = it.findMethods(myUpdated.lessSpecific(m));
- if (it.isAnnotation() && it.policy == RetentionPolicy.SOURCE) {
- debug("Annotation, retention policy = SOURCE => a switch to non-incremental mode requested");
- if (!incrementalDecision(it.outerClassName, it, affectedFiles, filter)) {
- debug("End of Differentiate, returning false");
- return false;
+ for (final MethodRepr mm : lessSpecific) {
+ if (!mm.equals(m)) {
+ debug("Found less specific method, affecting method usages");
+ myUpdated.affectMethodUsages(mm, propagated, mm.createUsage(myContext, it.name), state.affectedUsages, state.dependants);
}
}
- if ((addedModifiers & Opcodes.ACC_PROTECTED) > 0) {
- debug("Introduction of 'protected' modifier detected, adding class usage + inheritance constraint to affected usages");
- final UsageRepr.Usage usage = it.createUsage();
+ debug("Processing affected by specificity methods");
+ for (final Pair p : affectedMethods) {
+ final MethodRepr mm = p.first;
+ final ClassRepr cc = p.second;
- affectedUsages.add(usage);
- usageConstraints.put(usage, u.new InheritanceConstraint(it.name));
- }
+ if (cc == myMockClass) {
- if (diff.packageLocalOn()) {
- debug("Introduction of 'package local' access detected, adding class usage + package constraint to affected usages");
- final UsageRepr.Usage usage = it.createUsage();
-
- affectedUsages.add(usage);
- usageConstraints.put(usage, u.new PackageConstraint(it.getPackageName()));
- }
-
- if ((addedModifiers & Opcodes.ACC_FINAL) > 0 || (addedModifiers & Opcodes.ACC_PRIVATE) > 0) {
- debug("Introduction of 'private' or 'final' modifier(s) detected, adding class usage to affected usages");
- affectedUsages.add(it.createUsage());
- }
-
- if ((addedModifiers & Opcodes.ACC_ABSTRACT) > 0 || (addedModifiers & Opcodes.ACC_STATIC) > 0) {
- debug("Introduction of 'abstract' or 'static' modifier(s) detected, adding class new usage to affected usages");
- affectedUsages.add(UsageRepr.createClassNewUsage(myContext, it.name));
- }
-
- if (it.isAnnotation()) {
- debug("Class is annotation, performing annotation-specific analysis");
-
- if (diff.retentionChanged()) {
- debug("Retention policy change detected, adding class usage to affected usages");
- affectedUsages.add(it.createUsage());
}
else {
- final Collection removedtargets = diff.targets().removed();
+ final Option inheritorOf = mySelf.isInheritorOf(cc.name, it.name);
- if (removedtargets.contains(ElemType.LOCAL_VARIABLE)) {
- debug("Removed target contains LOCAL_VARIABLE => a switch to non-incremental mode requested");
- if (!incrementalDecision(it.outerClassName, it, affectedFiles, filter)) {
- debug("End of Differentiate, returning false");
- return false;
+ debug("Method: ", mm.name);
+ debug("Class : ", cc.name);
+
+ if (overrides.satisfy(mm) && inheritorOf.isValue() && inheritorOf.value()) {
+ debug("Current method overrides that found");
+
+ final int file = myClassToSourceFile.get(cc.name);
+
+ if (file > 0) {
+ final String f = myContext.getValue(file);
+ debug("Affecting file ", f);
+ myAffectedFiles.add(new File(f));
}
}
-
- if (!removedtargets.isEmpty()) {
- debug("Removed some annotation targets, adding annotation query");
- annotationQuery.add((UsageRepr.AnnotationUsage)UsageRepr
- .createAnnotationUsage(myContext, TypeRepr.createClassType(myContext, it.name), null, EnumSet.copyOf(removedtargets)));
- }
-
- for (final MethodRepr m : diff.methods().added()) {
- if (!m.hasValue()) {
- debug("Added method with no default value: ", m.name);
- debug("Adding class usage to affected usages");
- affectedUsages.add(it.createUsage());
- }
- }
- }
-
- debug("End of annotation-specific analysis");
- }
-
- debug("Processing added methods: ");
- for (final MethodRepr m : diff.methods().added()) {
- debug("Method: ", m.name);
-
- if (it.isAnnotation()) {
- debug("Class is annotation, skipping method analysis");
- continue;
- }
-
- if ((it.access & Opcodes.ACC_INTERFACE) > 0 ||
- (it.access & Opcodes.ACC_ABSTRACT) > 0 ||
- (m.access & Opcodes.ACC_ABSTRACT) > 0) {
- debug("Class is abstract, or is interface, or added method in abstract => affecting all subclasses");
- u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, false);
- }
-
- TIntHashSet propagated = null;
-
- if ((m.access & Opcodes.ACC_PRIVATE) == 0 && m.name != myInitName) {
- final ClassRepr oldIt = getReprByName(it.name);
-
- if (oldIt != null && self.findOverridenMethods(m, oldIt).size() > 0) {
-
- }
else {
- if (m.argumentTypes.length > 0) {
- propagated = u.propagateMethodAccess(m.name, it.name);
- debug("Conservative case on overriding methods, affecting method usages");
- u.affectMethodUsages(m, propagated, m.createMetaUsage(myContext, it.name), affectedUsages, dependants);
- }
- }
- }
+ debug("Current method does not override that found");
- if ((m.access & Opcodes.ACC_PRIVATE) == 0) {
- final Collection> affectedMethods = u.findAllMethodsBySpecificity(m, it);
- final MethodRepr.Predicate overrides = MethodRepr.equalByJavaRules(m);
+ final TIntHashSet yetPropagated = mySelf.propagateMethodAccess(mm.name, it.name);
- if (propagated == null) {
- propagated = u.propagateMethodAccess(m.name, it.name);
- }
-
- final Collection lessSpecific = it.findMethods(u.lessSpecific(m));
-
- for (final MethodRepr mm : lessSpecific) {
- if (!mm.equals(m)) {
- debug("Found less specific method, affecting method usages");
- u.affectMethodUsages(mm, propagated, mm.createUsage(myContext, it.name), affectedUsages, dependants);
- }
- }
-
- debug("Processing affected by specificity methods");
- for (final Pair p : affectedMethods) {
- final MethodRepr mm = p.first;
- final ClassRepr cc = p.second;
-
- if (cc == myMockClass) {
-
- }
- else {
- final Option inheritorOf = self.isInheritorOf(cc.name, it.name);
-
- debug("Method: ", mm.name);
- debug("Class : ", cc.name);
-
- if (overrides.satisfy(mm) && inheritorOf.isValue() && inheritorOf.value()) {
- debug("Current method overrides that found");
-
- final int file = myClassToSourceFile.get(cc.name);
-
- if (file > 0) {
- final String f = myContext.getValue(file);
- debug("Affecting file ", f);
- affectedFiles.add(new File(f));
- }
- }
- else {
- debug("Current method does not override that found");
-
- final TIntHashSet yetPropagated = self.propagateMethodAccess(mm.name, it.name);
-
- if (inheritorOf.isValue() && inheritorOf.value()) {
- final TIntHashSet deps = myClassToClassDependency.get(cc.name);
-
- if (deps != null) {
- addAll(dependants, deps);
- }
-
- u.affectMethodUsages(mm, yetPropagated, mm.createUsage(myContext, cc.name), affectedUsages, dependants);
- }
-
- debug("Affecting method usages for that found");
- u.affectMethodUsages(mm, yetPropagated, mm.createUsage(myContext, it.name), affectedUsages, dependants);
- }
- }
- }
-
- final TIntHashSet subClasses = getAllSubclasses(it.name);
-
- if (subClasses != null) {
- subClasses.forEach(new TIntProcedure() {
- @Override
- public boolean execute(int subClass) {
- final ClassRepr r = u.reprByName(subClass);
- final int sourceFileName = myClassToSourceFile.get(subClass);
-
- if (r != null && sourceFileName > 0) {
- final int outerClass = r.outerClassName;
-
- if (u.methodVisible(outerClass, m)) {
- final String f = myContext.getValue(sourceFileName);
- debug("Affecting file due to local overriding: ", f);
- affectedFiles.add(new File(f));
- }
- }
- return true;
- }
- });
- }
- }
- }
- debug("End of added methods processing");
-
- debug("Processing removed methods:");
- for (final MethodRepr m : diff.methods().removed()) {
- debug("Method ", m.name);
-
- final Collection> overridenMethods = u.findOverridenMethods(m, it);
- final TIntHashSet propagated = u.propagateMethodAccess(m.name, it.name);
-
- if (overridenMethods.size() == 0) {
- debug("No overridden methods found, affecting method usages");
- u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), affectedUsages, dependants);
- }
- else {
- boolean clear = true;
-
- loop:
- for (final Pair overriden : overridenMethods) {
- final MethodRepr mm = overriden.first;
-
- if (mm == myMockMethod || !mm.type.equals(m.type) || !empty(mm.signature) || !empty(m.signature)) {
- clear = false;
- break loop;
- }
- }
-
- if (!clear) {
- debug("No clearly overridden methods found, affecting method usages");
- u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), affectedUsages, dependants);
- }
- }
-
- final Collection> overriding = u.findOverridingMethods(m, it, false);
-
- for (final Pair p : overriding) {
- final int fName = myClassToSourceFile.get(p.second.name);
- debug("Affecting file by overriding: ", fName);
- affectedFiles.add(new File(myContext.getValue(fName)));
- }
-
- if ((m.access & Opcodes.ACC_ABSTRACT) == 0) {
- propagated.forEach(new TIntProcedure() {
- @Override
- public boolean execute(int p) {
- if (p != it.name) {
- final ClassRepr s = u.reprByName(p);
-
- if (s != null) {
- final Collection> overridenInS = u.findOverridenMethods(m, s);
-
- overridenInS.addAll(overridenMethods);
-
- boolean allAbstract = true;
- boolean visited = false;
-
- for (final Pair pp : overridenInS) {
- final ClassRepr cc = pp.second;
-
- if (cc == myMockClass) {
- visited = true;
- continue;
- }
-
- if (cc.name == it.name) {
- continue;
- }
-
- visited = true;
- allAbstract = ((pp.first.access & Opcodes.ACC_ABSTRACT) > 0) || ((cc.access & Opcodes.ACC_INTERFACE) > 0);
-
- if (!allAbstract) {
- break;
- }
- }
-
- if (allAbstract && visited) {
- final int source = myClassToSourceFile.get(p);
-
- if (source > 0) {
- final String f = myContext.getValue(source);
- debug(
- "Removed method is not abstract & overrides some abstract method which is not then over-overriden in subclass ",
- p);
- debug("Affecting subclass source file ", f);
- affectedFiles.add(new File(f));
- }
- }
- }
- }
- return true;
- }
- });
- }
- }
- debug("End of removed methods processing");
-
- debug("Processing changed methods:");
- for (final Pair mr : diff.methods().changed()) {
- final MethodRepr m = mr.first;
- final MethodRepr.Diff d = (MethodRepr.Diff)mr.second;
- final boolean throwsChanged = (d.exceptions().added().size() > 0) || (d.exceptions().changed().size() > 0);
-
- debug("Method: ", m.name);
-
- if (it.isAnnotation()) {
- if (d.defaultRemoved()) {
- debug("Class is annotation, default value is removed => adding annotation query");
- final TIntHashSet l = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
- l.add(m.name);
- annotationQuery.add((UsageRepr.AnnotationUsage)UsageRepr
- .createAnnotationUsage(myContext, TypeRepr.createClassType(myContext, it.name), l, null));
- }
- }
- else if (d.base() != Difference.NONE || throwsChanged) {
- final TIntHashSet propagated = u.propagateMethodAccess(m.name, it.name);
-
- boolean affected = false;
- boolean constrained = false;
-
- final Set usages = new HashSet();
-
- if (d.packageLocalOn()) {
- debug("Method became package-local, affecting method usages outside the package");
- u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants);
-
- for (final UsageRepr.Usage usage : usages) {
- usageConstraints.put(usage, u.new InheritanceConstraint(it.name));
- }
-
- affectedUsages.addAll(usages);
- affected = true;
- constrained = true;
- }
-
- if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0 || throwsChanged) {
- if (!affected) {
- debug("Return type, throws list or signature changed --- affecting method usages");
- u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants);
- affectedUsages.addAll(usages);
- }
- }
- else if ((d.base() & Difference.ACCESS) > 0) {
- if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0 ||
- (d.removedModifiers() & Opcodes.ACC_STATIC) > 0 ||
- (d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0) {
- if (!affected) {
- debug("Added static or private specifier or removed static specifier --- affecting method usages");
- u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants);
- affectedUsages.addAll(usages);
- }
-
- if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0) {
- debug("Added static specifier --- affecting subclasses");
- u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, false);
- }
- }
- else {
- if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0 ||
- (d.addedModifiers() & Opcodes.ACC_PUBLIC) > 0 ||
- (d.addedModifiers() & Opcodes.ACC_ABSTRACT) > 0) {
- debug("Added final, public or abstract specifier --- affecting subclasses");
- u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, false);
- }
-
- if ((d.addedModifiers() & Opcodes.ACC_PROTECTED) > 0 && !((d.removedModifiers() & Opcodes.ACC_PRIVATE) > 0)) {
- if (!constrained) {
- debug("Added public or package-local method became protected --- affect method usages with protected constraint");
- if (!affected) {
- u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants);
- affectedUsages.addAll(usages);
- }
-
- for (final UsageRepr.Usage usage : usages) {
- usageConstraints.put(usage, u.new InheritanceConstraint(it.name));
- }
- }
- }
- }
- }
- }
- }
- debug("End of changed methods processing");
-
- final int mask = Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
-
- debug("Processing added fields");
- for (final FieldRepr f : diff.fields().added()) {
- debug("Field: ", f.name);
-
- final boolean fPrivate = (f.access & Opcodes.ACC_PRIVATE) > 0;
- final boolean fProtected = (f.access & Opcodes.ACC_PROTECTED) > 0;
- final boolean fPublic = (f.access & Opcodes.ACC_PUBLIC) > 0;
- final boolean fPLocal = !fPrivate && !fProtected && !fPublic;
-
- if (!fPrivate) {
- final TIntHashSet subClasses = getAllSubclasses(it.name);
- subClasses.forEach(new TIntProcedure() {
- @Override
- public boolean execute(int subClass) {
- final ClassRepr r = u.reprByName(subClass);
- final int sourceFileName = myClassToSourceFile.get(subClass);
-
- if (r != null && sourceFileName > 0) {
- if (r.isLocal) {
- debug(
- "Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ",
- sourceFileName);
- affectedFiles.add(new File(myContext.getValue(sourceFileName)));
- }
- else {
- final int outerClass = r.outerClassName;
-
- if (!empty(outerClass) && u.fieldVisible(outerClass, f)) {
- debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ",
- sourceFileName);
- affectedFiles.add(new File(myContext.getValue(sourceFileName)));
- }
- }
- }
-
- debug("Affecting field usages referenced from subclass ", subClass);
- final TIntHashSet propagated = u.propagateFieldAccess(f.name, subClass);
- u.affectFieldUsages(f, propagated, f.createUsage(myContext, subClass), affectedUsages, dependants);
-
- final TIntHashSet deps = myClassToClassDependency.get(subClass);
+ if (inheritorOf.isValue() && inheritorOf.value()) {
+ final TIntHashSet deps = myClassToClassDependency.get(cc.name);
if (deps != null) {
- addAll(dependants, deps);
- }
- return true;
- }
- });
- }
-
- final Collection> overridden = u.findOverridenFields(f, it);
-
- for (final Pair p : overridden) {
- final FieldRepr ff = p.first;
- final ClassRepr cc = p.second;
-
- final boolean ffPrivate = (ff.access & Opcodes.ACC_PRIVATE) > 0;
- final boolean ffProtected = (ff.access & Opcodes.ACC_PROTECTED) > 0;
- final boolean ffPublic = (ff.access & Opcodes.ACC_PUBLIC) > 0;
- final boolean ffPLocal = Difference.isPackageLocal(ff.access);
-
- if (!ffPrivate) {
- final TIntHashSet propagated = o.propagateFieldAccess(ff.name, cc.name);
- final Set localUsages = new HashSet();
-
- debug("Affecting usages of overridden field in class ", cc.name);
- u.affectFieldUsages(ff, propagated, ff.createUsage(myContext, cc.name), localUsages, dependants);
-
- if (fPrivate || (fPublic && (ffPublic || ffPLocal)) || (fProtected && ffProtected) || (fPLocal && ffPLocal)) {
-
- }
- else {
- Util.UsageConstraint constaint;
-
- if ((ffProtected && fPublic) || (fProtected && ffPublic) || (ffPLocal && fProtected)) {
- constaint = u.new NegationConstraint(u.new InheritanceConstraint(cc.name));
- }
- else if (ffPublic && ffPLocal) {
- constaint = u.new NegationConstraint(u.new PackageConstraint(cc.getPackageName()));
- }
- else {
- constaint = u.new IntersectionConstraint(u.new NegationConstraint(u.new InheritanceConstraint(cc.name)),
- u.new NegationConstraint(u.new PackageConstraint(cc.getPackageName())));
+ addAll(state.dependants, deps);
}
- for (final UsageRepr.Usage usage : localUsages) {
- usageConstraints.put(usage, constaint);
- }
+ myUpdated
+ .affectMethodUsages(mm, yetPropagated, mm.createUsage(myContext, cc.name), state.affectedUsages, state.dependants);
}
- affectedUsages.addAll(localUsages);
+ debug("Affecting method usages for that found");
+ myUpdated
+ .affectMethodUsages(mm, yetPropagated, mm.createUsage(myContext, it.name), state.affectedUsages, state.dependants);
}
}
}
- debug("End of added fields processing");
- debug("Processing removed fields:");
- for (final FieldRepr f : diff.fields().removed()) {
- debug("Field: ", f.name);
+ final TIntHashSet subClasses = getAllSubclasses(it.name);
- if ((f.access & Opcodes.ACC_PRIVATE) == 0 && (f.access & mask) == mask && f.hasValue()) {
- debug("Field had value and was (non-private) final static => a switch to non-incremental mode requested");
- if (constantSearch != null) {
- works.addConstantWork(it.name, f, true, false);
- }
- else {
- if (!incrementalDecision(it.name, f, affectedFiles, filter)) {
- debug("End of Differentiate, returning false");
- return false;
- }
- }
- }
-
- final TIntHashSet propagated = u.propagateFieldAccess(f.name, it.name);
- u.affectFieldUsages(f, propagated, f.createUsage(myContext, it.name), affectedUsages, dependants);
- }
- debug("End of removed fields processing");
-
- debug("Processing changed fields:");
- for (final Pair f : diff.fields().changed()) {
- final Difference d = f.second;
- final FieldRepr field = f.first;
-
- debug("Field: ", field.name);
-
- if ((field.access & Opcodes.ACC_PRIVATE) == 0 && (field.access & mask) == mask) {
- final int changedModifiers = d.addedModifiers() | d.removedModifiers();
- final boolean harmful = (changedModifiers & (Opcodes.ACC_STATIC | Opcodes.ACC_FINAL)) > 0;
- final boolean accessChanged = (changedModifiers & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) > 0;
- final boolean valueChanged = (d.base() & Difference.VALUE) > 0 && d.hadValue();
-
- if (harmful || valueChanged || (accessChanged && !d.weakedAccess())) {
- debug("Inline field changed it's access or value => a switch to non-incremental mode requested");
- if (constantSearch != null) {
- works.addConstantWork(it.name, field, false, accessChanged);
- }
- else {
- if (!incrementalDecision(it.name, field, affectedFiles, filter)) {
- debug("End of Differentiate, returning false");
- return false;
- }
- }
- }
- }
-
- if (d.base() != Difference.NONE) {
- final TIntHashSet propagated = u.propagateFieldAccess(field.name, it.name);
-
- if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0) {
- debug("Type or signature changed --- affecting field usages");
- u.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), affectedUsages, dependants);
- }
- else if ((d.base() & Difference.ACCESS) > 0) {
- if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0 ||
- (d.removedModifiers() & Opcodes.ACC_STATIC) > 0 ||
- (d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0 ||
- (d.addedModifiers() & Opcodes.ACC_VOLATILE) > 0) {
- debug("Added/removed static modifier or added private/volatile modifier --- affecting field usages");
- u.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), affectedUsages, dependants);
- }
- else {
- boolean affected = false;
- final Set usages = new HashSet();
-
- if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0) {
- debug("Added final modifier --- affecting field assign usages");
- u.affectFieldUsages(field, propagated, field.createAssignUsage(myContext, it.name), usages, dependants);
- affectedUsages.addAll(usages);
- affected = true;
- }
-
- if ((d.removedModifiers() & Opcodes.ACC_PUBLIC) > 0) {
- debug("Removed public modifier, affecting field usages with appropriate constraint");
- if (!affected) {
- u.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), usages, dependants);
- affectedUsages.addAll(usages);
- }
-
- for (final UsageRepr.Usage usage : usages) {
- if ((d.addedModifiers() & Opcodes.ACC_PROTECTED) > 0) {
- usageConstraints.put(usage, u.new InheritanceConstraint(it.name));
- }
- else {
- usageConstraints.put(usage, u.new PackageConstraint(it.getPackageName()));
- }
- }
- }
- }
- }
- }
- }
- debug("End of changed fields processing");
- }
- debug("End of changed classes processing");
-
- debug("Processing removed classes:");
- for (final ClassRepr c : classDiff.removed()) {
- delta.addDeletedClass(c);
- self.appendDependents(c, dependants);
- debug("Adding usages of class ", c.name);
- affectedUsages.add(c.createUsage());
- }
- debug("End of removed classes processing.");
-
- debug("Processing added classes:");
- for (final ClassRepr c : classDiff.added()) {
- debug("Class name: ", c.name);
- delta.addChangedClass(c.name);
-
- final TIntHashSet depClasses = myClassToClassDependency.get(c.name);
-
- if (depClasses != null) {
- depClasses.forEach(new TIntProcedure() {
+ if (subClasses != null) {
+ subClasses.forEach(new TIntProcedure() {
@Override
- public boolean execute(int depClass) {
- final int fName = myClassToSourceFile.get(depClass);
+ public boolean execute(int subClass) {
+ final ClassRepr r = myUpdated.reprByName(subClass);
+ final int sourceFileName = myClassToSourceFile.get(subClass);
- if (fName > 0) {
- final String f = myContext.getValue(fName);
- final File theFile = new File(f);
+ if (r != null && sourceFileName > 0) {
+ final int outerClass = r.outerClassName;
- if (filter.accept(theFile)) {
- debug("Adding dependent file ", f);
- affectedFiles.add(theFile);
+ if (myUpdated.methodVisible(outerClass, m)) {
+ final String f = myContext.getValue(sourceFileName);
+ debug("Affecting file due to local overriding: ", f);
+ myAffectedFiles.add(new File(f));
}
}
return true;
@@ -1620,92 +1116,704 @@ public class Mappings {
});
}
}
- debug("End of added classes processing.");
+ }
+ debug("End of added methods processing");
+ }
- debug("Checking dependent files:");
- final TIntHashSet dependentFiles = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
+ private void processRemovedMethods (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
+ debug("Processing removed methods:");
+ for (final MethodRepr m : diff.methods().removed()) {
+ debug("Method ", m.name);
- dependants.forEach(new TIntProcedure() {
- @Override
- public boolean execute(int depClass) {
- final int file = myClassToSourceFile.get(depClass);
- if (file > 0) {
- dependentFiles.add(file);
+ final Collection> overridenMethods = myUpdated.findOverridenMethods(m, it);
+ final TIntHashSet propagated = myUpdated.propagateMethodAccess(m.name, it.name);
+
+ if (overridenMethods.size() == 0) {
+ debug("No overridden methods found, affecting method usages");
+ myUpdated.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), state.affectedUsages, state.dependants);
+ }
+ else {
+ boolean clear = true;
+
+ loop:
+ for (final Pair overriden : overridenMethods) {
+ final MethodRepr mm = overriden.first;
+
+ if (mm == myMockMethod || !mm.type.equals(m.type) || !empty(mm.signature) || !empty(m.signature)) {
+ clear = false;
+ break loop;
}
- return true;
- }
- });
-
-
- filewise:
- for (final int depFile : dependentFiles.toArray()) { // todo: avoid toArray()?
- final File theFile = new File(myContext.getValue(depFile));
-
- if (affectedFiles.contains(theFile) || compiledFiles.contains(theFile)) {
- continue filewise;
}
- debug("Dependent file: ", depFile);
- final Collection depClusters = mySourceFileToUsages.get(depFile);
- if (depClusters != null) {
- for (final UsageRepr.Cluster depCluster : depClusters) {
- final Set depUsages = depCluster.getUsages();
- if (depUsages == null) {
- continue;
- }
- final Set usages = new HashSet(depUsages);
+ if (!clear) {
+ debug("No clearly overridden methods found, affecting method usages");
+ myUpdated.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), state.affectedUsages, state.dependants);
+ }
+ }
- usages.retainAll(affectedUsages);
+ final Collection> overriding = myUpdated.findOverridingMethods(m, it, false);
- if (!usages.isEmpty()) {
- for (UsageRepr.Usage usage : usages) {
- final Util.UsageConstraint constraint = usageConstraints.get(usage);
+ for (final Pair p : overriding) {
+ final int fName = myClassToSourceFile.get(p.second.name);
+ debug("Affecting file by overriding: ", fName);
+ myAffectedFiles.add(new File(myContext.getValue(fName)));
+ }
- if (constraint == null) {
- debug("Added file with no constraints");
- affectedFiles.add(theFile);
- continue filewise;
+ if ((m.access & Opcodes.ACC_ABSTRACT) == 0) {
+ propagated.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int p) {
+ if (p != it.name) {
+ final ClassRepr s = myUpdated.reprByName(p);
+
+ if (s != null) {
+ final Collection> overridenInS = myUpdated.findOverridenMethods(m, s);
+
+ overridenInS.addAll(overridenMethods);
+
+ boolean allAbstract = true;
+ boolean visited = false;
+
+ for (final Pair pp : overridenInS) {
+ final ClassRepr cc = pp.second;
+
+ if (cc == myMockClass) {
+ visited = true;
+ continue;
+ }
+
+ if (cc.name == it.name) {
+ continue;
+ }
+
+ visited = true;
+ allAbstract = ((pp.first.access & Opcodes.ACC_ABSTRACT) > 0) || ((cc.access & Opcodes.ACC_INTERFACE) > 0);
+
+ if (!allAbstract) {
+ break;
+ }
}
- else {
- final TIntHashSet residenceClasses = depCluster.getResidence(usage);
- for (final int residentName : residenceClasses.toArray()) {
- if (constraint.checkResidence(residentName)) {
- debug("Added file with satisfied constraint");
- affectedFiles.add(theFile);
- continue filewise;
- }
+
+ if (allAbstract && visited) {
+ final int source = myClassToSourceFile.get(p);
+
+ if (source > 0) {
+ final String f = myContext.getValue(source);
+ debug(
+ "Removed method is not abstract & overrides some abstract method which is not then over-overriden in subclass ",
+ p);
+ debug("Affecting subclass source file ", f);
+ myAffectedFiles.add(new File(f));
}
}
}
}
+ return true;
+ }
+ });
+ }
+ }
+ debug("End of removed methods processing");
+ }
- if (annotationQuery.size() > 0) {
- final Collection annotationUsages = mySourceFileToAnnotationUsages.get(depFile);
+ private void processChangedMethods (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
+ debug("Processing changed methods:");
+ for (final Pair mr : diff.methods().changed()) {
+ final MethodRepr m = mr.first;
+ final MethodRepr.Diff d = (MethodRepr.Diff)mr.second;
+ final boolean throwsChanged = (d.exceptions().added().size() > 0) || (d.exceptions().changed().size() > 0);
- for (final UsageRepr.Usage usage : annotationUsages) {
- for (final UsageRepr.AnnotationUsage query : annotationQuery) {
- if (query.satisfies(usage)) {
- debug("Added file due to annotation query");
- affectedFiles.add(theFile);
+ debug("Method: ", m.name);
+
+ if (it.isAnnotation()) {
+ if (d.defaultRemoved()) {
+ debug("Class is annotation, default value is removed => adding annotation query");
+ final TIntHashSet l = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
+ l.add(m.name);
+ state.annotationQuery.add((UsageRepr.AnnotationUsage)UsageRepr
+ .createAnnotationUsage(myContext, TypeRepr.createClassType(myContext, it.name), l, null));
+ }
+ }
+ else if (d.base() != Difference.NONE || throwsChanged) {
+ final TIntHashSet propagated = myUpdated.propagateMethodAccess(m.name, it.name);
+
+ boolean affected = false;
+ boolean constrained = false;
+
+ final Set usages = new HashSet();
+
+ if (d.packageLocalOn()) {
+ debug("Method became package-local, affecting method usages outside the package");
+ myUpdated.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, state.dependants);
+
+ for (final UsageRepr.Usage usage : usages) {
+ state.usageConstraints.put(usage, myUpdated.new InheritanceConstraint(it.name));
+ }
+
+ state.affectedUsages.addAll(usages);
+ affected = true;
+ constrained = true;
+ }
+
+ if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0 || throwsChanged) {
+ if (!affected) {
+ debug("Return type, throws list or signature changed --- affecting method usages");
+ myUpdated.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, state.dependants);
+ state.affectedUsages.addAll(usages);
+ }
+ }
+ else if ((d.base() & Difference.ACCESS) > 0) {
+ if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0 ||
+ (d.removedModifiers() & Opcodes.ACC_STATIC) > 0 ||
+ (d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0) {
+ if (!affected) {
+ debug("Added static or private specifier or removed static specifier --- affecting method usages");
+ myUpdated.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, state.dependants);
+ state.affectedUsages.addAll(usages);
+ }
+
+ if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0) {
+ debug("Added static specifier --- affecting subclasses");
+ myUpdated.affectSubclasses(it.name, myAffectedFiles, state.affectedUsages, state.dependants, false);
+ }
+ }
+ else {
+ if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0 ||
+ (d.addedModifiers() & Opcodes.ACC_PUBLIC) > 0 ||
+ (d.addedModifiers() & Opcodes.ACC_ABSTRACT) > 0) {
+ debug("Added final, public or abstract specifier --- affecting subclasses");
+ myUpdated.affectSubclasses(it.name, myAffectedFiles, state.affectedUsages, state.dependants, false);
+ }
+
+ if ((d.addedModifiers() & Opcodes.ACC_PROTECTED) > 0 && !((d.removedModifiers() & Opcodes.ACC_PRIVATE) > 0)) {
+ if (!constrained) {
+ debug("Added public or package-local method became protected --- affect method usages with protected constraint");
+ if (!affected) {
+ myUpdated.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, state.dependants);
+ state.affectedUsages.addAll(usages);
+ }
+
+ for (final UsageRepr.Usage usage : usages) {
+ state.usageConstraints.put(usage, myUpdated.new InheritanceConstraint(it.name));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ debug("End of changed methods processing");
+ }
+
+ private boolean processAddedFields (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
+ debug("Processing added fields");
+
+ for (final FieldRepr f : diff.fields().added()) {
+ debug("Field: ", f.name);
+
+ final boolean fPrivate = (f.access & Opcodes.ACC_PRIVATE) > 0;
+ final boolean fProtected = (f.access & Opcodes.ACC_PROTECTED) > 0;
+ final boolean fPublic = (f.access & Opcodes.ACC_PUBLIC) > 0;
+ final boolean fPLocal = !fPrivate && !fProtected && !fPublic;
+
+ if (!fPrivate) {
+ final TIntHashSet subClasses = getAllSubclasses(it.name);
+ subClasses.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int subClass) {
+ final ClassRepr r = myUpdated.reprByName(subClass);
+ final int sourceFileName = myClassToSourceFile.get(subClass);
+
+ if (r != null && sourceFileName > 0) {
+ if (r.isLocal) {
+ debug(
+ "Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ",
+ sourceFileName);
+ myAffectedFiles.add(new File(myContext.getValue(sourceFileName)));
+ }
+ else {
+ final int outerClass = r.outerClassName;
+
+ if (!empty(outerClass) && myUpdated.fieldVisible(outerClass, f)) {
+ debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ",
+ sourceFileName);
+ myAffectedFiles.add(new File(myContext.getValue(sourceFileName)));
+ }
+ }
+ }
+
+ debug("Affecting field usages referenced from subclass ", subClass);
+ final TIntHashSet propagated = myUpdated.propagateFieldAccess(f.name, subClass);
+ myUpdated.affectFieldUsages(f, propagated, f.createUsage(myContext, subClass), state.affectedUsages, state.dependants);
+
+ final TIntHashSet deps = myClassToClassDependency.get(subClass);
+
+ if (deps != null) {
+ addAll(state.dependants, deps);
+ }
+ return true;
+ }
+ });
+ }
+
+ final Collection> overridden = myUpdated.findOverridenFields(f, it);
+
+ for (final Pair p : overridden) {
+ final FieldRepr ff = p.first;
+ final ClassRepr cc = p.second;
+
+ final boolean ffPrivate = (ff.access & Opcodes.ACC_PRIVATE) > 0;
+ final boolean ffProtected = (ff.access & Opcodes.ACC_PROTECTED) > 0;
+ final boolean ffPublic = (ff.access & Opcodes.ACC_PUBLIC) > 0;
+ final boolean ffPLocal = Difference.isPackageLocal(ff.access);
+
+ if (!ffPrivate) {
+ final TIntHashSet propagated = myOriginal.propagateFieldAccess(ff.name, cc.name);
+ final Set localUsages = new HashSet();
+
+ debug("Affecting usages of overridden field in class ", cc.name);
+ myUpdated.affectFieldUsages(ff, propagated, ff.createUsage(myContext, cc.name), localUsages, state.dependants);
+
+ if (fPrivate || (fPublic && (ffPublic || ffPLocal)) || (fProtected && ffProtected) || (fPLocal && ffPLocal)) {
+
+ }
+ else {
+ Util.UsageConstraint constaint;
+
+ if ((ffProtected && fPublic) || (fProtected && ffPublic) || (ffPLocal && fProtected)) {
+ constaint = myUpdated.new NegationConstraint(myUpdated.new InheritanceConstraint(cc.name));
+ }
+ else if (ffPublic && ffPLocal) {
+ constaint = myUpdated.new NegationConstraint(myUpdated.new PackageConstraint(cc.getPackageName()));
+ }
+ else {
+ constaint =
+ myUpdated.new IntersectionConstraint(myUpdated.new NegationConstraint(myUpdated.new InheritanceConstraint(cc.name)),
+ myUpdated.new NegationConstraint(
+ myUpdated.new PackageConstraint(cc.getPackageName())));
+ }
+
+ for (final UsageRepr.Usage usage : localUsages) {
+ state.usageConstraints.put(usage, constaint);
+ }
+ }
+
+ state.affectedUsages.addAll(localUsages);
+ }
+ }
+ }
+ debug("End of added fields processing");
+
+ return true;
+ }
+
+ private boolean processRemovedFields (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
+ debug("Processing removed fields:");
+
+ for (final FieldRepr f : diff.fields().removed()) {
+ debug("Field: ", f.name);
+
+ if ((f.access & Opcodes.ACC_PRIVATE) == 0 && (f.access & DESPERATE_MASK) == DESPERATE_MASK && f.hasValue()) {
+ debug("Field had value and was (non-private) final static => a switch to non-incremental mode requested");
+ if (myConstantSearch != null) {
+ myDelayedWorks.addConstantWork(it.name, f, true, false);
+ }
+ else {
+ if (!incrementalDecision(it.name, f, myAffectedFiles, myFilter)) {
+ debug("End of Differentiate, returning false");
+ return false;
+ }
+ }
+ }
+
+ final TIntHashSet propagated = myUpdated.propagateFieldAccess(f.name, it.name);
+ myUpdated.affectFieldUsages(f, propagated, f.createUsage(myContext, it.name), state.affectedUsages, state.dependants);
+ }
+ debug("End of removed fields processing");
+
+ return true;
+ }
+
+ private boolean processChangedFields (final DiffState state, final ClassRepr.Diff diff, final ClassRepr it) {
+ debug("Processing changed fields:");
+
+ for (final Pair f : diff.fields().changed()) {
+ final Difference d = f.second;
+ final FieldRepr field = f.first;
+
+ debug("Field: ", field.name);
+
+ if ((field.access & Opcodes.ACC_PRIVATE) == 0 && (field.access & DESPERATE_MASK) == DESPERATE_MASK) {
+ final int changedModifiers = d.addedModifiers() | d.removedModifiers();
+ final boolean harmful = (changedModifiers & (Opcodes.ACC_STATIC | Opcodes.ACC_FINAL)) > 0;
+ final boolean accessChanged = (changedModifiers & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) > 0;
+ final boolean valueChanged = (d.base() & Difference.VALUE) > 0 && d.hadValue();
+
+ if (harmful || valueChanged || (accessChanged && !d.weakedAccess())) {
+ debug("Inline field changed it's access or value => a switch to non-incremental mode requested");
+ if (myConstantSearch != null) {
+ myDelayedWorks.addConstantWork(it.name, field, false, accessChanged);
+ }
+ else {
+ if (!incrementalDecision(it.name, field, myAffectedFiles, myFilter)) {
+ debug("End of Differentiate, returning false");
+ return false;
+ }
+ }
+ }
+ }
+
+ if (d.base() != Difference.NONE) {
+ final TIntHashSet propagated = myUpdated.propagateFieldAccess(field.name, it.name);
+
+ if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0) {
+ debug("Type or signature changed --- affecting field usages");
+ myUpdated.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), state.affectedUsages, state.dependants);
+ }
+ else if ((d.base() & Difference.ACCESS) > 0) {
+ if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0 ||
+ (d.removedModifiers() & Opcodes.ACC_STATIC) > 0 ||
+ (d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0 ||
+ (d.addedModifiers() & Opcodes.ACC_VOLATILE) > 0) {
+ debug("Added/removed static modifier or added private/volatile modifier --- affecting field usages");
+ myUpdated
+ .affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), state.affectedUsages, state.dependants);
+ }
+ else {
+ boolean affected = false;
+ final Set usages = new HashSet();
+
+ if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0) {
+ debug("Added final modifier --- affecting field assign usages");
+ myUpdated.affectFieldUsages(field, propagated, field.createAssignUsage(myContext, it.name), usages, state.dependants);
+ state.affectedUsages.addAll(usages);
+ affected = true;
+ }
+
+ if ((d.removedModifiers() & Opcodes.ACC_PUBLIC) > 0) {
+ debug("Removed public modifier, affecting field usages with appropriate constraint");
+ if (!affected) {
+ myUpdated.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), usages, state.dependants);
+ state.affectedUsages.addAll(usages);
+ }
+
+ for (final UsageRepr.Usage usage : usages) {
+ if ((d.addedModifiers() & Opcodes.ACC_PROTECTED) > 0) {
+ state.usageConstraints.put(usage, myUpdated.new InheritanceConstraint(it.name));
+ }
+ else {
+ state.usageConstraints.put(usage, myUpdated.new PackageConstraint(it.getPackageName()));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ debug("End of changed fields processing");
+
+ return true;
+ }
+
+ private boolean processChangedClasses(final DiffState state) {
+ debug("Processing changed classes:");
+ for (final Pair changed : state.classDiff.changed()) {
+ final ClassRepr it = changed.first;
+ final ClassRepr.Diff diff = (ClassRepr.Diff)changed.second;
+
+ mySelf.appendDependents(it, state.dependants);
+
+ myDelta.addChangedClass(it.name);
+
+ debug("Changed: ", it.name);
+
+ final int addedModifiers = diff.addedModifiers();
+
+ final boolean superClassChanged = (diff.base() & Difference.SUPERCLASS) > 0;
+ final boolean interfacesChanged = !diff.interfaces().unchanged();
+ final boolean signatureChanged = (diff.base() & Difference.SIGNATURE) > 0;
+
+ if (superClassChanged || interfacesChanged || signatureChanged) {
+ debug("Superclass changed: ", superClassChanged);
+ debug("Interfaces changed: ", interfacesChanged);
+ debug("Signature changed ", signatureChanged);
+
+ final boolean extendsChanged = superClassChanged && !diff.extendsAdded();
+ final boolean interfacesRemoved = interfacesChanged && !diff.interfaces().removed().isEmpty();
+
+ debug("Extends changed: ", extendsChanged);
+ debug("Interfaces removed: ", interfacesRemoved);
+
+ myUpdated.affectSubclasses(it.name, myAffectedFiles, state.affectedUsages, state.dependants,
+ extendsChanged || interfacesRemoved || signatureChanged);
+ }
+
+ if ((diff.addedModifiers() & Opcodes.ACC_INTERFACE) > 0 || (diff.removedModifiers() & Opcodes.ACC_INTERFACE) > 0) {
+ debug("Class-to-interface or interface-to-class conversion detected, added class usage to affected usages");
+ state.affectedUsages.add(it.createUsage());
+ }
+
+ if (it.isAnnotation() && it.policy == RetentionPolicy.SOURCE) {
+ debug("Annotation, retention policy = SOURCE => a switch to non-incremental mode requested");
+ if (!incrementalDecision(it.outerClassName, it, myAffectedFiles, myFilter)) {
+ debug("End of Differentiate, returning false");
+ return false;
+ }
+ }
+
+ if ((addedModifiers & Opcodes.ACC_PROTECTED) > 0) {
+ debug("Introduction of 'protected' modifier detected, adding class usage + inheritance constraint to affected usages");
+ final UsageRepr.Usage usage = it.createUsage();
+
+ state.affectedUsages.add(usage);
+ state.usageConstraints.put(usage, myUpdated.new InheritanceConstraint(it.name));
+ }
+
+ if (diff.packageLocalOn()) {
+ debug("Introduction of 'package local' access detected, adding class usage + package constraint to affected usages");
+ final UsageRepr.Usage usage = it.createUsage();
+
+ state.affectedUsages.add(usage);
+ state.usageConstraints.put(usage, myUpdated.new PackageConstraint(it.getPackageName()));
+ }
+
+ if ((addedModifiers & Opcodes.ACC_FINAL) > 0 || (addedModifiers & Opcodes.ACC_PRIVATE) > 0) {
+ debug("Introduction of 'private' or 'final' modifier(s) detected, adding class usage to affected usages");
+ state.affectedUsages.add(it.createUsage());
+ }
+
+ if ((addedModifiers & Opcodes.ACC_ABSTRACT) > 0 || (addedModifiers & Opcodes.ACC_STATIC) > 0) {
+ debug("Introduction of 'abstract' or 'static' modifier(s) detected, adding class new usage to affected usages");
+ state.affectedUsages.add(UsageRepr.createClassNewUsage(myContext, it.name));
+ }
+
+ if (it.isAnnotation()) {
+ debug("Class is annotation, performing annotation-specific analysis");
+
+ if (diff.retentionChanged()) {
+ debug("Retention policy change detected, adding class usage to affected usages");
+ state.affectedUsages.add(it.createUsage());
+ }
+ else {
+ final Collection removedtargets = diff.targets().removed();
+
+ if (removedtargets.contains(ElemType.LOCAL_VARIABLE)) {
+ debug("Removed target contains LOCAL_VARIABLE => a switch to non-incremental mode requested");
+ if (!incrementalDecision(it.outerClassName, it, myAffectedFiles, myFilter)) {
+ debug("End of Differentiate, returning false");
+ return false;
+ }
+ }
+
+ if (!removedtargets.isEmpty()) {
+ debug("Removed some annotation targets, adding annotation query");
+ state.annotationQuery.add((UsageRepr.AnnotationUsage)UsageRepr
+ .createAnnotationUsage(myContext, TypeRepr.createClassType(myContext, it.name), null, EnumSet.copyOf(removedtargets)));
+ }
+
+ for (final MethodRepr m : diff.methods().added()) {
+ if (!m.hasValue()) {
+ debug("Added method with no default value: ", m.name);
+ debug("Adding class usage to affected usages");
+ state.affectedUsages.add(it.createUsage());
+ }
+ }
+ }
+
+ debug("End of annotation-specific analysis");
+ }
+
+ processAddedMethods (state, diff, it);
+ processRemovedMethods (state, diff, it);
+ processChangedMethods (state, diff, it);
+
+ if (!processAddedFields (state, diff, it)) {
+ return false;
+ }
+
+ if (!processRemovedFields (state, diff, it)) {
+ return false;
+ }
+
+ if (!processChangedFields (state, diff, it)) {
+ return false;
+ }
+ }
+ debug("End of changed classes processing");
+
+ return true;
+ }
+
+ private void processRemovedClases(final DiffState state) {
+ debug("Processing removed classes:");
+ for (final ClassRepr c : state.classDiff.removed()) {
+ myDelta.addDeletedClass(c);
+ mySelf.appendDependents(c, state.dependants);
+ debug("Adding usages of class ", c.name);
+ state.affectedUsages.add(c.createUsage());
+ }
+ debug("End of removed classes processing.");
+ }
+
+ private void processAddedClasses(final DiffState state) {
+ debug("Processing added classes:");
+ for (final ClassRepr c : state.classDiff.added()) {
+ debug("Class name: ", c.name);
+ myDelta.addChangedClass(c.name);
+
+ final TIntHashSet depClasses = myClassToClassDependency.get(c.name);
+
+ if (depClasses != null) {
+ depClasses.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int depClass) {
+ final int fName = myClassToSourceFile.get(depClass);
+
+ if (fName > 0) {
+ final String f = myContext.getValue(fName);
+ final File theFile = new File(f);
+
+ if (myFilter.accept(theFile)) {
+ debug("Adding dependent file ", f);
+ myAffectedFiles.add(theFile);
+ }
+ }
+ return true;
+ }
+ });
+ }
+ }
+ debug("End of added classes processing.");
+ }
+
+ private void calaulateAffectedFiles(final DiffState state) {
+ debug("Checking dependent files:");
+ final TIntHashSet dependentFiles = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
+
+ state.dependants.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int depClass) {
+ final int file = myClassToSourceFile.get(depClass);
+ if (file > 0) {
+ dependentFiles.add(file);
+ }
+ return true;
+ }
+ });
+
+ filewise:
+ for (final int depFile : dependentFiles.toArray()) { // todo: avoid toArray()?
+ final File theFile = new File(myContext.getValue(depFile));
+
+ if (myAffectedFiles.contains(theFile) || myCompiledFiles.contains(theFile)) {
+ continue filewise;
+ }
+
+ debug("Dependent file: ", depFile);
+ final Collection depClusters = mySourceFileToUsages.get(depFile);
+ if (depClusters != null) {
+ for (final UsageRepr.Cluster depCluster : depClusters) {
+ final Set depUsages = depCluster.getUsages();
+ if (depUsages == null) {
+ continue;
+ }
+ final Set usages = new HashSet(depUsages);
+
+ usages.retainAll(state.affectedUsages);
+
+ if (!usages.isEmpty()) {
+ for (UsageRepr.Usage usage : usages) {
+ final Util.UsageConstraint constraint = state.usageConstraints.get(usage);
+
+ if (constraint == null) {
+ debug("Added file with no constraints");
+ myAffectedFiles.add(theFile);
+ continue filewise;
+ }
+ else {
+ final TIntHashSet residenceClasses = depCluster.getResidence(usage);
+ for (final int residentName : residenceClasses.toArray()) {
+ if (constraint.checkResidence(residentName)) {
+ debug("Added file with satisfied constraint");
+ myAffectedFiles.add(theFile);
continue filewise;
}
}
}
}
}
+
+ if (state.annotationQuery.size() > 0) {
+ final Collection annotationUsages = mySourceFileToAnnotationUsages.get(depFile);
+
+ for (final UsageRepr.Usage usage : annotationUsages) {
+ for (final UsageRepr.AnnotationUsage query : state.annotationQuery) {
+ if (query.satisfies(usage)) {
+ debug("Added file due to annotation query");
+ myAffectedFiles.add(theFile);
+ continue filewise;
+ }
+ }
+ }
+ }
}
}
}
-
- if (removed != null) {
- for (final String r : removed) {
- affectedFiles.remove(new File(r));
- }
- }
-
- debug("End of Differentiate.");
- return works.doWork(affectedFiles);
}
+
+ boolean differentiate() {
+ synchronized (myLock) {
+
+ debug("Begin of Differentiate:");
+
+ processDisappearedClasses();
+
+ final List newClasses = new ArrayList();
+ myDelta.mySourceFileToClasses.forEachEntry(new TIntObjectProcedure>() {
+ @Override
+ public boolean execute(int fileName, Collection classes) {
+ newClasses.add(new FileClasses(fileName, classes));
+ return true;
+ }
+ });
+
+ for (final FileClasses compiledFile : newClasses) {
+ final int fileName = compiledFile.fileName;
+ final Set classes = compiledFile.fileClasses;
+ final Set pastClasses = (Set)mySourceFileToClasses.get(fileName);
+ final DiffState state = new DiffState(Difference.make(pastClasses, classes));
+
+ if (!processChangedClasses(state)) {
+ return false;
+ }
+
+ processRemovedClases(state);
+ processAddedClasses(state);
+
+ calaulateAffectedFiles(state);
+ }
+
+ if (myRemoved != null) {
+ for (final String r : myRemoved) {
+ myAffectedFiles.remove(new File(r));
+ }
+ }
+
+ debug("End of Differentiate.");
+ return myDelayedWorks.doWork(myAffectedFiles);
+ }
+ }
+ }
+
+ public boolean differentiate
+ (final Mappings delta,
+ final Collection removed,
+ final Collection filesToCompile,
+ final Collection compiledFiles,
+ final Collection affectedFiles,
+ final DependentFilesFilter filter,
+ @Nullable final Callbacks.ConstantAffectionResolver constantSearch) {
+ return new Differential(delta, removed, filesToCompile, compiledFiles, affectedFiles, filter, constantSearch).differentiate();
}
private void cleanupBackDependency(final int className, @Nullable Collection clusters, IntIntMultiMaplet buffer) {
diff --git a/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy b/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy
index d40e9cc91e9b..92521fb12f09 100644
--- a/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy
+++ b/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy
@@ -334,15 +334,17 @@ public class IdeaProjectLoader {
def componentTag = getComponent(root, "Encoding");
if (componentTag == null) return;
componentTag.file?.each {Node fileNode ->
- def url = fileNode."@url";
- def charset = fileNode."@charset";
+ String url = fileNode."@url";
+ String charset = fileNode."@charset";
- if ("PROJECT".equals(url)) {
- project.projectCharset = charset;
- }
- else {
- def path = projectMacroExpander.expandMacros(IdeaProjectLoadingUtil.pathFromUrl(url));
- project.filePathToCharset[path] = charset;
+ if (!StringUtil.isEmptyOrSpaces(charset)) {
+ if ("PROJECT".equals(url)) {
+ project.projectCharset = charset;
+ }
+ else {
+ def path = projectMacroExpander.expandMacros(IdeaProjectLoadingUtil.pathFromUrl(url));
+ project.filePathToCharset[FileUtil.toCanonicalPath(path)] = charset;
+ }
}
}
}
@@ -632,6 +634,12 @@ public class IdeaProjectLoader {
case "JDK_1_5": return "1.5"
case "JDK_1_6": return "1.6"
case "JDK_1_7": return "1.7"
+ case "JDK_1_8": return "1.8"
+ }
+
+ final String prefix = "JDK_";
+ if (imlPropertyText != null && imlPropertyText.startsWith(prefix)) {
+ return imlPropertyText.substring(prefix.length()).replace('_', '.');
}
return "1.6"
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/PrefixMatchingWeigher.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/PrefixMatchingWeigher.java
index 5290bf1e5ee3..2df59cd5fa37 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/PrefixMatchingWeigher.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/PrefixMatchingWeigher.java
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.psi.codeStyle.MinusculeMatcher;
import com.intellij.psi.codeStyle.NameUtil;
import org.jetbrains.annotations.NotNull;
@@ -38,7 +39,7 @@ public class PrefixMatchingWeigher extends CompletionWeigher {
final NameUtil.MatchingCaseSensitivity sensitivity =
setting == CodeInsightSettings.NONE ? NameUtil.MatchingCaseSensitivity.NONE :
setting == CodeInsightSettings.FIRST_LETTER ? NameUtil.MatchingCaseSensitivity.FIRST_LETTER : NameUtil.MatchingCaseSensitivity.ALL;
- final NameUtil.MinusculeMatcher matcher = new NameUtil.MinusculeMatcher(CamelHumpMatcher.applyMiddleMatching(prefix), sensitivity);
+ final MinusculeMatcher matcher = new MinusculeMatcher(CamelHumpMatcher.applyMiddleMatching(prefix), sensitivity);
int max = Integer.MIN_VALUE;
for (String lookupString : item.getAllLookupStrings()) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/IntentionActionWrapper.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/IntentionActionWrapper.java
index 685db4510e68..37a1d3b89ef1 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/IntentionActionWrapper.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/IntentionActionWrapper.java
@@ -32,6 +32,7 @@ public class IntentionActionWrapper implements IntentionAction {
private IntentionAction myDelegate;
private final String[] myCategories;
private final IntentionActionBean myExtension;
+ private String myFullFamilyName;
public IntentionActionWrapper(final IntentionActionBean extension, String[] categories) {
myExtension = extension;
@@ -60,13 +61,13 @@ public class IntentionActionWrapper implements IntentionAction {
return getDelegate().startInWriteAction();
}
+ @NotNull
public String getFullFamilyName(){
- if (myCategories != null) {
- return StringUtil.join(myCategories, "/") + "/" + getFamilyName();
- }
- else {
- return getFamilyName();
+ String result = myFullFamilyName;
+ if (result == null) {
+ myFullFamilyName = result = myCategories != null ? StringUtil.join(myCategories, "/") + "/" + getFamilyName() : getFamilyName();
}
+ return result;
}
public synchronized IntentionAction getDelegate() {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java
index 0a5e258a0c14..3e9b529ad131 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java
@@ -24,6 +24,7 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.codeStyle.MinusculeMatcher;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.ui.*;
import com.intellij.ui.speedSearch.SpeedSearchUtil;
@@ -255,7 +256,7 @@ public class LookupCellRenderer implements ListCellRenderer {
final String prefix = myLookup.itemPattern(item);
if (prefix.length() > 0) {
- Iterable ranges = new NameUtil.MinusculeMatcher("*" + prefix, NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(name);
+ Iterable ranges = new MinusculeMatcher("*" + prefix, NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(name);
if (ranges != null) {
SimpleTextAttributes highlighted =
new SimpleTextAttributes(style, selected ? SELECTED_PREFIX_FOREGROUND_COLOR : PREFIX_FOREGROUND_COLOR);
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
index 393fd5000bd5..c3839457750b 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
@@ -46,6 +46,7 @@ import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.ex.WindowManagerEx;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.codeStyle.MinusculeMatcher;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.psi.statistics.StatisticsInfo;
import com.intellij.psi.statistics.StatisticsManager;
@@ -1020,7 +1021,8 @@ public abstract class ChooseByNameBase {
String text = EXTRA_ELEM.equals(modelElement) ? null : myModel.getFullName(modelElement);
if (text != null) {
String shortName = myModel.getElementName(modelElement);
- int match = shortName != null && matcher instanceof NameUtil.MinusculeMatcher ? ((NameUtil.MinusculeMatcher)matcher).matchingDegree(shortName) : Integer.MIN_VALUE;
+ int match = shortName != null && matcher instanceof MinusculeMatcher
+ ? ((MinusculeMatcher)matcher).matchingDegree(shortName) : Integer.MIN_VALUE;
int stats = StatisticsManager.getInstance().getUseCount(new StatisticsInfo(statContext, text));
if (stats > best || stats == best && match > bestMatch) {
best = stats;
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
index 89bb47436d43..7fbc2a2fdbd4 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.codeStyle.MinusculeMatcher;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.psi.util.proximity.PsiProximityComparator;
import com.intellij.util.Function;
@@ -147,10 +148,10 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameItemProvider
if (name == null) return false;
final List suspects = split(name, base);
- final List> patternsAndMatchers =
- ContainerUtil.map2List(split(qualifierPattern, base), new Function>() {
+ final List> patternsAndMatchers =
+ ContainerUtil.map2List(split(qualifierPattern, base), new Function>() {
@Override
- public Pair fun(String s) {
+ public Pair fun(String s) {
return Pair.create(getNamePattern(base, s), buildPatternMatcher(getNamePattern(base, s)));
}
});
@@ -159,9 +160,9 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameItemProvider
try {
patterns:
- for (Pair patternAndMatcher : patternsAndMatchers) {
+ for (Pair patternAndMatcher : patternsAndMatchers) {
final String pattern = patternAndMatcher.first;
- final NameUtil.MinusculeMatcher matcher = patternAndMatcher.second;
+ final MinusculeMatcher matcher = patternAndMatcher.second;
if (!pattern.isEmpty()) {
for (int j = matchPosition; j < suspects.size() - 1; j++) {
String suspect = suspects.get(j);
@@ -204,7 +205,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameItemProvider
pattern = pattern.substring(1);
}
- final NameUtil.MinusculeMatcher matcher = buildPatternMatcher(pattern);
+ final MinusculeMatcher matcher = buildPatternMatcher(pattern);
try {
for (String name : names) {
@@ -221,7 +222,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameItemProvider
}
}
- private static boolean matches(ChooseByNameBase base, String pattern, NameUtil.MinusculeMatcher matcher, String name) {
+ private static boolean matches(ChooseByNameBase base, String pattern, MinusculeMatcher matcher, String name) {
boolean matches = false;
if (name != null) {
if (base.getModel() instanceof CustomMatcherModel) {
@@ -236,7 +237,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameItemProvider
return matches;
}
- private static NameUtil.MinusculeMatcher buildPatternMatcher(String pattern) {
+ private static MinusculeMatcher buildPatternMatcher(String pattern) {
return NameUtil.buildMatcher(pattern, NameUtil.MatchingCaseSensitivity.NONE);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/markup/AttributesFlyweight.java b/platform/platform-api/src/com/intellij/openapi/editor/markup/AttributesFlyweight.java
index b6ea12c0257f..05fa2cd09b82 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/markup/AttributesFlyweight.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/markup/AttributesFlyweight.java
@@ -29,7 +29,55 @@ import java.awt.*;
public class AttributesFlyweight {
private final int myHashCode;
- private static final StripedLockConcurrentHashMap entries = new StripedLockConcurrentHashMap();
+ private static final StripedLockConcurrentHashMap entries = new StripedLockConcurrentHashMap();
+ private static final ThreadLocal ourKey = new ThreadLocal();
+
+ private static class FlyweightKey implements Cloneable {
+ Color foreground;
+ Color background;
+ @JdkConstants.FontStyle int fontType;
+ Color effectColor;
+ EffectType effectType;
+ Color errorStripeColor;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof FlyweightKey)) return false;
+
+ FlyweightKey key = (FlyweightKey)o;
+
+ if (fontType != key.fontType) return false;
+ if (background != null ? !background.equals(key.background) : key.background != null) return false;
+ if (effectColor != null ? !effectColor.equals(key.effectColor) : key.effectColor != null) return false;
+ if (effectType != key.effectType) return false;
+ if (errorStripeColor != null ? !errorStripeColor.equals(key.errorStripeColor) : key.errorStripeColor != null) return false;
+ if (foreground != null ? !foreground.equals(key.foreground) : key.foreground != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = foreground != null ? foreground.hashCode() : 0;
+ result = 31 * result + (background != null ? background.hashCode() : 0);
+ result = 31 * result + fontType;
+ result = 31 * result + (effectColor != null ? effectColor.hashCode() : 0);
+ result = 31 * result + (effectType != null ? effectType.hashCode() : 0);
+ result = 31 * result + (errorStripeColor != null ? errorStripeColor.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ protected FlyweightKey clone() {
+ try {
+ return (FlyweightKey)super.clone();
+ }
+ catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
@NotNull
public static AttributesFlyweight create(Color foreground,
@@ -38,8 +86,23 @@ public class AttributesFlyweight {
Color effectColor,
EffectType effectType,
Color errorStripeColor) {
- AttributesFlyweight key = new AttributesFlyweight(foreground, background, fontType, effectColor, effectType, errorStripeColor);
- return ConcurrencyUtil.cacheOrGet(entries, key, key);
+ FlyweightKey key = ourKey.get();
+ if (key == null) {
+ ourKey.set(key = new FlyweightKey());
+ }
+ key.foreground = foreground;
+ key.background = background;
+ key.fontType = fontType;
+ key.effectColor = effectColor;
+ key.effectType = effectType;
+ key.errorStripeColor = errorStripeColor;
+
+ AttributesFlyweight flyweight = entries.get(key);
+ if (flyweight != null) {
+ return flyweight;
+ }
+
+ return ConcurrencyUtil.cacheOrGet(entries, key.clone(), new AttributesFlyweight(foreground, background, fontType, effectColor, effectType, errorStripeColor));
}
private final Color myForeground;
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java
index 367957385950..839eea53bd76 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java
@@ -716,7 +716,7 @@ public class Messages {
}
/**
- * Shows dialog with given message and title, infomation icon {@link #getInformationIcon()} and OK button
+ * Shows dialog with given message and title, information icon {@link #getInformationIcon()} and OK button
*/
public static void showInfoMessage(Component component, String message, String title) {
if (canShowMacSheetPanel()) {
@@ -728,7 +728,7 @@ public class Messages {
}
/**
- * Shows dialog with given message and title, infomation icon {@link #getInformationIcon()} and OK button
+ * Shows dialog with given message and title, information icon {@link #getInformationIcon()} and OK button
*/
public static void showInfoMessage(Project project, @Nls String message, @Nls String title) {
if (canShowMacSheetPanel()) {
@@ -740,7 +740,7 @@ public class Messages {
}
/**
- * Shows dialog with given message and title, infomation icon {@link #getInformationIcon()} and OK button
+ * Shows dialog with given message and title, information icon {@link #getInformationIcon()} and OK button
*/
public static void showInfoMessage(String message, String title) {
if (canShowMacSheetPanel()) {
diff --git a/platform/platform-api/src/com/intellij/ui/speedSearch/SpeedSearchUtil.java b/platform/platform-api/src/com/intellij/ui/speedSearch/SpeedSearchUtil.java
index b75cd5db6fa3..8e3f0f5ba13e 100644
--- a/platform/platform-api/src/com/intellij/ui/speedSearch/SpeedSearchUtil.java
+++ b/platform/platform-api/src/com/intellij/ui/speedSearch/SpeedSearchUtil.java
@@ -18,7 +18,7 @@ package com.intellij.ui.speedSearch;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.registry.Registry;
-import com.intellij.psi.codeStyle.NameUtil;
+import com.intellij.psi.codeStyle.MinusculeMatcher;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.Processor;
@@ -65,12 +65,12 @@ public final class SpeedSearchUtil {
final Matcher matcher,
final Color selectedBg,
final boolean selected) {
- if (!(matcher instanceof NameUtil.MinusculeMatcher) || (Registry.is("ide.highlight.match.in.selected.only") && !selected)) {
+ if (!(matcher instanceof MinusculeMatcher) || (Registry.is("ide.highlight.match.in.selected.only") && !selected)) {
component.append(text, attributes);
return;
}
- final Iterable iterable = ((NameUtil.MinusculeMatcher)matcher).matchingFragments(text);
+ final Iterable iterable = ((MinusculeMatcher)matcher).matchingFragments(text);
if (iterable != null) {
final Color fg = attributes.getFgColor();
final int style = attributes.getStyle();
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java
index 9d6da6f8d442..00ef9f89ad09 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java
@@ -93,6 +93,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
private final DefaultActionGroup mySecondaryActions = new DefaultActionGroup();
private boolean myMinimalMode;
+ private boolean myForceUseMacEnhancements;
public ActionButton getSecondaryActionsButton() {
return mySecondaryActionsButton;
@@ -164,7 +165,11 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
}
private boolean doMacEnhancementsForMainToolbar() {
- return (UIUtil.isUnderAquaLookAndFeel() && ActionPlaces.MAIN_TOOLBAR.equals(myPlace));
+ return (UIUtil.isUnderAquaLookAndFeel() && (ActionPlaces.MAIN_TOOLBAR.equals(myPlace) || myForceUseMacEnhancements));
+ }
+
+ public void setForceUseMacEnhancements(boolean useMacEnhancements) {
+ myForceUseMacEnhancements = useMacEnhancements;
}
private boolean isInsideNavBar() {
diff --git a/platform/platform-impl/src/com/intellij/ui/SpeedSearchComparator.java b/platform/platform-impl/src/com/intellij/ui/SpeedSearchComparator.java
index 0f3b5dccdb64..31e2f6597412 100644
--- a/platform/platform-impl/src/com/intellij/ui/SpeedSearchComparator.java
+++ b/platform/platform-impl/src/com/intellij/ui/SpeedSearchComparator.java
@@ -17,6 +17,7 @@ package com.intellij.ui;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.codeStyle.MinusculeMatcher;
import com.intellij.psi.codeStyle.NameUtil;
import org.jetbrains.annotations.Nullable;
@@ -24,7 +25,7 @@ import org.jetbrains.annotations.Nullable;
* @author Konstantin Bulenkov
*/
public class SpeedSearchComparator {
- private NameUtil.MinusculeMatcher myMinusculeMatcher;
+ private MinusculeMatcher myMinusculeMatcher;
private String myRecentSearchText;
private boolean myShouldMatchFromTheBeginning;
private boolean myShouldMatchCamelCase;
@@ -52,7 +53,7 @@ public class SpeedSearchComparator {
if (!myShouldMatchFromTheBeginning && !pattern.startsWith("*")) {
pattern = "*" + pattern;
}
- myMinusculeMatcher = new NameUtil.MinusculeMatcher(pattern, NameUtil.MatchingCaseSensitivity.NONE);
+ myMinusculeMatcher = new MinusculeMatcher(pattern, NameUtil.MatchingCaseSensitivity.NONE);
}
return myMinusculeMatcher.matchingFragments(text);
}
diff --git a/platform/platform-tests/testSrc/com/intellij/history/integration/FileListeningTest.java b/platform/platform-tests/testSrc/com/intellij/history/integration/FileListeningTest.java
index f5cbf86aac8a..2d65ec17ac8f 100644
--- a/platform/platform-tests/testSrc/com/intellij/history/integration/FileListeningTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/history/integration/FileListeningTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 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.
@@ -72,7 +72,7 @@ public class FileListeningTest extends IntegrationTestCase {
LocalFileSystem.getInstance().refresh(false);
List changes = getVcs().getChangeListInTests().getChangesInTests().get(0).getChanges();
- assertEquals(4, changes.size());
+ assertEquals(changes.toString(), 4, changes.size());
List actual = new SmartList();
for (Change each : changes) {
actual.add(((StructuralChange)each).getPath());
@@ -100,7 +100,7 @@ public class FileListeningTest extends IntegrationTestCase {
VirtualFile f = createFile("file.txt");
assertEquals(2, getRevisionsFor(f).size());
- f.rename(null, "file2.txt");
+ f.rename(this, "file2.txt");
assertEquals(3, getRevisionsFor(f).size());
}
@@ -125,7 +125,7 @@ public class FileListeningTest extends IntegrationTestCase {
addFileListenerDuring(l, new RunnableAdapter() {
@Override
public void doRun() throws IOException {
- f.rename(null, "new.txt");
+ f.rename(this, "new.txt");
}
});
@@ -139,7 +139,7 @@ public class FileListeningTest extends IntegrationTestCase {
VirtualFile f = createFile("file.hprof");
assertEquals(before, getRevisionsFor(myRoot).size());
- f.rename(null, "file.txt");
+ f.rename(this, "file.txt");
assertEquals(before + 1, getRevisionsFor(myRoot).size());
assertEquals(2, getRevisionsFor(f).size());
@@ -151,7 +151,7 @@ public class FileListeningTest extends IntegrationTestCase {
VirtualFile f = createFile("file.txt");
assertEquals(before + 1, getRevisionsFor(myRoot).size());
- f.rename(null, "file.hprof");
+ f.rename(this, "file.hprof");
assertEquals(before + 2, getRevisionsFor(myRoot).size());
}
@@ -161,7 +161,7 @@ public class FileListeningTest extends IntegrationTestCase {
VirtualFile f = createFile(FILTERED_DIR_NAME);
assertEquals(before, getRevisionsFor(myRoot).size());
- f.rename(null, "not_filtered");
+ f.rename(this, "not_filtered");
assertEquals(before + 1, getRevisionsFor(myRoot).size());
assertEquals(2, getRevisionsFor(f).size());
@@ -173,7 +173,7 @@ public class FileListeningTest extends IntegrationTestCase {
VirtualFile f = createDirectory("not_filtered");
assertEquals(before + 1, getRevisionsFor(myRoot).size());
- f.rename(null, FILTERED_DIR_NAME);
+ f.rename(this, FILTERED_DIR_NAME);
assertEquals(before + 2, getRevisionsFor(myRoot).size());
}
@@ -188,7 +188,7 @@ public class FileListeningTest extends IntegrationTestCase {
assertEquals(4, getRevisionsFor(f).size());
}
- public void testIgnoringROStstusChangeForUnversionedFiles() throws Exception {
+ public void testIgnoringROStatusChangeForUnversionedFiles() throws Exception {
int before = getRevisionsFor(myRoot).size();
VirtualFile f = createFile("f.hprof");
@@ -202,7 +202,7 @@ public class FileListeningTest extends IntegrationTestCase {
int before = getRevisionsFor(myRoot).size();
- f.delete(null);
+ f.delete(this);
assertEquals(before + 1, getRevisionsFor(myRoot).size());
}
@@ -210,24 +210,26 @@ public class FileListeningTest extends IntegrationTestCase {
int before = getRevisionsFor(myRoot).size();
VirtualFile f = createDirectory(FILTERED_DIR_NAME);
- f.delete(null);
+ f.delete(this);
assertEquals(before, getRevisionsFor(myRoot).size());
}
public void testDeletionDoesNotVersionIgnoredFilesRecursively() throws Exception {
String dir1 = createDirectoryExternally("dir");
- String f1 = createFileExternally("dir/f.txt");
+ createFileExternally("dir/f.txt");
createFileExternally("dir/f.class");
createFileExternally("dir/subdir/f.txt");
- String dir2 = createDirectoryExternally("dir/subdir/subdir2");
- String f2 = createFileExternally("dir/subdir/subdir2/f.txt");
+ createDirectoryExternally("dir/subdir/subdir2");
+ createFileExternally("dir/subdir/subdir2/f.txt");
LocalFileSystem.getInstance().refresh(false);
addExcludedDir(myRoot.getPath() + "/dir/subdir");
addContentRoot(myRoot.getPath() + "/dir/subdir/subdir2");
- LocalFileSystem.getInstance().findFileByPath(dir1).delete(this);
+ final VirtualFile vDir1 = LocalFileSystem.getInstance().findFileByPath(dir1);
+ assertNotNull(dir1, vDir1);
+ vDir1.delete(this);
List changes = getVcs().getChangeListInTests().getChangesInTests().get(0).getChanges();
assertEquals(1, changes.size());
diff --git a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java
index 72ac2b2fccac..c2a329e9dcae 100644
--- a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java
@@ -20,6 +20,7 @@
package com.intellij.psi.util;
import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.codeStyle.MinusculeMatcher;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.UsefulTestCase;
@@ -312,57 +313,57 @@ public class NameUtilTest extends UsefulTestCase {
}
public void testMinusculeFirstLetter() {
- assertTrue(new NameUtil.MinusculeMatcher("WebLogic", NameUtil.MatchingCaseSensitivity.FIRST_LETTER).matches("WebLogic"));
- assertFalse(new NameUtil.MinusculeMatcher("webLogic", NameUtil.MatchingCaseSensitivity.FIRST_LETTER).matches("WebLogic"));
- assertTrue(new NameUtil.MinusculeMatcher("cL", NameUtil.MatchingCaseSensitivity.FIRST_LETTER).matches("class"));
- assertTrue(new NameUtil.MinusculeMatcher("CL", NameUtil.MatchingCaseSensitivity.FIRST_LETTER).matches("Class"));
- assertFalse(new NameUtil.MinusculeMatcher("abc", NameUtil.MatchingCaseSensitivity.FIRST_LETTER).matches("_abc"));
+ assertTrue(new MinusculeMatcher("WebLogic", NameUtil.MatchingCaseSensitivity.FIRST_LETTER).matches("WebLogic"));
+ assertFalse(new MinusculeMatcher("webLogic", NameUtil.MatchingCaseSensitivity.FIRST_LETTER).matches("WebLogic"));
+ assertTrue(new MinusculeMatcher("cL", NameUtil.MatchingCaseSensitivity.FIRST_LETTER).matches("class"));
+ assertTrue(new MinusculeMatcher("CL", NameUtil.MatchingCaseSensitivity.FIRST_LETTER).matches("Class"));
+ assertFalse(new MinusculeMatcher("abc", NameUtil.MatchingCaseSensitivity.FIRST_LETTER).matches("_abc"));
}
public void testMinusculeAllImportant() {
- assertTrue(new NameUtil.MinusculeMatcher("WebLogic", NameUtil.MatchingCaseSensitivity.ALL).matches("WebLogic"));
- assertFalse(new NameUtil.MinusculeMatcher("webLogic", NameUtil.MatchingCaseSensitivity.ALL).matches("weblogic"));
- assertFalse(new NameUtil.MinusculeMatcher("FOO", NameUtil.MatchingCaseSensitivity.ALL).matches("foo"));
- assertFalse(new NameUtil.MinusculeMatcher("foo", NameUtil.MatchingCaseSensitivity.ALL).matches("fOO"));
- assertFalse(new NameUtil.MinusculeMatcher("Wl", NameUtil.MatchingCaseSensitivity.ALL).matches("WebLogic"));
- assertTrue(new NameUtil.MinusculeMatcher("WL", NameUtil.MatchingCaseSensitivity.ALL).matches("WebLogic"));
- assertFalse(new NameUtil.MinusculeMatcher("WL", NameUtil.MatchingCaseSensitivity.ALL).matches("Weblogic"));
- assertFalse(new NameUtil.MinusculeMatcher("WL", NameUtil.MatchingCaseSensitivity.ALL).matches("weblogic"));
- assertFalse(new NameUtil.MinusculeMatcher("webLogic", NameUtil.MatchingCaseSensitivity.ALL).matches("WebLogic"));
- assertFalse(new NameUtil.MinusculeMatcher("Str", NameUtil.MatchingCaseSensitivity.ALL).matches("SomeThingRidiculous"));
+ assertTrue(new MinusculeMatcher("WebLogic", NameUtil.MatchingCaseSensitivity.ALL).matches("WebLogic"));
+ assertFalse(new MinusculeMatcher("webLogic", NameUtil.MatchingCaseSensitivity.ALL).matches("weblogic"));
+ assertFalse(new MinusculeMatcher("FOO", NameUtil.MatchingCaseSensitivity.ALL).matches("foo"));
+ assertFalse(new MinusculeMatcher("foo", NameUtil.MatchingCaseSensitivity.ALL).matches("fOO"));
+ assertFalse(new MinusculeMatcher("Wl", NameUtil.MatchingCaseSensitivity.ALL).matches("WebLogic"));
+ assertTrue(new MinusculeMatcher("WL", NameUtil.MatchingCaseSensitivity.ALL).matches("WebLogic"));
+ assertFalse(new MinusculeMatcher("WL", NameUtil.MatchingCaseSensitivity.ALL).matches("Weblogic"));
+ assertFalse(new MinusculeMatcher("WL", NameUtil.MatchingCaseSensitivity.ALL).matches("weblogic"));
+ assertFalse(new MinusculeMatcher("webLogic", NameUtil.MatchingCaseSensitivity.ALL).matches("WebLogic"));
+ assertFalse(new MinusculeMatcher("Str", NameUtil.MatchingCaseSensitivity.ALL).matches("SomeThingRidiculous"));
}
public void testMatchingFragments() {
@NonNls String sample = "NoClassDefFoundException";
// 0 2 7 10 15 21
- assertOrderedEquals(new NameUtil.MinusculeMatcher("ncldfou*ion", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
+ assertOrderedEquals(new MinusculeMatcher("ncldfou*ion", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
TextRange.from(0, 1), TextRange.from(2, 2), TextRange.from(7, 1), TextRange.from(10, 3), TextRange.from(21, 3));
sample = "doGet(HttpServletRequest, HttpServletResponse):void";
// 0 22
- assertOrderedEquals(new NameUtil.MinusculeMatcher("d*st", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
+ assertOrderedEquals(new MinusculeMatcher("d*st", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
TextRange.from(0, 1), TextRange.from(22, 2));
- assertOrderedEquals(new NameUtil.MinusculeMatcher("doge*st", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
+ assertOrderedEquals(new MinusculeMatcher("doge*st", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
TextRange.from(0, 4), TextRange.from(22, 2));
sample = "_test";
- assertOrderedEquals(new NameUtil.MinusculeMatcher("_", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
+ assertOrderedEquals(new MinusculeMatcher("_", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
TextRange.from(0, 1));
- assertOrderedEquals(new NameUtil.MinusculeMatcher("_t", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
+ assertOrderedEquals(new MinusculeMatcher("_t", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
TextRange.from(0, 2));
}
public void testMatchingFragmentsSorted() {
@NonNls String sample = "SWUPGRADEHDLRFSPR7TEST";
// 0 9 12
- assertOrderedEquals(new NameUtil.MinusculeMatcher("SWU*H*R", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
+ assertOrderedEquals(new MinusculeMatcher("SWU*H*R", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
TextRange.from(0, 3), TextRange.from(9, 1), TextRange.from(12, 1));
}
public void testPreferCapsMatching() {
String sample = "getCurrentUser";
// 0 4 10
- assertOrderedEquals(new NameUtil.MinusculeMatcher("getCU", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
+ assertOrderedEquals(new MinusculeMatcher("getCU", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample),
TextRange.from(0, 4), TextRange.from(10, 1));
}
@@ -390,7 +391,7 @@ public class NameUtilTest extends UsefulTestCase {
}
public void testMeaningfulMatchingDegree() {
- assertTrue(new NameUtil.MinusculeMatcher(" EUC-", NameUtil.MatchingCaseSensitivity.FIRST_LETTER).matchingDegree("x-EUC-TW") > Integer.MIN_VALUE);
+ assertTrue(new MinusculeMatcher(" EUC-", NameUtil.MatchingCaseSensitivity.FIRST_LETTER).matchingDegree("x-EUC-TW") > Integer.MIN_VALUE);
}
private static void assertPreference(@NonNls String pattern,
@@ -403,7 +404,7 @@ public class NameUtilTest extends UsefulTestCase {
@NonNls String less,
@NonNls String more,
NameUtil.MatchingCaseSensitivity sensitivity) {
- NameUtil.MinusculeMatcher matcher = new NameUtil.MinusculeMatcher(pattern, sensitivity);
+ MinusculeMatcher matcher = new MinusculeMatcher(pattern, sensitivity);
int iLess = matcher.matchingDegree(less);
int iMore = matcher.matchingDegree(more);
assertTrue(iLess + ">=" + iMore + "; " + less + ">=" + more, iLess < iMore);
@@ -411,24 +412,24 @@ public class NameUtilTest extends UsefulTestCase {
public void testPerformance() {
@NonNls final String longName = "ThisIsAQuiteLongNameWithParentheses().Dots.-Minuses-_UNDERSCORES_digits239:colons:/slashes\\AndOfCourseManyLetters";
- final List matching = new ArrayList();
- final List nonMatching = new ArrayList();
+ final List matching = new ArrayList();
+ final List nonMatching = new ArrayList();
for (String s : CollectionFactory.ar("*", "*i", "*a", "*u", "T", "ti", longName, longName.substring(0, 20))) {
- matching.add(new NameUtil.MinusculeMatcher(s, NameUtil.MatchingCaseSensitivity.NONE));
+ matching.add(new MinusculeMatcher(s, NameUtil.MatchingCaseSensitivity.NONE));
}
for (String s : CollectionFactory.ar("A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "ta")) {
- nonMatching.add(new NameUtil.MinusculeMatcher(s, NameUtil.MatchingCaseSensitivity.NONE));
+ nonMatching.add(new MinusculeMatcher(s, NameUtil.MatchingCaseSensitivity.NONE));
}
- PlatformTestUtil.startPerformanceTest("Matcher is slow", 1200, new ThrowableRunnable() {
+ PlatformTestUtil.startPerformanceTest("Matcher is slow", 1700, new ThrowableRunnable() {
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
- for (NameUtil.MinusculeMatcher matcher : matching) {
+ for (MinusculeMatcher matcher : matching) {
assertTrue(matcher.matches(longName));
}
- for (NameUtil.MinusculeMatcher matcher : nonMatching) {
+ for (MinusculeMatcher matcher : nonMatching) {
assertFalse(matcher.matches(longName));
}
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/HighlightTestInfo.java b/platform/testFramework/src/com/intellij/testFramework/HighlightTestInfo.java
index 9d12ebc4f484..407ae199627e 100644
--- a/platform/testFramework/src/com/intellij/testFramework/HighlightTestInfo.java
+++ b/platform/testFramework/src/com/intellij/testFramework/HighlightTestInfo.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.
@@ -36,6 +36,7 @@ public abstract class HighlightTestInfo implements Disposable {
Disposer.register(parentDisposable, this);
myPlace = parentDisposable.toString();
}
+
public HighlightTestInfo checkWarnings() { checkWarnings = true; return this; }
public HighlightTestInfo checkWeakWarnings() { checkWeakWarnings = true; return this; }
public HighlightTestInfo checkInfos() { checkInfos = true; return this; }
@@ -43,10 +44,14 @@ public abstract class HighlightTestInfo implements Disposable {
public HighlightTestInfo projectRoot(@NonNls @NotNull String root) { projectRoot = root; return this; }
public HighlightTestInfo test() throws Exception {
- doTest();
- tested = true;
- Disposer.dispose(this);
- return this;
+ try {
+ doTest();
+ return this;
+ }
+ finally {
+ tested = true;
+ Disposer.dispose(this);
+ }
}
@Override
diff --git a/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java
new file mode 100644
index 000000000000..32074ac649f6
--- /dev/null
+++ b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java
@@ -0,0 +1,296 @@
+/*
+ * 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.psi.codeStyle;
+
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.FList;
+import com.intellij.util.text.CharArrayCharSequence;
+import com.intellij.util.text.Matcher;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+
+/**
+* @author peter
+*/
+public class MinusculeMatcher implements Matcher {
+ private final char[] myPattern;
+ private final NameUtil.MatchingCaseSensitivity myOptions;
+
+ public MinusculeMatcher(String pattern, NameUtil.MatchingCaseSensitivity options) {
+ myOptions = options;
+ myPattern = StringUtil.trimEnd(pattern, "* ").replaceAll(":", "\\*:").toCharArray();
+ }
+
+ @Nullable
+ private FList matchName(String name, int patternIndex, int nameIndex) {
+ if (patternIndex == myPattern.length) {
+ return FList.emptyList();
+ }
+ if ('*' == myPattern[patternIndex]) {
+ return skipChars(name, patternIndex, nameIndex, true);
+ }
+ if (nameIndex == name.length()) {
+ return null;
+ }
+
+ if ('.' == myPattern[patternIndex] && name.charAt(nameIndex) != '.') {
+ return skipChars(name, patternIndex, nameIndex, false);
+ }
+
+ if (' ' == myPattern[patternIndex] && patternIndex != myPattern.length - 1) {
+ return skipWords(name, patternIndex, nameIndex);
+ }
+
+ if ((patternIndex == 0 || patternIndex == 1 && myPattern[0] == ' ' && nameIndex == 0) &&
+ myOptions != NameUtil.MatchingCaseSensitivity.NONE && name.charAt(nameIndex) != myPattern[patternIndex]) {
+ return null;
+ }
+
+ if (NameUtil.isWordSeparator(name.charAt(nameIndex))) {
+ return skipSeparators(name, patternIndex, nameIndex);
+ }
+
+ if (StringUtil.toLowerCase(name.charAt(nameIndex)) != StringUtil.toLowerCase(myPattern[patternIndex])) {
+ if (Character.isDigit(name.charAt(nameIndex)) && nameIndex > 0 || (name.charAt(nameIndex) == '.' && name.indexOf('.', nameIndex + 1) > 0)) {
+ return matchName(name, patternIndex, nameIndex + 1);
+ }
+ return null;
+ }
+
+ if (myOptions == NameUtil.MatchingCaseSensitivity.ALL && name.charAt(nameIndex) != myPattern[patternIndex]) {
+ return null;
+ }
+
+ int nextStart = NameUtil.nextWord(name, nameIndex);
+
+ int lastUpper = NameUtil.isWordStart(myPattern[patternIndex]) ? 0 : -1;
+
+ int i = 1;
+ while (true) {
+ if (patternIndex + i == myPattern.length || i + nameIndex == nextStart) {
+ break;
+ }
+ char p = myPattern[patternIndex + i];
+ char w = name.charAt(i + nameIndex);
+ if (lastUpper == i - 1 && NameUtil.isWordStart(p) && myOptions != NameUtil.MatchingCaseSensitivity.ALL) {
+ if (p == w) {
+ lastUpper = i;
+ }
+ p = StringUtil.toLowerCase(p);
+ }
+
+ if (myOptions != NameUtil.MatchingCaseSensitivity.ALL) {
+ w = StringUtil.toLowerCase(w);
+ }
+ if (w != p) {
+ break;
+ }
+ i++;
+ }
+
+ if (isFinalSpaceMatch(name, patternIndex, nameIndex, nextStart, i)) {
+ return FList.emptyList().prepend(TextRange.from(nameIndex, i));
+ }
+
+ return matchAfterFragment(name, patternIndex, nameIndex, nextStart, lastUpper, i);
+ }
+
+ private boolean isFinalSpaceMatch(String name, int patternIndex, int nameIndex, int nextStart, int i) {
+ return nextStart == name.length() &&
+ patternIndex + i == myPattern.length - 1 &&
+ ' ' == myPattern[patternIndex + i] &&
+ (i == 1 && NameUtil.isWordStart(myPattern[patternIndex]) || i + nameIndex == name.length());
+ }
+
+ @Nullable
+ private FList matchAfterFragment(String name, int patternIndex, int nameIndex, int nextStart, int lastUpper, int matchLen) {
+ boolean star = patternIndex + matchLen < myPattern.length && myPattern[patternIndex + matchLen] == '*';
+ if (lastUpper >= 0) {
+ FList ranges = matchName(name, patternIndex + lastUpper + 1, star && matchLen == lastUpper ? nameIndex + lastUpper : nextStart);
+ if (ranges != null) {
+ return prependRange(ranges, nameIndex, lastUpper + 1);
+ }
+ }
+
+ int trial = matchLen;
+ while (trial > 0) {
+ FList ranges = matchName(name, patternIndex + trial, nextStart);
+ if (ranges != null) {
+ return prependRange(ranges, nameIndex, trial);
+ }
+ trial--;
+ }
+
+ FList ranges = matchName(name, patternIndex + matchLen, nameIndex + matchLen);
+ if (ranges != null) {
+ return prependRange(ranges, nameIndex, matchLen);
+ }
+ return null;
+ }
+
+ private static FList prependRange(FList ranges, int from, int length) {
+ TextRange head = ranges.getHead();
+ if (head != null && head.getStartOffset() == from + length) {
+ return ranges.getTail().prepend(new TextRange(from, head.getEndOffset()));
+ }
+ return ranges.prepend(TextRange.from(from, length));
+ }
+
+ @Nullable
+ private FList skipSeparators(String name, int patternIndex, int nameIndex) {
+ int nextStart = NameUtil.nextWord(name, nameIndex);
+ assert nextStart - nameIndex == 1 : "'" + name + "'" + nameIndex + " " + nextStart;
+ char p = myPattern[patternIndex];
+ if (NameUtil.isWordSeparator(p)) {
+ if (myOptions != NameUtil.MatchingCaseSensitivity.NONE &&
+ nameIndex == 0 && name.length() > 1 && patternIndex + 1 < myPattern.length &&
+ NameUtil.isWordSeparator(name.charAt(1)) && !NameUtil.isWordSeparator(myPattern[patternIndex + 1])) {
+ return null;
+ }
+
+ final FList ranges = matchName(name, patternIndex + 1, nextStart);
+ if (ranges != null) {
+ return prependRange(ranges, nameIndex, 1);
+ }
+
+ return null;
+ }
+
+ return matchName(name, patternIndex, nextStart);
+ }
+
+ @Nullable
+ private FList skipChars(String name, int patternIndex, int nameIndex, boolean maySkipNextChar) {
+ while ('*' == myPattern[patternIndex]) {
+ patternIndex++;
+ if (patternIndex == myPattern.length) {
+ return FList.emptyList();
+ }
+ }
+
+ String nextChar = String.valueOf(myPattern[patternIndex]);
+ boolean upper = Character.isUpperCase(myPattern[patternIndex]);
+
+ int fromIndex = nameIndex;
+ while (true) {
+ int next = StringUtil.indexOfIgnoreCase(name, nextChar, fromIndex);
+ if (next < 0) {
+ break;
+ }
+ if (upper && next > 0 && !Character.isUpperCase(name.charAt(next))) {
+ fromIndex = next + 1;
+ continue;
+ }
+
+ FList ranges = matchName(name, patternIndex, next);
+ if (ranges != null) {
+ return ranges;
+ }
+ if (!maySkipNextChar) {
+ return null;
+ }
+ fromIndex = next + 1;
+ }
+ return null;
+ }
+
+ @Nullable
+ private FList skipWords(String name, int patternIndex, int nameIndex) {
+ while (' ' == myPattern[patternIndex]) {
+ patternIndex++;
+ if (patternIndex == myPattern.length) {
+ return null;
+ }
+ }
+
+ if (nameIndex == 0 || NameUtil.isWordStart(name, nameIndex)) {
+ FList ranges = matchName(name, patternIndex, nameIndex);
+ if (ranges != null) {
+ return ranges;
+ }
+ }
+
+ boolean separatorInPattern = NameUtil.isWordSeparator(myPattern[patternIndex]);
+ int fromIndex = nameIndex;
+ while (fromIndex < name.length()) {
+ int next = separatorInPattern ? name.indexOf(myPattern[patternIndex], fromIndex) : NameUtil.nextWord(name, fromIndex);
+ if (next < 0) {
+ break;
+ }
+
+ FList ranges = matchName(name, patternIndex, next);
+ if (ranges != null) {
+ return ranges;
+ }
+ fromIndex = next;
+ if (separatorInPattern) {
+ fromIndex++;
+ }
+ }
+ return null;
+ }
+
+ public int matchingDegree(String name) {
+ Iterable iterable = matchingFragments(name);
+ if (iterable == null) return Integer.MIN_VALUE;
+
+ int fragmentCount = 0;
+ int matchingCase = 0;
+ CharArrayCharSequence seq = new CharArrayCharSequence(myPattern);
+ int p = -1;
+ TextRange first = null;
+ for (TextRange range : iterable) {
+ if (first == null) {
+ first = range;
+ }
+ for (int i = range.getStartOffset(); i < range.getEndOffset(); i++) {
+ char c = name.charAt(i);
+ p = StringUtil.indexOf(seq, c, p + 1, myPattern.length, false);
+ if (p < 0) {
+ break;
+ }
+ matchingCase += c == myPattern[p] ? 1 : 0;
+ }
+ fragmentCount++;
+ }
+
+ int commonStart = 0;
+ while (commonStart < name.length() && commonStart < myPattern.length && name.charAt(commonStart) == myPattern[commonStart]) {
+ commonStart++;
+ }
+
+ boolean prefixMatching = first != null && first.getStartOffset() == 0;
+ boolean middleWordStart = first != null && first.getStartOffset() > 0 && NameUtil.isWordStart(name, first.getStartOffset());
+
+ return -fragmentCount + matchingCase * 10 + commonStart + (prefixMatching ? 2 : middleWordStart ? 1 : 0) * 100;
+ }
+
+ @Override
+ public boolean matches(String name) {
+ return matchingFragments(name) != null;
+ }
+
+ @Nullable
+ public Iterable matchingFragments(String name) {
+ if (name.isEmpty()) {
+ return myPattern.length == 0 ? Collections.emptyList() : null;
+ }
+
+ return matchName(name, 0, 0);
+ }
+}
diff --git a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java
index 1fd815e56922..5725e6460a48 100644
--- a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java
+++ b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java
@@ -15,20 +15,15 @@
*/
package com.intellij.psi.codeStyle;
-import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.util.text.StringUtilRt;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.containers.FList;
-import com.intellij.util.text.CharArrayCharSequence;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
public class NameUtil {
@@ -331,24 +326,24 @@ public class NameUtil {
return suggestion;
}
- private static boolean isWordStart(String text, int i) {
+ static boolean isWordStart(String text, int i) {
if (isWordStart(text.charAt(i))) {
return true;
}
if (!Character.isLetterOrDigit(text.charAt(i))) {
return false;
}
- if (i > 0 && (MinusculeMatcher.isWordSeparator(text.charAt(i - 1)) || text.charAt(i - 1) == '.')) {
+ if (i > 0 && (isWordSeparator(text.charAt(i - 1)) || text.charAt(i - 1) == '.')) {
return true;
}
return false;
}
- private static boolean isWordStart(char p) {
+ static boolean isWordStart(char p) {
return Character.isUpperCase(p) || Character.isDigit(p);
}
- private static int nextWord(String text, int start) {
+ static int nextWord(String text, int start) {
if (!Character.isLetterOrDigit(text.charAt(start))) {
return start + 1;
}
@@ -378,6 +373,10 @@ public class NameUtil {
}
}
+ static boolean isWordSeparator(char c) {
+ return Character.isWhitespace(c) || c == '_' || c == '-' || c == ':';
+ }
+
/**
* @deprecated use com.intellij.util.text.Matcher
*/
@@ -409,276 +408,4 @@ public class NameUtil {
public enum MatchingCaseSensitivity {
NONE, FIRST_LETTER, ALL
}
-
- public static class MinusculeMatcher implements com.intellij.util.text.Matcher {
- private final char[] myPattern;
- private final MatchingCaseSensitivity myOptions;
-
- public MinusculeMatcher(String pattern, MatchingCaseSensitivity options) {
- myOptions = options;
- myPattern = StringUtil.trimEnd(pattern, "* ").replaceAll(":", "\\*:").toCharArray();
- }
-
- @Nullable
- private FList matchName(String name, int patternIndex, int nameIndex) {
- if (patternIndex == myPattern.length) {
- return FList.emptyList();
- }
- if ('*' == myPattern[patternIndex]) {
- return skipChars(name, patternIndex, nameIndex, true);
- }
- if (nameIndex == name.length()) {
- return null;
- }
-
- if ('.' == myPattern[patternIndex] && name.charAt(nameIndex) != '.') {
- return skipChars(name, patternIndex, nameIndex, false);
- }
-
- if (' ' == myPattern[patternIndex] && patternIndex != myPattern.length - 1) {
- return skipWords(name, patternIndex, nameIndex);
- }
-
- if ((patternIndex == 0 || patternIndex == 1 && myPattern[0] == ' ' && nameIndex == 0) &&
- myOptions != MatchingCaseSensitivity.NONE && name.charAt(nameIndex) != myPattern[patternIndex]) {
- return null;
- }
-
- if (isWordSeparator(name.charAt(nameIndex))) {
- return skipSeparators(name, patternIndex, nameIndex);
- }
-
- if (StringUtil.toLowerCase(name.charAt(nameIndex)) != StringUtil.toLowerCase(myPattern[patternIndex])) {
- if (Character.isDigit(name.charAt(nameIndex)) && nameIndex > 0 || (name.charAt(nameIndex) == '.' && name.indexOf('.', nameIndex + 1) > 0)) {
- return matchName(name, patternIndex, nameIndex + 1);
- }
- return null;
- }
-
- if (myOptions == MatchingCaseSensitivity.ALL && name.charAt(nameIndex) != myPattern[patternIndex]) {
- return null;
- }
-
- int nextStart = NameUtil.nextWord(name, nameIndex);
-
- int lastUpper = isWordStart(myPattern[patternIndex]) ? 0 : -1;
-
- int i = 1;
- while (true) {
- if (patternIndex + i == myPattern.length || i + nameIndex == nextStart) {
- break;
- }
- char p = myPattern[patternIndex + i];
- char w = name.charAt(i + nameIndex);
- if (lastUpper == i - 1 && isWordStart(p) && myOptions != MatchingCaseSensitivity.ALL) {
- if (p == w) {
- lastUpper = i;
- }
- p = StringUtil.toLowerCase(p);
- }
-
- if (myOptions != MatchingCaseSensitivity.ALL) {
- w = StringUtil.toLowerCase(w);
- }
- if (w != p) {
- break;
- }
- i++;
- }
-
- if (isFinalSpaceMatch(name, patternIndex, nameIndex, nextStart, i)) {
- return FList.emptyList().prepend(TextRange.from(nameIndex, i));
- }
-
- return matchAfterFragment(name, patternIndex, nameIndex, nextStart, lastUpper, i);
- }
-
- private boolean isFinalSpaceMatch(String name, int patternIndex, int nameIndex, int nextStart, int i) {
- return nextStart == name.length() &&
- patternIndex + i == myPattern.length - 1 &&
- ' ' == myPattern[patternIndex + i] &&
- (i == 1 && isWordStart(myPattern[patternIndex]) || i + nameIndex == name.length());
- }
-
- @Nullable
- private FList matchAfterFragment(String name, int patternIndex, int nameIndex, int nextStart, int lastUpper, int matchLen) {
- boolean star = patternIndex + matchLen < myPattern.length && myPattern[patternIndex + matchLen] == '*';
- if (lastUpper >= 0) {
- FList ranges = matchName(name, patternIndex + lastUpper + 1, star && matchLen == lastUpper ? nameIndex + lastUpper : nextStart);
- if (ranges != null) {
- return prependRange(ranges, nameIndex, lastUpper + 1);
- }
- }
-
- int trial = matchLen;
- while (trial > 0) {
- FList ranges = matchName(name, patternIndex + trial, nextStart);
- if (ranges != null) {
- return prependRange(ranges, nameIndex, trial);
- }
- trial--;
- }
-
- FList ranges = matchName(name, patternIndex + matchLen, nameIndex + matchLen);
- if (ranges != null) {
- return prependRange(ranges, nameIndex, matchLen);
- }
- return null;
- }
-
- private static FList prependRange(FList ranges, int from, int length) {
- TextRange head = ranges.getHead();
- if (head != null && head.getStartOffset() == from + length) {
- return ranges.getTail().prepend(new TextRange(from, head.getEndOffset()));
- }
- return ranges.prepend(TextRange.from(from, length));
- }
-
- private static boolean isWordSeparator(char c) {
- return Character.isWhitespace(c) || c == '_' || c == '-' || c == ':';
- }
-
- @Nullable
- private FList skipSeparators(String name, int patternIndex, int nameIndex) {
- int nextStart = NameUtil.nextWord(name, nameIndex);
- assert nextStart - nameIndex == 1 : "'" + name + "'" + nameIndex + " " + nextStart;
- char p = myPattern[patternIndex];
- if (isWordSeparator(p)) {
- if (myOptions != MatchingCaseSensitivity.NONE &&
- nameIndex == 0 && name.length() > 1 && patternIndex + 1 < myPattern.length &&
- isWordSeparator(name.charAt(1)) && !isWordSeparator(myPattern[patternIndex + 1])) {
- return null;
- }
-
- final FList ranges = matchName(name, patternIndex + 1, nextStart);
- if (ranges != null) {
- return prependRange(ranges, nameIndex, 1);
- }
-
- return null;
- }
-
- return matchName(name, patternIndex, nextStart);
- }
-
- @Nullable
- private FList skipChars(String name, int patternIndex, int nameIndex, boolean maySkipNextChar) {
- while ('*' == myPattern[patternIndex]) {
- patternIndex++;
- if (patternIndex == myPattern.length) {
- return FList.emptyList();
- }
- }
-
- String nextChar = String.valueOf(myPattern[patternIndex]);
- boolean upper = Character.isUpperCase(myPattern[patternIndex]);
-
- int fromIndex = nameIndex;
- while (true) {
- int next = StringUtil.indexOfIgnoreCase(name, nextChar, fromIndex);
- if (next < 0) {
- break;
- }
- if (upper && next > 0 && !Character.isUpperCase(name.charAt(next))) {
- fromIndex = next + 1;
- continue;
- }
-
- FList ranges = matchName(name, patternIndex, next);
- if (ranges != null) {
- return ranges;
- }
- if (!maySkipNextChar) {
- return null;
- }
- fromIndex = next + 1;
- }
- return null;
- }
-
- @Nullable
- private FList skipWords(String name, int patternIndex, int nameIndex) {
- while (' ' == myPattern[patternIndex]) {
- patternIndex++;
- if (patternIndex == myPattern.length) {
- return null;
- }
- }
-
- if (nameIndex == 0 || isWordStart(name, nameIndex)) {
- FList ranges = matchName(name, patternIndex, nameIndex);
- if (ranges != null) {
- return ranges;
- }
- }
-
- boolean separatorInPattern = isWordSeparator(myPattern[patternIndex]);
- int fromIndex = nameIndex;
- while (fromIndex < name.length()) {
- int next = separatorInPattern ? name.indexOf(myPattern[patternIndex], fromIndex) : nextWord(name, fromIndex);
- if (next < 0) {
- break;
- }
-
- FList ranges = matchName(name, patternIndex, next);
- if (ranges != null) {
- return ranges;
- }
- fromIndex = next;
- if (separatorInPattern) {
- fromIndex++;
- }
- }
- return null;
- }
-
- public int matchingDegree(String name) {
- Iterable iterable = matchingFragments(name);
- if (iterable == null) return Integer.MIN_VALUE;
-
- int fragmentCount = 0;
- int matchingCase = 0;
- CharArrayCharSequence seq = new CharArrayCharSequence(myPattern);
- int p = -1;
- TextRange first = null;
- for (TextRange range : iterable) {
- if (first == null) {
- first = range;
- }
- for (int i = range.getStartOffset(); i < range.getEndOffset(); i++) {
- char c = name.charAt(i);
- p = StringUtil.indexOf(seq, c, p + 1, myPattern.length, false);
- if (p < 0) {
- break;
- }
- matchingCase += c == myPattern[p] ? 1 : 0;
- }
- fragmentCount++;
- }
-
- int commonStart = 0;
- while (commonStart < name.length() && commonStart < myPattern.length && name.charAt(commonStart) == myPattern[commonStart]) {
- commonStart++;
- }
-
- boolean prefixMatching = first != null && first.getStartOffset() == 0;
- boolean middleWordStart = first != null && first.getStartOffset() > 0 && isWordStart(name, first.getStartOffset());
-
- return -fragmentCount + matchingCase * 10 + commonStart + (prefixMatching ? 2 : middleWordStart ? 1 : 0) * 100;
- }
-
- @Override
- public boolean matches(String name) {
- return matchingFragments(name) != null;
- }
-
- @Nullable
- public Iterable matchingFragments(String name) {
- if (name.isEmpty()) {
- return myPattern.length == 0 ? Collections.emptyList() : null;
- }
-
- return matchName(name, 0, 0);
- }
- }
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsConfirmationDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsConfirmationDialog.java
index 149c6c9cb089..202e15ad9d72 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsConfirmationDialog.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsConfirmationDialog.java
@@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.changes;
import com.intellij.CommonBundle;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vcs.VcsShowConfirmationOption;
import com.intellij.util.ui.OptionsDialog;
@@ -73,18 +74,20 @@ public class VcsConfirmationDialog extends OptionsDialog {
@Override
protected Action[] createActions() {
- return new Action[] {
- new AbstractAction(CommonBundle.getYesButtonText()) {
- {
- putValue(DEFAULT_ACTION, Boolean.TRUE);
- }
- public void actionPerformed(ActionEvent e) {
- doOKAction();
- }
- }, new AbstractAction(CommonBundle.getNoButtonText()) {
- public void actionPerformed(ActionEvent e) {
- doCancelAction();
- }
- }};
+ final AbstractAction okAction = new AbstractAction(CommonBundle.getYesButtonText()) {
+ {
+ putValue(DEFAULT_ACTION, Boolean.TRUE);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ doOKAction();
+ }
+ };
+ final AbstractAction cancelAction = new AbstractAction(CommonBundle.getNoButtonText()) {
+ public void actionPerformed(ActionEvent e) {
+ doCancelAction();
+ }
+ };
+ return SystemInfo.isMac ? new Action[] {cancelAction, okAction} : new Action[] {okAction, cancelAction};
}
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java
index 3bbaed4fbef4..af08b7c08ae5 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
@@ -1023,7 +1024,7 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
new Task.Backgroundable(project, VcsBundle.message("show.diff.progress.title")) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
- LocalHistoryAction action = file != null ? startLocalHistoryAction(revision) : LocalHistoryAction.NULL;
+ final LocalHistoryAction action = file != null ? startLocalHistoryAction(revision) : LocalHistoryAction.NULL;
final byte[] revisionContent;
try {
revisionContent = VcsHistoryUtil.loadRevisionContent(revision);
@@ -1049,39 +1050,37 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
return;
}
- try {
- UIUtil.invokeAndWaitIfNeeded(new Runnable() {
- @Override public void run() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- public void run() {
- CommandProcessor.getInstance().executeCommand(project, new Runnable() {
- public void run() {
- if (file != null && !file.isWritable()) {
- if (ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(file).hasReadonlyFiles()) {
- return;
- }
- }
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ new WriteCommandAction.Simple(project) {
+ @Override
+ protected void run() throws Throwable {
+ if (file != null &&
+ !file.isWritable() &&
+ ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(file).hasReadonlyFiles()) {
+ return;
+ }
- try {
- write(revisionContent);
- } catch (IOException e) {
- Messages.showMessageDialog(VcsBundle.message("message.text.cannot.save.content", e.getLocalizedMessage()),
- VcsBundle.message( "message.title.get.revision.content"), Messages.getErrorIcon());
- }
- }
- }, createGetActionTitle(revision), null);
+ try {
+ write(revisionContent);
+ }
+ catch (IOException e) {
+ Messages.showMessageDialog(VcsBundle.message("message.text.cannot.save.content", e.getLocalizedMessage()),
+ VcsBundle.message("message.title.get.revision.content"), Messages.getErrorIcon());
+ }
}
- });
+ }.execute();
+ if (file != null) {
+ VcsDirtyScopeManager.getInstance(project).fileDirty(file);
+ }
+ }
+ finally {
+ action.finish();
}
- });
-
- if (file != null) {
- VcsDirtyScopeManager.getInstance(project).fileDirty(file);
}
- }
- finally {
- action.finish();
- }
+ });
}
}.queue();
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/AbstractCommonUpdateAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/AbstractCommonUpdateAction.java
index 2e8d8380f5e7..d0a300d97200 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/AbstractCommonUpdateAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/AbstractCommonUpdateAction.java
@@ -49,7 +49,6 @@ import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.WaitForProgressToShow;
-import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.OptionsDialog;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NonNls;
@@ -581,19 +580,14 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
updateInfoTree.setBefore(myBefore);
updateInfoTree.setAfter(myAfter);
- // todo make temporal listener of changes reload
- if (updateInfoTree != null) {
- updateInfoTree.setCanGroupByChangeList(canGroupByChangelist(myVcsToVirtualFiles.keySet()));
- final MessageBusConnection messageBusConnection = myProject.getMessageBus().connect();
- messageBusConnection.subscribe(CommittedChangesCache.COMMITTED_TOPIC, new CommittedChangesAdapter() {
- public void incomingChangesUpdated(final List receivedChanges) {
- if (receivedChanges != null) {
- updateInfoTree.setChangeLists(receivedChanges);
- messageBusConnection.disconnect();
- }
+ updateInfoTree.setCanGroupByChangeList(canGroupByChangelist(myVcsToVirtualFiles.keySet()));
+ myProject.getMessageBus().connect(updateInfoTree).subscribe(CommittedChangesCache.COMMITTED_TOPIC, new CommittedChangesAdapter() {
+ public void incomingChangesUpdated(final List receivedChanges) {
+ if (receivedChanges != null) {
+ updateInfoTree.setChangeLists(receivedChanges);
}
- });
- }
+ }
+ });
}
public void onCancel() {
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/ByteOpAssign.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/ByteOpAssign.java
new file mode 100644
index 000000000000..ca45c9670725
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/ByteOpAssign.java
@@ -0,0 +1,23 @@
+/*
+ * 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.siyeh.ipp.opassign.assignment;
+
+class ByteOpassign {
+
+ void foo(byte b) {
+ b += 1;
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/ByteOpAssign_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/ByteOpAssign_after.java
new file mode 100644
index 000000000000..af4441527704
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/ByteOpAssign_after.java
@@ -0,0 +1,23 @@
+/*
+ * 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.siyeh.ipp.opassign.assignment;
+
+class ByteOpassign {
+
+ void foo(byte b) {
+ b = (byte) (b + 1);
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/ByteOpassign.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/ByteOpassign.java
deleted file mode 100644
index ce6c0daca40f..000000000000
--- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/ByteOpassign.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.siyeh.ipp.opassign.assignment;
-
-class ByteOpassign {
-
- void foo(byte b) {
- b += 1;
- }
-}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/ByteOpassign_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/ByteOpassign_after.java
deleted file mode 100644
index e4daf05d38e4..000000000000
--- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/ByteOpassign_after.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.siyeh.ipp.opassign.assignment;
-
-class ByteOpassign {
-
- void foo(byte b) {
- b = (byte) (b + 1);
- }
-}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/DoubleOpAssign.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/DoubleOpAssign.java
new file mode 100644
index 000000000000..2e8a0e5ba7a5
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/DoubleOpAssign.java
@@ -0,0 +1,23 @@
+/*
+ * 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.siyeh.ipp.opassign.assignment;
+
+class DoubleOpassign {
+
+ void foo(double d) {
+ d += 0.5;
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/DoubleOpAssign_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/DoubleOpAssign_after.java
new file mode 100644
index 000000000000..fe005f3c66d2
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/DoubleOpAssign_after.java
@@ -0,0 +1,23 @@
+/*
+ * 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.siyeh.ipp.opassign.assignment;
+
+class DoubleOpassign {
+
+ void foo(double d) {
+ d = d + 0.5;
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/DoubleOpassign.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/DoubleOpassign.java
deleted file mode 100644
index fb159c964e3b..000000000000
--- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/DoubleOpassign.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.siyeh.ipp.opassign.assignment;
-
-class DoubleOpassign {
-
- void foo(double d) {
- d += 0.5;
- }
-}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/DoubleOpassign_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/DoubleOpassign_after.java
deleted file mode 100644
index fabb55a2a1c3..000000000000
--- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/DoubleOpassign_after.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.siyeh.ipp.opassign.assignment;
-
-class DoubleOpassign {
-
- void foo(double d) {
- d = d + 0.5;
- }
-}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/StringOpAssign_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/StringOpAssign_after.java
new file mode 100644
index 000000000000..feab030b8d20
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/StringOpAssign_after.java
@@ -0,0 +1,23 @@
+/*
+ * 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.siyeh.ipp.opassign.assignment;
+
+class StringOpassign {
+
+ void foo(String s) {
+ s = s + 1.0;
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/StringOpassign_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/StringOpassign_after.java
deleted file mode 100644
index 5457c890258b..000000000000
--- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/StringOpassign_after.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.siyeh.ipp.opassign.assignment;
-
-class StringOpassign {
-
- void foo(String s) {
- s = s + 1.0;
- }
-}
\ No newline at end of file
diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidFacet.groovy b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidFacet.groovy
index d7d04ba87dab..7f9d3dddb6a9 100644
--- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidFacet.groovy
+++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidFacet.groovy
@@ -92,7 +92,7 @@ class AndroidFacet extends Facet {
}
if (lookInContentRoot) {
- module.contentRoots.each {String contentRoot ->
+ for (String contentRoot in module.contentRoots) {
def absPath = FileUtil.toSystemIndependentName(contentRoot + relativePath)
def f = new File(absPath)
diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java
index c982ef16a5ae..265845566c92 100644
--- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java
+++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java
@@ -584,6 +584,7 @@ public class AndroidSourceGeneratingBuilder extends ModuleLevelBuilder {
if (!FileUtil.moveDirWithContent(tmpOutputDir, aptOutputDirectory)) {
context.processMessage(new CompilerMessage(ANDROID_APT_COMPILER, BuildMessage.Kind.ERROR, AndroidJpsBundle
.message("android.jps.errors.cannot.move.content", tmpOutputDir.getPath(), aptOutputDirectory.getPath())));
+ success = false;
continue;
}
markDirtyRecursively(aptOutputDirectory, context, ANDROID_APT_COMPILER);
diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java
index 350ba76c09e4..254d6b90beb2 100644
--- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java
+++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java
@@ -27,7 +27,6 @@ import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
-import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import org.jdom.Element;
@@ -97,15 +96,10 @@ public class AndroidFacetConfiguration implements FacetConfiguration {
}
public void init(@NotNull Module module, @NotNull String baseDirectoryPath) {
- String moduleDirPath = AndroidRootUtil.getModuleDirPath(module);
- if (moduleDirPath == null) {
+ final String s = AndroidRootUtil.getPathRelativeToModuleDir(module, baseDirectoryPath);
+ if (s == null || s.length() == 0) {
return;
}
- if (moduleDirPath.equals(baseDirectoryPath)) {
- return;
- }
-
- String s = FileUtil.getRelativePath(moduleDirPath, baseDirectoryPath, '/');
GEN_FOLDER_RELATIVE_PATH_APT = '/' + s + GEN_FOLDER_RELATIVE_PATH_APT;
GEN_FOLDER_RELATIVE_PATH_AIDL = '/' + s + GEN_FOLDER_RELATIVE_PATH_AIDL;
diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java b/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java
index c24eed85f9a6..6eeb95037884 100644
--- a/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java
+++ b/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java
@@ -514,4 +514,16 @@ public class AndroidRootUtil {
String moduleDirPath = getModuleDirPath(facet.getModule());
return moduleDirPath != null ? FileUtil.toSystemDependentName(moduleDirPath + path) : null;
}
+
+ @Nullable
+ public static String getPathRelativeToModuleDir(@NotNull Module module, @NotNull String path) {
+ String moduleDirPath = getModuleDirPath(module);
+ if (moduleDirPath == null) {
+ return null;
+ }
+ if (moduleDirPath.equals(path)) {
+ return "";
+ }
+ return FileUtil.getRelativePath(moduleDirPath, path, '/');
+ }
}
diff --git a/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java b/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java
index 2eaa9968d45e..7aa809d188e1 100644
--- a/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java
+++ b/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java
@@ -389,9 +389,13 @@ public abstract class AndroidFacetImporterBase extends FacetImporter 0 ? '/' + s + '/' : "/";
+ configuration.RES_FOLDER_RELATIVE_PATH = s + AndroidMavenUtil.APK_LIB_ARTIFACT_RES_DIR;
+ configuration.LIBS_FOLDER_RELATIVE_PATH = s + AndroidMavenUtil.APK_LIB_ARTIFACT_NATIVE_LIBS_DIR;
+ configuration.MANIFEST_FILE_RELATIVE_PATH = s + AndroidMavenUtil.APK_LIB_ARTIFACT_MANIFEST_FILE;
+ }
importSdkAndDependenciesForApklibArtifact(project, rootModelAdapter, apklibModuleModel, modelsProvider, mavenTree, artifact,
mavenProject2ModuleName);
diff --git a/plugins/devkit/src/dom/impl/IdeaPluginImpl.java b/plugins/devkit/src/dom/impl/IdeaPluginImpl.java
index 198bcd3eb31a..bb213490e9c2 100644
--- a/plugins/devkit/src/dom/impl/IdeaPluginImpl.java
+++ b/plugins/devkit/src/dom/impl/IdeaPluginImpl.java
@@ -26,6 +26,10 @@ import org.jetbrains.idea.devkit.dom.IdeaPlugin;
public abstract class IdeaPluginImpl implements IdeaPlugin {
public String getPluginId() {
final XmlTag tag = getXmlTag();
+ if (tag == null) {
+ return null;
+ }
+
final XmlTag idTag = tag.findFirstSubTag("id");
if (idTag != null) {
return idTag.getValue().getTrimmedText();
diff --git a/plugins/git4idea/src/git4idea/GitUtil.java b/plugins/git4idea/src/git4idea/GitUtil.java
index 41db3cd4f414..4c4879a483ab 100644
--- a/plugins/git4idea/src/git4idea/GitUtil.java
+++ b/plugins/git4idea/src/git4idea/GitUtil.java
@@ -298,6 +298,9 @@ public class GitUtil {
* @return git root for the file
* @throws IllegalArgumentException if the file is not under git
* @throws VcsException if the file is not under git
+ *
+ * @deprecated because uses the java.io.File.
+ * @use GitRepositoryManager#getRepositoryForFile().
*/
public static VirtualFile getGitRoot(final FilePath filePath) throws VcsException {
VirtualFile root = getGitRootOrNull(filePath);
@@ -312,7 +315,11 @@ public class GitUtil {
*
* @param filePath a file path
* @return git root for the file or null if the file is not under git
+ *
+ * @deprecated because uses the java.io.File.
+ * @use GitRepositoryManager#getRepositoryForFile().
*/
+ @Deprecated
@Nullable
public static VirtualFile getGitRootOrNull(final FilePath filePath) {
return getGitRootOrNull(filePath.getIOFile());
@@ -322,6 +329,11 @@ public class GitUtil {
return file != null && file.exists() && file.isDirectory() && new File(file, DOT_GIT).exists();
}
+ /**
+ * @deprecated because uses the java.io.File.
+ * @use GitRepositoryManager#getRepositoryForFile().
+ */
+ @Deprecated
@Nullable
public static VirtualFile getGitRootOrNull(final File file) {
File root = file;
@@ -337,6 +349,9 @@ public class GitUtil {
* @param file the file to check
* @return git root for the file
* @throws VcsException if the file is not under git
+ *
+ * @deprecated because uses the java.io.File.
+ * @use GitRepositoryManager#getRepositoryForFile().
*/
public static VirtualFile getGitRoot(@NotNull final VirtualFile file) throws VcsException {
final VirtualFile root = gitRootOrNull(file);
@@ -353,6 +368,9 @@ public class GitUtil {
*
* @param file the file to check
* @return git root for the file or null if the file is not not under Git
+ *
+ * @deprecated because uses the java.io.File.
+ * @use GitRepositoryManager#getRepositoryForFile().
*/
@Nullable
public static VirtualFile gitRootOrNull(final VirtualFile file) {
@@ -376,6 +394,9 @@ public class GitUtil {
* @param project the project
* @param vcs the git Vcs
* @return the list of the roots
+ *
+ * @deprecated because uses the java.io.File.
+ * @use GitRepositoryManager#getRepositoryForFile().
*/
@NotNull
public static List getGitRoots(Project project, GitVcs vcs) throws VcsException {
diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java
index e0ee250f464e..c8129a70249f 100644
--- a/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java
+++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
+import com.intellij.openapi.vcs.VcsRoot;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import git4idea.GitUtil;
@@ -97,9 +98,13 @@ public class GitRepositoryManagerImpl extends AbstractProjectComponent implement
@Override
@Nullable
public GitRepository getRepositoryForFile(@NotNull VirtualFile file) {
- final VirtualFile vcsRoot = myVcsManager.getVcsRootFor(file);
+ final VcsRoot vcsRoot = myVcsManager.getVcsRootObjectFor(file);
if (vcsRoot == null) { return null; }
- return getRepositoryForRoot(vcsRoot);
+ if (!myVcs.equals(vcsRoot.vcs)) {
+ LOG.info(String.format("getRepositoryForFile returned non-Git (%s) root for file %s", vcsRoot.vcs.getDisplayName(), file));
+ return null;
+ }
+ return getRepositoryForRoot(vcsRoot.path);
}
@Override
diff --git a/plugins/git4idea/src/git4idea/status/GitChangeProvider.java b/plugins/git4idea/src/git4idea/status/GitChangeProvider.java
index ab5754660478..94b3e69e7e47 100644
--- a/plugins/git4idea/src/git4idea/status/GitChangeProvider.java
+++ b/plugins/git4idea/src/git4idea/status/GitChangeProvider.java
@@ -62,6 +62,11 @@ public class GitChangeProvider implements ChangeProvider {
final ChangelistBuilder builder,
final ProgressIndicator progress,
final ChangeListManagerGate addGate) throws VcsException {
+ final GitVcs vcs = GitVcs.getInstance(myProject);
+ if (vcs == null) {
+ // already disposed or not yet initialized => ignoring
+ return;
+ }
final Collection affected = dirtyScope.getAffectedContentRootsWithCheck();
if (dirtyScope.getAffectedContentRoots().size() != affected.size()) {
@@ -78,8 +83,10 @@ public class GitChangeProvider implements ChangeProvider {
myFileDocumentManager, myVcsManager);
for (VirtualFile root : roots) {
GitChangesCollector collector = isNewGitChangeProviderAvailable()
- ? GitNewChangesCollector.collect(myProject, myGit, myChangeListManager, dirtyScope, root)
- : GitOldChangesCollector.collect(myProject, myChangeListManager, dirtyScope, root);
+ ? GitNewChangesCollector.collect(myProject, myGit, myChangeListManager, myVcsManager,
+ vcs, dirtyScope, root)
+ : GitOldChangesCollector.collect(myProject, myChangeListManager, myVcsManager,
+ vcs, dirtyScope, root);
holder.changed(collector.getChanges());
for (Change file : collector.getChanges()) {
builder.processChange(file, GitVcs.getKey());
@@ -90,11 +97,10 @@ public class GitChangeProvider implements ChangeProvider {
}
holder.feedBuilder(builder);
}
- } catch (VcsException e) {// most probably the error happened because git is not configured
- final GitVcs vcs = GitVcs.getInstance(myProject);
- if (vcs != null) {
- vcs.getExecutableValidator().showNotificationOrThrow(e);
- }
+ }
+ catch (VcsException e) {
+ // most probably the error happened because git is not configured
+ vcs.getExecutableValidator().showNotificationOrThrow(e);
}
}
diff --git a/plugins/git4idea/src/git4idea/status/GitChangesCollector.java b/plugins/git4idea/src/git4idea/status/GitChangesCollector.java
index 92058bc189d0..0d7869471475 100644
--- a/plugins/git4idea/src/git4idea/status/GitChangesCollector.java
+++ b/plugins/git4idea/src/git4idea/status/GitChangesCollector.java
@@ -17,13 +17,12 @@ package git4idea.status;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.vcs.FilePath;
-import com.intellij.openapi.vcs.FilePathImpl;
+import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManager;
+import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.VcsDirtyScope;
import com.intellij.openapi.vfs.VirtualFile;
-import git4idea.GitUtil;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@@ -37,18 +36,21 @@ import java.util.*;
* @author Kirill Likhodedov
*/
abstract class GitChangesCollector {
- protected final Project myProject;
- protected final VirtualFile myVcsRoot;
- private final ChangeListManager myChangeListManager;
- private final VcsDirtyScope myDirtyScope;
+ @NotNull protected final Project myProject;
+ @NotNull protected final VirtualFile myVcsRoot;
+
+ @NotNull private final VcsDirtyScope myDirtyScope;
+ @NotNull private final ChangeListManager myChangeListManager;
+ @NotNull private final ProjectLevelVcsManager myVcsManager;
+ @NotNull private AbstractVcs myVcs;
- GitChangesCollector(@NotNull Project project,
- @NotNull ChangeListManager changeListManager,
- @NotNull VcsDirtyScope dirtyScope,
- @NotNull VirtualFile vcsRoot) {
+ GitChangesCollector(@NotNull Project project, @NotNull ChangeListManager changeListManager, @NotNull ProjectLevelVcsManager vcsManager,
+ @NotNull AbstractVcs vcs, @NotNull VcsDirtyScope dirtyScope, @NotNull VirtualFile vcsRoot) {
myProject = project;
myChangeListManager = changeListManager;
+ myVcsManager = vcsManager;
+ myVcs = vcs;
myDirtyScope = dirtyScope;
myVcsRoot = vcsRoot;
}
@@ -80,27 +82,24 @@ abstract class GitChangesCollector {
}
if (includeChanges) {
- try {
- for (Change c : myChangeListManager.getChangesIn(myVcsRoot)) {
- switch (c.getType()) {
- case NEW:
- case DELETED:
- case MOVED:
- if (c.getAfterRevision() != null) {
- addToPaths(c.getAfterRevision().getFile(), allPaths);
- }
- if (c.getBeforeRevision() != null) {
- addToPaths(c.getBeforeRevision().getFile(), allPaths);
- }
- case MODIFICATION:
- default:
- // do nothing
- }
+ for (Change c : myChangeListManager.getChangesIn(myVcsRoot)) {
+ switch (c.getType()) {
+ case NEW:
+ case DELETED:
+ case MOVED:
+ ContentRevision afterRevision = c.getAfterRevision();
+ if (afterRevision != null) {
+ addToPaths(afterRevision.getFile(), allPaths);
+ }
+ ContentRevision beforeRevision = c.getBeforeRevision();
+ if (beforeRevision != null) {
+ addToPaths(beforeRevision.getFile(), allPaths);
+ }
+ case MODIFICATION:
+ default:
+ // do nothing
}
}
- catch (Exception t) {
- // ignore exceptions
- }
}
removeCommonParents(allPaths);
@@ -114,9 +113,9 @@ abstract class GitChangesCollector {
}
protected void addToPaths(FilePath pathToAdd, List paths) {
- File file = pathToAdd.getIOFile();
- if (myVcsRoot.equals(GitUtil.getGitRootOrNull(file))) {
- paths.add(file.getPath());
+ VcsRoot fileRoot = myVcsManager.getVcsRootObjectFor(pathToAdd);
+ if (fileRoot != null && fileRoot.vcs != null && fileRoot.vcs.equals(myVcs) && myVcsRoot.equals(fileRoot.path)) {
+ paths.add(pathToAdd.getPath());
}
}
diff --git a/plugins/git4idea/src/git4idea/status/GitNewChangesCollector.java b/plugins/git4idea/src/git4idea/status/GitNewChangesCollector.java
index 983e493813cf..6d1afc991059 100644
--- a/plugins/git4idea/src/git4idea/status/GitNewChangesCollector.java
+++ b/plugins/git4idea/src/git4idea/status/GitNewChangesCollector.java
@@ -18,9 +18,7 @@ package git4idea.status;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vcs.FilePath;
-import com.intellij.openapi.vcs.FileStatus;
-import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.ContentRevision;
@@ -70,8 +68,9 @@ class GitNewChangesCollector extends GitChangesCollector {
*/
@NotNull
static GitNewChangesCollector collect(@NotNull Project project, @NotNull Git git, @NotNull ChangeListManager changeListManager,
+ @NotNull ProjectLevelVcsManager vcsManager, @NotNull AbstractVcs vcs,
@NotNull VcsDirtyScope dirtyScope, @NotNull VirtualFile vcsRoot) throws VcsException {
- return new GitNewChangesCollector(project, git, changeListManager, dirtyScope, vcsRoot);
+ return new GitNewChangesCollector(project, git, changeListManager, vcsManager, vcs, dirtyScope, vcsRoot);
}
@Override
@@ -87,9 +86,10 @@ class GitNewChangesCollector extends GitChangesCollector {
}
private GitNewChangesCollector(@NotNull Project project, @NotNull Git git, @NotNull ChangeListManager changeListManager,
+ @NotNull ProjectLevelVcsManager vcsManager, @NotNull AbstractVcs vcs,
@NotNull VcsDirtyScope dirtyScope, @NotNull VirtualFile vcsRoot) throws VcsException
{
- super(project, changeListManager, dirtyScope, vcsRoot);
+ super(project, changeListManager, vcsManager, vcs, dirtyScope, vcsRoot);
myGit = git;
myRepository = GitUtil.getRepositoryManager(myProject).getRepositoryForRoot(vcsRoot);
diff --git a/plugins/git4idea/src/git4idea/status/GitOldChangesCollector.java b/plugins/git4idea/src/git4idea/status/GitOldChangesCollector.java
index 52ed9458f353..518efac8ca8d 100644
--- a/plugins/git4idea/src/git4idea/status/GitOldChangesCollector.java
+++ b/plugins/git4idea/src/git4idea/status/GitOldChangesCollector.java
@@ -16,9 +16,7 @@
package git4idea.status;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vcs.FilePath;
-import com.intellij.openapi.vcs.FileStatus;
-import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.ContentRevision;
@@ -104,11 +102,10 @@ class GitOldChangesCollector extends GitChangesCollector {
* This may be lengthy.
*/
@NotNull
- static GitOldChangesCollector collect(@NotNull Project project,
- @NotNull ChangeListManager changeListManager,
- @NotNull VcsDirtyScope dirtyScope,
- @NotNull VirtualFile vcsRoot) throws VcsException {
- return new GitOldChangesCollector(project, changeListManager, dirtyScope, vcsRoot);
+ static GitOldChangesCollector collect(@NotNull Project project, @NotNull ChangeListManager changeListManager,
+ @NotNull ProjectLevelVcsManager vcsManager, @NotNull AbstractVcs vcs,
+ @NotNull VcsDirtyScope dirtyScope, @NotNull VirtualFile vcsRoot) throws VcsException {
+ return new GitOldChangesCollector(project, changeListManager, vcsManager, vcs, dirtyScope, vcsRoot);
}
@NotNull
@@ -123,11 +120,10 @@ class GitOldChangesCollector extends GitChangesCollector {
return myChanges;
}
- private GitOldChangesCollector(@NotNull Project project,
- @NotNull ChangeListManager changeListManager,
- @NotNull VcsDirtyScope dirtyScope,
+ private GitOldChangesCollector(@NotNull Project project, @NotNull ChangeListManager changeListManager,
+ @NotNull ProjectLevelVcsManager vcsManager, @NotNull AbstractVcs vcs, @NotNull VcsDirtyScope dirtyScope,
@NotNull VirtualFile vcsRoot) throws VcsException {
- super(project, changeListManager, dirtyScope, vcsRoot);
+ super(project, changeListManager, vcsManager, vcs, dirtyScope, vcsRoot);
updateIndex();
collectUnmergedAndUnversioned();
collectDiffChanges();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java
index 8198915d6eff..81ad5ef1d57a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java
@@ -111,6 +111,7 @@ public class SvnConfiguration implements PersistentStateComponent {
public boolean IGNORE_SPACES_IN_ANNOTATE = true;
public boolean SHOW_MERGE_SOURCES_IN_ANNOTATE = true;
public boolean FORCE_UPDATE = false;
+ public boolean IGNORE_EXTERNALS = false;
public Boolean TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE;
public UseAcceleration myUseAcceleration = UseAcceleration.nothing;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineUpdateClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineUpdateClient.java
index 0b3296955b6b..ae68233c985a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineUpdateClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineUpdateClient.java
@@ -44,6 +44,7 @@ public class SvnCommandLineUpdateClient extends SvnSvnkitUpdateClient {
private static final String ourAuthenticationRealm = "Authentication realm:";
private final Project myProject;
private final VirtualFile myCommonAncestor;
+ private boolean myIgnoreExternals;
public SvnCommandLineUpdateClient(final Project project, VirtualFile commonAncestor) {
super(SvnVcs.getInstance(project).createUpdateClient());
@@ -102,6 +103,9 @@ public class SvnCommandLineUpdateClient extends SvnSvnkitUpdateClient {
if (makeParents) {
command.addParameters("--parents");
}
+ if (myIgnoreExternals) {
+ command.addParameters("--ignore-externals");
+ }
command.addParameters("--accept", "postpone");
command.addParameters("--config-dir", configDir.getPath());
@@ -268,4 +272,9 @@ public class SvnCommandLineUpdateClient extends SvnSvnkitUpdateClient {
// todo MAIN
//return super.doSwitch(path, url, pegRevision, revision, depth, allowUnversionedObstructions, depthIsSticky, ignoreAncestry);
}
+
+ @Override
+ public void setIgnoreExternals(boolean ignoreExternals) {
+ myIgnoreExternals = ignoreExternals;
+ }
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnSvnkitUpdateClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnSvnkitUpdateClient.java
index c3a6dbf9e67d..d69a47b2ec70 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnSvnkitUpdateClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnSvnkitUpdateClient.java
@@ -200,6 +200,11 @@ public class SvnSvnkitUpdateClient implements SvnUpdateClientI {
myClient.setEventHandler(dispatcher);
}
+ @Override
+ public void setIgnoreExternals(boolean ignoreExternals) {
+ myClient.setIgnoreExternals(ignoreExternals);
+ }
+
public ISVNEventHandler getEventHandler() {
return myDispatcher;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnUpdateClientI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnUpdateClientI.java
index 3568ce8a33e8..f587581f2c31 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnUpdateClientI.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnUpdateClientI.java
@@ -72,4 +72,5 @@ public interface SvnUpdateClientI {
void setExportExpandsKeywords(boolean expand);
void setEventHandler(ISVNEventHandler dispatcher);
+ void setIgnoreExternals(boolean ignoreExternals);
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
index 41062ac038d2..b2137fe3eaa5 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
@@ -85,7 +85,6 @@ public class SvnUpdateEnvironment extends AbstractSvnUpdateIntegrateEnvironment
final SVNURL sourceUrl = getSourceUrl(myVcs, root);
final boolean isSwitch = rootInfo != null && rootInfo.getUrl() != null && ! rootInfo.getUrl().equals(sourceUrl);
final SVNRevision updateTo = rootInfo != null && rootInfo.isUpdateToRevision() ? rootInfo.getRevision() : SVNRevision.HEAD;
-
if (isSwitch) {
final SvnUpdateClientI updateClient = createUpdateClient(configuration, root, true, sourceUrl);
rev = updateClient.doSwitch(root, rootInfo.getUrl(), SVNRevision.UNDEFINED, rootInfo.getRevision(), configuration.UPDATE_DEPTH, configuration.FORCE_UPDATE, false);
@@ -108,6 +107,9 @@ public class SvnUpdateEnvironment extends AbstractSvnUpdateIntegrateEnvironment
} else {
updateClient = new SvnSvnkitUpdateClient(myVcs.createUpdateClient());
}
+ if (! isSwitch) {
+ updateClient.setIgnoreExternals(configuration.IGNORE_EXTERNALS);
+ }
updateClient.setEventHandler(myHandler);
updateClient.setUpdateLocksOnDemand(configuration.UPDATE_LOCK_ON_DEMAND);
return updateClient;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.form b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.form
index c5d82eaf815b..9dba2ba4a112 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.form
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.form
@@ -14,7 +14,7 @@
-
+
@@ -22,7 +22,7 @@
-
+
@@ -57,6 +57,14 @@
+
+
+
+
+
+
+
+
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java
index 9080272ba078..ab66664f0f82 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java
@@ -34,6 +34,7 @@ public class SvnUpdatePanel extends AbstractSvnUpdatePanel {
private DepthCombo myDepthCombo;
private JLabel myDepthLabel;
private JPanel myAdditionalPanel;
+ private JCheckBox myIgnoreExternalsCheckBox;
public SvnUpdatePanel(SvnVcs vcs, Collection roots) {
super(vcs);
@@ -58,12 +59,19 @@ public class SvnUpdatePanel extends AbstractSvnUpdatePanel {
}
});
myForceBox.setSelected(svnConfiguration.FORCE_UPDATE);
+ myIgnoreExternalsCheckBox.setSelected(svnConfiguration.IGNORE_EXTERNALS);
myForceBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
svnConfiguration.FORCE_UPDATE = myForceBox.isSelected();
}
});
+ myIgnoreExternalsCheckBox.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ svnConfiguration.IGNORE_EXTERNALS = myIgnoreExternalsCheckBox.isSelected();
+ }
+ });
}
protected JPanel getRootsPanel() {