Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Dmitry Jemerov
2011-02-17 20:22:44 +01:00
52 changed files with 832 additions and 416 deletions
@@ -27,6 +27,8 @@ import com.intellij.util.StringBuilderSpinAllocator;
import org.jetbrains.annotations.NonNls;
import java.io.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* @author Eugene Zhuravlev
@@ -47,6 +49,8 @@ public class CompilerParsingThread implements Runnable, OutputParser.Callback {
private String myPushBackLine = null;
private volatile boolean myProcessExited = false;
private final CompileContext myContext;
private final BlockingQueue<String> myLines = new LinkedBlockingQueue<String>();
public CompilerParsingThread(Process process, OutputParser outputParser, final boolean readErrorStream, boolean trimLines, CompileContext context) {
myProcess = process;
@@ -60,6 +64,24 @@ public class CompilerParsingThread implements Runnable, OutputParser.Callback {
volatile boolean processing;
public void run() {
if (CompileDriver.ourDebugMode) {
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
while (true) {
final String line = readLine(myCompilerOutStreamReader);
if (CompileDriver.ourDebugMode) {
System.out.println("RAW_LIne read: #" + line + "#");
}
if (line == null) {
myLines.offer(TERMINATION_STRING);
break;
}
myLines.offer(line);
}
}
});
}
processing = true;
try {
while (true) {
@@ -111,7 +133,7 @@ public class CompilerParsingThread implements Runnable, OutputParser.Callback {
myLastReadLine = pushBack;
return pushBack;
}
final String line = readLine(myCompilerOutStreamReader);
final String line = getNextUnprocessedLine();
if (LOG.isDebugEnabled()) {
LOG.debug("LIne read: #" + line + "#");
}
@@ -127,6 +149,28 @@ public class CompilerParsingThread implements Runnable, OutputParser.Callback {
return myLastReadLine;
}
private String getNextUnprocessedLine() {
if (CompileDriver.ourDebugMode) {
try {
if (TERMINATION_STRING.equals(myLines.peek())) {
return TERMINATION_STRING;
}
final String line = myLines.take();
if (TERMINATION_STRING.equals(line)) {
myLines.offer(TERMINATION_STRING); // pushback
}
return line;
}
catch (InterruptedException e) {
e.printStackTrace();
return TERMINATION_STRING;
}
}
else {
return readLine(myCompilerOutStreamReader);
}
}
@Override
public void pushBack(String line) {
myLastReadLine = null;
@@ -224,16 +268,17 @@ public class CompilerParsingThread implements Runnable, OutputParser.Callback {
private int readNextByte(final Reader reader) {
try {
if (!CompileDriver.ourDebugMode) {
while(!reader.ready()) {
if (isProcessTerminated()) {
return -1;
}
try {
Thread.sleep(1L);
}
catch (InterruptedException ignore) {
while(!reader.ready()) {
if (isProcessTerminated()) {
if (reader.ready()) {
break;
}
return -1;
}
try {
Thread.sleep(1L);
}
catch (InterruptedException ignore) {
}
}
return reader.read();
@@ -244,6 +289,12 @@ public class CompilerParsingThread implements Runnable, OutputParser.Callback {
}
return -1; // When process terminated Process.getInputStream()'s underlying stream becomes closed on Linux.
}
catch (Throwable t) {
if (CompileDriver.ourDebugMode) {
t.printStackTrace();
}
return -1;
}
}
private boolean isProcessTerminated() {
@@ -177,6 +177,7 @@ public class JavaCompletionContributor extends CompletionContributor {
}
if (AFTER_NUMBER_LITERAL.accepts(position)) {
_result.stopHere();
return;
}
@@ -39,7 +39,10 @@ public class InsertLiteralUnderscoresAction extends PsiElementBaseIntentionActio
!PsiType.FLOAT.equals(type) && !PsiType.DOUBLE.equals(type)) return false;
final String text = literalExpression.getText();
return text != null && !text.contains("_");
if (text == null || text.contains("_")) return false;
final String converted = LiteralFormatUtil.format(text, type);
return converted.length() != text.length();
}
@Override
@@ -16,6 +16,7 @@
package com.intellij.codeInspection;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -71,29 +72,8 @@ public class ExplicitTypeCanBeDiamondInspection extends BaseJavaLocalInspectionT
final PsiTypeElement[] typeElements = parameterList.getTypeParameterElements();
if (typeElements.length > 0) {
if (typeElements.length == 1 && typeElements[0].getType() instanceof PsiDiamondType) return;
holder.registerProblem(parameterList, "Redundant type argument #ref #loc",
new LocalQuickFix() {
@NotNull
@Override
public String getName() {
return "Replace with <>";
}
@NotNull
@Override
public String getFamilyName() {
return getName();
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement psiElement = descriptor.getPsiElement();
if (psiElement instanceof PsiReferenceParameterList) {
final PsiTypeElement[] parameterElements = ((PsiReferenceParameterList)psiElement).getTypeParameterElements();
psiElement.deleteChildRange(parameterElements[0], parameterElements[parameterElements.length - 1]);
}
}
});
holder.registerProblem(parameterList, "Redundant type argument #ref #loc",
ProblemHighlightType.LIKE_UNUSED_SYMBOL, new ReplaceWithDiamondFix());
}
}
}
@@ -101,4 +81,27 @@ public class ExplicitTypeCanBeDiamondInspection extends BaseJavaLocalInspectionT
}
};
}
private static class ReplaceWithDiamondFix implements LocalQuickFix, HighPriorityAction {
@NotNull
@Override
public String getName() {
return "Replace with <>";
}
@NotNull
@Override
public String getFamilyName() {
return getName();
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement psiElement = descriptor.getPsiElement();
if (psiElement instanceof PsiReferenceParameterList) {
final PsiTypeElement[] parameterElements = ((PsiReferenceParameterList)psiElement).getTypeParameterElements();
psiElement.deleteChildRange(parameterElements[0], parameterElements[parameterElements.length - 1]);
}
}
}
}
@@ -68,43 +68,22 @@ public class SafeVarargsCanBeUsedInspection extends BaseJavaLocalInspectionTool
if (!PsiUtil.getLanguageLevel(method).isAtLeast(LanguageLevel.JDK_1_7)) return;
if (AnnotationUtil.isAnnotated(method, "java.lang.SafeVarargs", false)) return;
if (!method.isVarArgs()) return;
if (method.hasModifierProperty(PsiModifier.STATIC) || method.hasModifierProperty(PsiModifier.FINAL)) {
final PsiParameter psiParameter = method.getParameterList().getParameters()[method.getParameterList().getParametersCount() - 1];
final PsiType componentType = ((PsiEllipsisType)psiParameter.getType()).getComponentType();
if (GenericsHighlightUtil.isReifiableType(componentType)) {
final PsiParameter psiParameter = method.getParameterList().getParameters()[method.getParameterList().getParametersCount() - 1];
final PsiType componentType = ((PsiEllipsisType)psiParameter.getType()).getComponentType();
if (GenericsHighlightUtil.isReifiableType(componentType)) {
return;
}
for (PsiReference reference : ReferencesSearch.search(psiParameter)) {
final PsiElement element = reference.getElement();
if (element instanceof PsiExpression && !PsiUtil.isAccessedForReading((PsiExpression)element)) {
return;
}
for (PsiReference reference : ReferencesSearch.search(psiParameter)) {
final PsiElement element = reference.getElement();
if (element instanceof PsiExpression && !PsiUtil.isAccessedForReading((PsiExpression)element)) {
return;
}
}
final PsiIdentifier nameIdentifier = method.getNameIdentifier();
if (nameIdentifier != null) {
holder.registerProblem(nameIdentifier, "Possible heap pollution from parametrized vararg type #loc", new LocalQuickFix() {
@NotNull
@Override
public String getName() {
return "Annotate as @SafeVarargs";
}
@NotNull
@Override
public String getFamilyName() {
return getName();
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement psiElement = descriptor.getPsiElement();
if (psiElement instanceof PsiIdentifier) {
final PsiMethod psiMethod = (PsiMethod)psiElement.getParent();
new AddAnnotationFix("java.lang.SafeVarargs", psiMethod).applyFix(project, descriptor);
}
}
});
}
}
final PsiIdentifier nameIdentifier = method.getNameIdentifier();
if (nameIdentifier != null) {
holder.registerProblem(nameIdentifier, "Possible heap pollution from parameterized vararg type #loc",
//todo check if can be final or static
method.hasModifierProperty(PsiModifier.FINAL) || method.hasModifierProperty(PsiModifier.STATIC) ? new AnnotateAsSafeVarargsQuickFix() : null);
}
}
@@ -113,4 +92,27 @@ public class SafeVarargsCanBeUsedInspection extends BaseJavaLocalInspectionTool
}
};
}
private static class AnnotateAsSafeVarargsQuickFix implements LocalQuickFix {
@NotNull
@Override
public String getName() {
return "Annotate as @SafeVarargs";
}
@NotNull
@Override
public String getFamilyName() {
return getName();
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement psiElement = descriptor.getPsiElement();
if (psiElement instanceof PsiIdentifier) {
final PsiMethod psiMethod = (PsiMethod)psiElement.getParent();
new AddAnnotationFix("java.lang.SafeVarargs", psiMethod).applyFix(project, descriptor);
}
}
}
}
@@ -66,7 +66,8 @@ public class ClassesTreeStructureProvider implements SelectableTreeStructureProv
PsiClass[] classes = classOwner.getClasses();
if (fileInRoots(file)) {
if (classes.length == 1 && !(classes[0] instanceof SyntheticElement)) {
if (classes.length == 1 && !(classes[0] instanceof SyntheticElement) &&
(file == null || file.getNameWithoutExtension().equals(classes[0].getName()))) {
result.add(new ClassTreeNode(myProject, classes[0], settings1));
} else {
result.add(new PsiClassOwnerTreeNode(classOwner, settings1));
@@ -18,6 +18,8 @@ package com.intellij.psi.impl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import gnu.trove.THashMap;
import gnu.trove.TObjectHashingStrategy;
@@ -25,10 +27,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.*;
/**
* @author ik, dsl
@@ -99,11 +98,13 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
}
private abstract static class SubstitutionVisitorBase extends PsiTypeVisitorEx<PsiType> {
@Override
public PsiType visitType(PsiType type) {
LOG.assertTrue(false);
return null;
}
@Override
public PsiType visitWildcardType(PsiWildcardType wildcardType) {
final PsiType bound = wildcardType.getBound();
if (bound == null) {
@@ -135,10 +136,12 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
return PsiWildcardType.createUnbounded(wildcardType.getManager());
}
@Override
public PsiType visitPrimitiveType(PsiPrimitiveType primitiveType) {
return primitiveType;
}
@Override
public PsiType visitArrayType(PsiArrayType arrayType) {
final PsiType componentType = arrayType.getComponentType();
final PsiType substitutedComponentType = componentType.accept(this);
@@ -147,6 +150,7 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
return new PsiArrayType(substitutedComponentType);
}
@Override
public PsiType visitEllipsisType(PsiEllipsisType ellipsisType) {
final PsiType componentType = ellipsisType.getComponentType();
final PsiType substitutedComponentType = componentType.accept(this);
@@ -155,15 +159,26 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
return new PsiEllipsisType(substitutedComponentType);
}
@Override
public PsiType visitTypeVariable(final PsiTypeVariable var) {
return var;
}
@Override
public PsiType visitBottom(final Bottom bottom) {
return bottom;
}
@Override
public abstract PsiType visitClassType(PsiClassType classType);
@Override
public PsiType visitDisjunctionType(PsiDisjunctionType disjunctionType) {
final List<PsiType> substituted = ContainerUtil.map(disjunctionType.getDisjunctions(), new Function<PsiType, PsiType>() {
@Override public PsiType fun(PsiType psiType) { return psiType.accept(SubstitutionVisitorBase.this); }
});
return new PsiDisjunctionType(substituted, disjunctionType.getManager());
}
}
private final SubstitutionVisitor myAddingBoundsSubstitutionVisitor = new SubstitutionVisitor(SubstituteKind.ADD_BOUNDS);
@@ -13,10 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author max
*/
package com.intellij.psi.impl.smartPointers;
import com.intellij.openapi.diagnostic.Logger;
@@ -26,20 +22,28 @@ import com.intellij.psi.impl.PsiSubstitutorImpl;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.impl.source.PsiImmediateClassType;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author max
*/
public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.smartPointers.SmartTypePointerManagerImpl");
private final SmartPointerManager myPsiPointerManager;
private final Project myProject;
public SmartTypePointerManagerImpl(SmartPointerManager psiPointerManager, final Project project) {
public SmartTypePointerManagerImpl(final SmartPointerManager psiPointerManager, final Project project) {
myPsiPointerManager = psiPointerManager;
myProject = project;
}
@@ -102,26 +106,24 @@ public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
return PsiWildcardType.createUnbounded(myManager);
}
else {
final PsiType type = myBoundPointer.getType();
assert type != null : myBoundPointer;
if (myIsExtending) {
return PsiWildcardType.createExtends(myManager, myBoundPointer.getType());
return PsiWildcardType.createExtends(myManager, type);
}
else {
return PsiWildcardType.createSuper(myManager, myBoundPointer.getType());
return PsiWildcardType.createSuper(myManager, type);
}
}
}
}
private static class ClassTypePointer implements SmartTypePointer {
private PsiType myType;
private final SmartPsiElementPointer myClass;
private final Map<SmartPsiElementPointer, SmartTypePointer> myMap;
public ClassTypePointer(PsiType type,
SmartPsiElementPointer aClass,
Map<SmartPsiElementPointer, SmartTypePointer> map) {
public ClassTypePointer(PsiType type, SmartPsiElementPointer aClass, Map<SmartPsiElementPointer, SmartTypePointer> map) {
myType = type;
myClass = aClass;
myMap = map;
@@ -182,15 +184,40 @@ public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
}
}
private class DisjunctionTypePointer implements SmartTypePointer {
private PsiType myType;
private final List<SmartTypePointer> myPointers;
private DisjunctionTypePointer(final PsiDisjunctionType type) {
myType = type;
myPointers = ContainerUtil.map(type.getDisjunctions(), new Function<PsiType, SmartTypePointer>() {
@Override public SmartTypePointer fun(PsiType psiType) { return createSmartTypePointer(psiType); }
});
}
@Override
public PsiType getType() {
if (myType.isValid()) return myType;
final List<PsiType> types = ContainerUtil.map(myPointers, new NullableFunction<SmartTypePointer, PsiType>() {
@Override public PsiType fun(SmartTypePointer typePointer) { return typePointer.getType(); }
});
return new PsiDisjunctionType(types, PsiManager.getInstance(myProject));
}
}
private class SmartTypeCreatingVisitor extends PsiTypeVisitor<SmartTypePointer> {
@Override
public SmartTypePointer visitPrimitiveType(PsiPrimitiveType primitiveType) {
return new SimpleTypePointer(primitiveType);
}
@Override
public SmartTypePointer visitArrayType(PsiArrayType arrayType) {
return new ArrayTypePointer(arrayType, arrayType.getComponentType().accept(this));
}
@Override
public SmartTypePointer visitWildcardType(PsiWildcardType wildcardType) {
final PsiType bound = wildcardType.getBound();
final SmartTypePointer boundPointer;
@@ -203,6 +230,7 @@ public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
return new WildcardTypePointer(wildcardType, boundPointer);
}
@Override
public SmartTypePointer visitClassType(PsiClassType classType) {
final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
final PsiClass aClass = resolveResult.getElement();
@@ -226,6 +254,10 @@ public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
}
return new ClassTypePointer(classType, myPsiPointerManager.createSmartPsiElementPointer(aClass), map);
}
}
@Override
public SmartTypePointer visitDisjunctionType(PsiDisjunctionType disjunctionType) {
return new DisjunctionTypePointer(disjunctionType);
}
}
}
@@ -32,6 +32,7 @@ import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PatchedSoftReference;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -102,7 +103,12 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl
cachedType = componentType.createArrayType();
}
else {
cachedType = new PsiDisjunctionType(this);
final List<PsiTypeElement> typeElements = PsiTreeUtil.getChildrenOfTypeAsList(this, PsiTypeElement.class);
if (typeElements.size() < 2) LOG.error("Incorrect nested type: " + this);
final List<PsiType> types = ContainerUtil.map(typeElements, new Function<PsiTypeElement, PsiType>() {
@Override public PsiType fun(final PsiTypeElement psiTypeElement) { return psiTypeElement.getType(); }
});
cachedType = new PsiDisjunctionType(types, getManager());
}
}
else if (elementType == JavaElementType.JAVA_CODE_REFERENCE) {
@@ -180,15 +180,18 @@ public class JavaChangeUtilSupport implements TreeGenerator, TreeCopyHandler {
return createType(original.getProject(), originalText, null, generated);
}
if (type instanceof PsiIntersectionType) {
PsiIntersectionType intersectionType = (PsiIntersectionType)type;
LightTypeElement te = new LightTypeElement(original.getManager(), intersectionType.getConjuncts()[0]);
LightTypeElement te = new LightTypeElement(original.getManager(), ((PsiIntersectionType)type).getRepresentative());
return ChangeUtil.generateTreeElement(te, table, manager);
}
if (type instanceof PsiDisjunctionType) {
LightTypeElement te = new LightTypeElement(original.getManager(), ((PsiDisjunctionType)type).getLeastUpperBound());
return ChangeUtil.generateTreeElement(te, table, manager);
}
PsiClassType classType = (PsiClassType)type;
String text = classType.getPresentableText();
final TreeElement element = createType(original.getProject(), text, original, false);
PsiTypeElementImpl result = (PsiTypeElementImpl)SourceTreeToPsiMap.treeElementToPsi(element);
PsiTypeElementImpl result = SourceTreeToPsiMap.treeToPsiNotNull(element);
CodeEditUtil.setNodeGenerated(result, generated);
if (generated) {
@@ -397,7 +400,7 @@ public class JavaChangeUtilSupport implements TreeGenerator, TreeCopyHandler {
case PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND:
case PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND:
case PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND:
final PsiElement target = ((PsiJavaCodeReferenceElement)SourceTreeToPsiMap.treeElementToPsi(original)).resolve();
final PsiElement target = SourceTreeToPsiMap.<PsiJavaCodeReferenceElement>treeToPsiNotNull(original).resolve();
if (target instanceof PsiClass) {
ref.putCopyableUserData(REFERENCED_CLASS_KEY, (PsiClass)target);
}
@@ -40,7 +40,7 @@ import java.util.*;
public class TypeSelectorManagerImpl implements TypeSelectorManager {
private SmartTypePointer myPointer;
private PsiType myDefaultType;
private final PsiExpression myMainOccurence;
private final PsiExpression myMainOccurrence;
private final PsiExpression[] myOccurrences;
private final PsiType[] myTypesForMain;
private final PsiType[] myTypesForAll;
@@ -49,10 +49,9 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
private final PsiElementFactory myFactory;
private final SmartTypePointerManager mySmartTypePointerManager;
private ExpectedTypesProvider.ExpectedClassProvider myOccurrenceClassProvider;
private ExpectedTypesProvider myExpectedTypesProvider;
public TypeSelectorManagerImpl(Project project, PsiType type, PsiExpression mainOccurence, PsiExpression[] occurrences) {
this(project, type, null, mainOccurence, occurrences);
public TypeSelectorManagerImpl(Project project, PsiType type, PsiExpression mainOccurrence, PsiExpression[] occurrences) {
this(project, type, null, mainOccurrence, occurrences);
}
public TypeSelectorManagerImpl(Project project, PsiType type, PsiExpression[] occurrences) {
@@ -63,14 +62,14 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
myFactory = JavaPsiFacade.getInstance(project).getElementFactory();
mySmartTypePointerManager = SmartTypePointerManager.getInstance(project);
setDefaultType(type);
myMainOccurence = null;
myMainOccurrence = null;
myOccurrences = occurrences;
myExpectedTypesProvider = ExpectedTypesProvider.getInstance(project);
myOccurrenceClassProvider = createOccurrenceClassProvider();
myTypesForAll = getTypesForAll(areTypesDirected);
myTypesForMain = PsiType.EMPTY_ARRAY;
myIsOneSuggestion = myTypesForAll.length == 1;
myIsOneSuggestion = myTypesForAll.length == 1;
if (myIsOneSuggestion) {
myTypeSelector = new TypeSelector(myTypesForAll[0]);
}
@@ -83,14 +82,13 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
public TypeSelectorManagerImpl(Project project,
PsiType type,
PsiMethod containingMethod,
PsiExpression mainOccurence,
PsiExpression mainOccurrence,
PsiExpression[] occurrences) {
myFactory = JavaPsiFacade.getInstance(project).getElementFactory();
mySmartTypePointerManager = SmartTypePointerManager.getInstance(project);
setDefaultType(type);
myMainOccurence = mainOccurence;
myMainOccurrence = mainOccurrence;
myOccurrences = occurrences;
myExpectedTypesProvider = ExpectedTypesProvider.getInstance(project);
myOccurrenceClassProvider = createOccurrenceClassProvider();
myTypesForMain = getTypesForMain();
@@ -149,8 +147,8 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
private ExpectedTypesProvider.ExpectedClassProvider createOccurrenceClassProvider() {
final Set<PsiClass> occurrenceClasses = new HashSet<PsiClass>();
for (final PsiExpression occurence : myOccurrences) {
final PsiType occurrenceType = occurence.getType();
for (final PsiExpression occurrence : myOccurrences) {
final PsiType occurrenceType = occurrence.getType();
final PsiClass aClass = PsiUtil.resolveClassInType(occurrenceType);
if (aClass != null) {
occurrenceClasses.add(aClass);
@@ -160,8 +158,7 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
}
private PsiType[] getTypesForMain() {
final ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getExpectedTypes(myMainOccurence, false, myOccurrenceClassProvider,
false);
final ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getExpectedTypes(myMainOccurrence, false, myOccurrenceClassProvider, false);
final ArrayList<PsiType> allowedTypes = new ArrayList<PsiType>();
RefactoringHierarchyUtil.processSuperTypes(getDefaultType(), new RefactoringHierarchyUtil.SuperTypeVisitor() {
public void visitType(PsiType aType) {
@@ -173,9 +170,8 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
}
private void checkIfAllowed(PsiType type) {
if (expectedTypes != null && expectedTypes.length > 0) {
final ExpectedTypeInfo
typeInfo = ExpectedTypesProvider.createInfo(type, ExpectedTypeInfo.TYPE_STRICTLY, type, TailType.NONE);
if (expectedTypes.length > 0) {
final ExpectedTypeInfo typeInfo = ExpectedTypesProvider.createInfo(type, ExpectedTypeInfo.TYPE_STRICTLY, type, TailType.NONE);
for (ExpectedTypeInfo expectedType : expectedTypes) {
if (expectedType.intersect(typeInfo).length != 0) {
allowedTypes.add(type);
@@ -196,9 +192,7 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
private PsiType[] getTypesForAll(final boolean areTypesDirected) {
final ArrayList<ExpectedTypeInfo[]> expectedTypesFromAll = new ArrayList<ExpectedTypeInfo[]>();
for (PsiExpression occurrence : myOccurrences) {
final ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getExpectedTypes(occurrence, false, myOccurrenceClassProvider,
isUsedAfter());
final ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getExpectedTypes(occurrence, false, myOccurrenceClassProvider, isUsedAfter());
if (expectedTypes.length > 0) {
expectedTypesFromAll.add(expectedTypes);
}
@@ -259,20 +253,22 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
result.add(0, unboxedType);
}
if (defaultType instanceof PsiPrimitiveType && myMainOccurence != null) {
final PsiClassType boxedType = ((PsiPrimitiveType)defaultType).getBoxedType(myMainOccurence);
if (defaultType instanceof PsiPrimitiveType && myMainOccurrence != null) {
final PsiClassType boxedType = ((PsiPrimitiveType)defaultType).getBoxedType(myMainOccurrence);
if (boxedType != null) {
result.remove(boxedType);
result.add(0, boxedType);
}
}
result.add(0, defaultType);
if (!TypeConversionUtil.isComposite(defaultType)) {
result.add(0, defaultType);
}
return result;
}
public void setAllOccurences(boolean allOccurences) {
public void setAllOccurences(boolean occurrences) {
if (myIsOneSuggestion) return;
setTypesAndPreselect(allOccurences ? myTypesForAll : myTypesForMain);
setTypesAndPreselect(occurrences ? myTypesForAll : myTypesForMain);
}
private void setTypesAndPreselect(PsiType[] types) {
@@ -5,9 +5,10 @@ abstract class C {
private static class E2 extends E { }
private static class E3 extends E { }
private static class RE extends RuntimeException { }
private interface I { }
private static class IE1 extends E implements I { }
private static class IE2 extends E implements I { }
private interface I<T> { }
private static class IE1 extends E implements I<Integer> { }
private static class IE2 extends E implements I<Long> { }
private static class F<X> { F(X x) { } }
abstract void f() throws E1, E2;
abstract void g() throws IE1, IE2;
@@ -18,6 +19,8 @@ abstract class C {
try { f(); } catch (E2 | E1 e) { } catch (E e) { } catch (RE e) { }
try { f(); } catch (E1 | E e) { E ee = e; }
try { g(); } catch (IE1 | IE2 e) { E ee = e; I ii = e; }
try { g(); } catch (IE1 | IE2 e) { F<?> f = new F<>(e); }
try { g(); } catch (IE1 | IE2 e) { new F<I<? extends Number>>(e); }
try { f(); } catch (E1 | E2 | <error descr="Exception 'C.E3' is never thrown in the corresponding try block">E3</error> e) { }
try { f(); } catch (<error descr="Exception 'C.E3' is never thrown in the corresponding try block">E3</error> | E e) { }
@@ -1,7 +0,0 @@
// "Annotate as @SafeVarargs" "false"
public class Test {
public <T> void m<caret>ain(T... args) {
}
}
@@ -0,0 +1,11 @@
class C {
static class E1 extends Exception { }
static class E2 extends Exception { }
void m() {
try { }
catch (E1 | E2 ex) {
final Exception e = ex;
}
}
}
@@ -0,0 +1,11 @@
class C {
static class E1 extends Exception { }
static class E2 extends Exception { }
void m() {
try { }
catch (E1 | E2 ex) {
<caret>ex;
}
}
}
@@ -0,0 +1,12 @@
class C {
interface B<T> { }
static class E1 extends Exception implements B<Integer> { }
static class E2 extends Exception implements B<Long> { }
void m() {
try { }
catch (E1 | E2 ex) {
final B<? extends Number> b = ex;
}
}
}
@@ -0,0 +1,12 @@
class C {
interface B<T> { }
static class E1 extends Exception implements B<Integer> { }
static class E2 extends Exception implements B<Long> { }
void m() {
try { }
catch (E1 | E2 ex) {
<caret>ex;
}
}
}
@@ -476,5 +476,14 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
assert !lookup
}
public void testDoubleLiteralInField() {
myFixture.configureByText "a.java", """
public interface Test {
double FULL = 1.0<caret>
}"""
type 'd'
assert !lookup
}
}
@@ -3,8 +3,6 @@ package com.intellij.refactoring;
import com.intellij.JavaTestUtil;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiType;
@@ -250,6 +248,14 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
});
}
public void testMultiCatchSimple() throws Exception {
doTest(new MockIntroduceVariableHandler("e", true, true, false, "C.E1 | C.E2"));
}
public void testMultiCatchTyped() throws Exception {
doTest(new MockIntroduceVariableHandler("b", true, true, false, "C.E1 | C.E2"));
}
private void doTest(IntroduceVariableBase testMe) throws Exception {
@NonNls String baseName = "/refactoring/introduceVariable/" + getTestName(false);
configureByFile(baseName + ".java");
@@ -18,39 +18,38 @@ package com.intellij.psi;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
/**
* Composite type resulting from Project Coin's multi-catch statements, * i.e. <code>FileNotFoundException | EOFException</code>.
* In most cases should be threatened via its least upper bound * (<code>IOException</code> in the example above).
*/
public class PsiDisjunctionType extends PsiType {
private final PsiTypeElement myTypeElement;
private final PsiManager myManager;
private final List<PsiType> myTypes;
private final CachedValue<PsiType> myLubCache;
public PsiDisjunctionType(final PsiTypeElement typeElement) {
public PsiDisjunctionType(final List<PsiType> types, final PsiManager psiManager) {
super(PsiAnnotation.EMPTY_ARRAY);
myTypeElement = typeElement;
myManager = psiManager;
myTypes = Collections.unmodifiableList(types);
final List<PsiTypeElement> typeElements = PsiTreeUtil.getChildrenOfTypeAsList(myTypeElement, PsiTypeElement.class);
myTypes = Collections.unmodifiableList(ContainerUtil.map(typeElements, new Function<PsiTypeElement, PsiType>() {
@Override
public PsiType fun(final PsiTypeElement psiTypeElement) {
return psiTypeElement.getType();
}
}));
final CachedValuesManager cacheManager = CachedValuesManager.getManager(myTypeElement.getProject());
final CachedValuesManager cacheManager = CachedValuesManager.getManager(psiManager.getProject());
myLubCache = cacheManager.createCachedValue(new CachedValueProvider<PsiType>() {
public Result<PsiType> compute() {
PsiType lub = myTypes.get(0);
for (int i = 1; i < myTypes.size(); i++) {
lub = GenericsUtil.getLeastUpperBound(lub, myTypes.get(i), myTypeElement.getManager());
lub = GenericsUtil.getLeastUpperBound(lub, myTypes.get(i), psiManager);
}
return Result.create(lub, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
}
@@ -65,6 +64,10 @@ public class PsiDisjunctionType extends PsiType {
return myTypes;
}
public PsiManager getManager() {
return myManager;
}
@Override
public String getPresentableText() {
return StringUtil.join(myTypes, new Function<PsiType, String>() {
@@ -101,11 +104,7 @@ public class PsiDisjunctionType extends PsiType {
@Override
public <A> A accept(final PsiTypeVisitor<A> visitor) {
final PsiType lub = getLeastUpperBound();
if (lub instanceof PsiClassType) {
return visitor.visitClassType((PsiClassType)lub);
}
return visitor.visitType(lub);
return visitor.visitDisjunctionType(this);
}
@Override
@@ -45,7 +45,7 @@ public interface PsiParameter extends PsiVariable {
/**
* Checks if the parameter accepts a variable number of arguments.
*
* @return true if the parameter is varargs, false otherwise
* @return true if the parameter is a vararg, false otherwise
*/
boolean isVarArgs();
@@ -38,7 +38,7 @@ public interface PsiSubstitutor {
/**
* Empty, or natural, substitutor. For any type parameter <code>T</code>,
* substitues type <code>T</code>.
* substitutes type <code>T</code>.
* <b>Example:</b> consider class <code>List&lt;E&gt;</code>. <code>this</code>
* inside class <code>List</code> has type List with EMPTY substitutor.
*/
@@ -56,7 +56,7 @@ public interface PsiSubstitutor {
PsiType substitute(@NotNull PsiTypeParameter typeParameter);
/**
* Substitutes type parameters occuring in <code>type</code> with their values.
* Substitutes type parameters occurring in <code>type</code> with their values.
* If value for type parameter is <code>null<code>, appropriate erasure is returned.
*
* @param type the type to substitute the type parameters for.
@@ -98,7 +98,7 @@ public interface PsiSubstitutor {
PsiSubstitutor putAll(PsiSubstitutor another);
/**
* Returns the map from type parameters to types used for substution by this substitutor.
* Returns the map from type parameters to types used for substitution by this substitutor.
*
* @return the substitution map instance.
*/
@@ -40,7 +40,7 @@ public interface PsiTryStatement extends PsiStatement {
PsiCodeBlock[] getCatchBlocks();
/**
* Returns the array of parametets for <code>catch</code> sections.
* Returns the array of parameters for <code>catch</code> sections.
*
* @return the array of parameters, or an empty array if the statement has no catch sections.
*/
@@ -48,4 +48,8 @@ public class PsiTypeVisitor<A> {
public A visitEllipsisType(PsiEllipsisType ellipsisType) {
return visitArrayType(ellipsisType);
}
public A visitDisjunctionType(PsiDisjunctionType disjunctionType) {
return visitType(disjunctionType);
}
}
@@ -24,6 +24,7 @@ import com.intellij.psi.*;
import com.intellij.psi.infos.ClassCandidateInfo;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
@@ -33,10 +34,7 @@ import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.*;
public class TypeConversionUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.util.TypeConversionUtil");
@@ -75,6 +73,7 @@ public class TypeConversionUtil {
TYPE_TO_RANK_MAP.put(PsiType.BOOLEAN, BOOL_RANK);
}
private TypeConversionUtil() { }
/**
* @return true if fromType can be casted to toType
@@ -1077,6 +1076,10 @@ public class TypeConversionUtil {
return type != null && isPrimitiveWrapper(type.getCanonicalText());
}
public static boolean isComposite(final PsiType type) {
return type instanceof PsiDisjunctionType || type instanceof PsiIntersectionType;
}
public static PsiType typeParameterErasure(@NotNull PsiTypeParameter typeParameter) {
return typeParameterErasure(typeParameter, PsiSubstitutor.EMPTY);
}
@@ -1122,9 +1125,10 @@ public class TypeConversionUtil {
return erasure(type, PsiSubstitutor.EMPTY);
}
public static PsiType erasure(PsiType type, final PsiSubstitutor beforeSubstitutor) {
public static PsiType erasure(final PsiType type, final PsiSubstitutor beforeSubstitutor) {
if (type == null) return null;
return type.accept(new PsiTypeVisitor<PsiType>() {
@Override
public PsiType visitClassType(PsiClassType classType) {
final PsiClass aClass = classType.resolve();
if (aClass instanceof PsiTypeParameter) {
@@ -1135,14 +1139,17 @@ public class TypeConversionUtil {
}
}
@Override
public PsiType visitWildcardType(PsiWildcardType wildcardType) {
return wildcardType.getExtendsBound().accept(this);
}
@Override
public PsiType visitPrimitiveType(PsiPrimitiveType primitiveType) {
return primitiveType;
}
@Override
public PsiType visitEllipsisType(PsiEllipsisType ellipsisType) {
final PsiType componentType = ellipsisType.getComponentType();
final PsiType newComponentType = componentType.accept(this);
@@ -1150,12 +1157,21 @@ public class TypeConversionUtil {
return new PsiArrayType(newComponentType);
}
@Override
public PsiType visitArrayType(PsiArrayType arrayType) {
final PsiType componentType = arrayType.getComponentType();
final PsiType newComponentType = componentType.accept(this);
if (newComponentType == componentType) return arrayType;
return newComponentType.createArrayType();
}
@Override
public PsiType visitDisjunctionType(PsiDisjunctionType disjunctionType) {
final List<PsiType> erased = ContainerUtil.map(disjunctionType.getDisjunctions(), new Function<PsiType, PsiType>() {
@Override public PsiType fun(PsiType psiType) { return erasure(psiType, beforeSubstitutor); }
});
return new PsiDisjunctionType(erased, disjunctionType.getManager());
}
});
}
@@ -1539,6 +1555,5 @@ public class TypeConversionUtil {
}
return new ClassCandidateInfo(clazz, result.getSubstitutor());
}
}
@@ -66,11 +66,11 @@ public abstract class PsiElementPattern<T extends PsiElement,Self extends PsiEle
}
public Self afterLeaf(@NotNull final ElementPattern<? extends PsiElement> pattern) {
return afterLeafSkipping(psiElement().whitespaceCommentOrError(), pattern);
return afterLeafSkipping(psiElement().whitespaceCommentEmptyOrError(), pattern);
}
public Self beforeLeaf(@NotNull final ElementPattern<? extends PsiElement> pattern) {
return beforeLeafSkipping(psiElement().whitespaceCommentOrError(), pattern);
return beforeLeafSkipping(psiElement().whitespaceCommentEmptyOrError(), pattern);
}
public Self whitespace() {
@@ -81,6 +81,10 @@ public abstract class PsiElementPattern<T extends PsiElement,Self extends PsiEle
return andOr(psiElement().whitespace(), psiElement(PsiComment.class), psiElement(PsiErrorElement.class));
}
public Self whitespaceCommentEmptyOrError() {
return andOr(psiElement().whitespace(), psiElement(PsiComment.class), psiElement(PsiErrorElement.class), psiElement().withText(""));
}
public Self withFirstNonWhitespaceChild(@NotNull final ElementPattern<? extends PsiElement> pattern) {
return withChildren(collection(PsiElement.class).filter(not(psiElement().whitespace()), collection(PsiElement.class).first(pattern)));
}
@@ -67,7 +67,6 @@ class ParameterInfoComponent extends JPanel{
myObjects = objects;
setLayout(new GridBagLayout());
setBorder(BorderFactory.createCompoundBorder(LineBorder.createGrayLineBorder(), BorderFactory.createEmptyBorder(0, 5, 0, 5)));
setBackground(BACKGROUND_COLOR);
myHandler = handler;
@@ -314,7 +313,9 @@ class ParameterInfoComponent extends JPanel{
Dimension normalPreferredSize = super.getPreferredSize();
// some fonts (for example, Arial Black Cursiva) have NORMAL characters wider than BOLD characters
return new Dimension(Math.max(boldPreferredSize.width, normalPreferredSize.width), Math.max(boldPreferredSize.height, normalPreferredSize.height));
return new Dimension(Math.max(boldPreferredSize.width, normalPreferredSize.width),
Math.max(boldPreferredSize.height, normalPreferredSize.height));
}
}
}
@@ -198,7 +198,7 @@ public class LookupCellRenderer implements ListCellRenderer {
return text.substring(0, i) + ELLIPSIS;
}
private static Color getTailTextColor(boolean isSelected, LookupElementPresentation presentation, Color defaultForeground) {
public static Color getTailTextColor(boolean isSelected, LookupElementPresentation presentation, Color defaultForeground) {
if (presentation.isTailGrayed()) {
return getGrayedForeground(isSelected);
}
@@ -67,6 +67,7 @@ import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.MatteBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
@@ -1135,11 +1136,10 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
}
else if (myHintMode) {
final int itemTextPadding = 2;
final int borderWidth = 0;
final JPanel hintComponent = createAutopopupHintComponent(itemTextPadding, borderWidth);
final JPanel hintComponent = createAutopopupHintComponent(itemTextPadding);
Point bestPoint = calculatePosition(hintComponent);
bestPoint.x += myCellRenderer.getIconIndent() - itemTextPadding - borderWidth;
bestPoint.x += myCellRenderer.getIconIndent() - itemTextPadding;
Point editorPoint = SwingUtilities.convertPoint(
editor.getComponent().getRootPane().getLayeredPane(),
bestPoint,
@@ -1165,7 +1165,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
}
}
private JPanel createAutopopupHintComponent(int itemTextPadding, int borderWidth) {
private JPanel createAutopopupHintComponent(int itemTextPadding) {
int maxAutopopupItems = 7;
JPanel pane = new JPanel(new GridBagLayout());
pane.setBackground(HintUtil.INFORMATION_COLOR);
@@ -1185,53 +1185,75 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
c.ipadx = itemTextPadding;
c.fill = GridBagConstraints.HORIZONTAL;
final SimpleColoredComponent comp = new SimpleColoredComponent();
comp.setFont(editorFont);
final int style = presentation.isItemTextBold() ? Font.BOLD : Font.PLAIN;
myCellRenderer.renderItemName(element, LookupCellRenderer.FOREGROUND_COLOR, false, style,
StringUtil.notNullize(presentation.getItemText()), comp);
final JPanel p1 = new JPanel(new BorderLayout());
p1.setBackground(pane.getBackground());
p1.add(comp, BorderLayout.WEST);
final JLabel label = new JLabel(presentation.getTailText());
label.setFont(label.getFont().deriveFont(Font.PLAIN, editorFont.getSize()));
p1.add(label, BorderLayout.CENTER);
pane.add(p1, c);
}
{
final GridBagLayout gridBagLayout = new GridBagLayout();
final JPanel row = new JPanel(gridBagLayout);
row.setBackground(pane.getBackground());
{
final GridBagConstraints c = new GridBagConstraints();
c.gridx = 1;
c.gridy = i;
c.fill = GridBagConstraints.HORIZONTAL;
final JLabel comp = new JLabel(" " + StringUtil.notNullize(presentation.getTypeText()) + " ");
comp.setFont(comp.getFont().deriveFont(Font.PLAIN, editorFont.getSize()));
comp.setHorizontalAlignment(SwingConstants.RIGHT);
pane.add(comp, c);
GridBagConstraints c1 = new GridBagConstraints();
c1.anchor = GridBagConstraints.BASELINE;
final SimpleColoredComponent nameLabel = new SimpleColoredComponent();
nameLabel.setFont(editorFont);
final int style = presentation.isItemTextBold() ? Font.BOLD : Font.PLAIN;
myCellRenderer.renderItemName(element, LookupCellRenderer.FOREGROUND_COLOR, false, style,
StringUtil.notNullize(presentation.getItemText()), nameLabel);
row.add(nameLabel, c1);
c1 = new GridBagConstraints();
c1.weightx = 1;
c1.anchor = GridBagConstraints.BASELINE;
c1.fill = GridBagConstraints.HORIZONTAL;
final JLabel tailLabel = new JLabel(presentation.getTailText());
tailLabel.setFont(tailLabel.getFont().deriveFont(Font.PLAIN, editorFont.getSize()));
tailLabel.setForeground(LookupCellRenderer.getTailTextColor(false, presentation, tailLabel.getForeground()));
row.add(tailLabel, c1);
c1 = new GridBagConstraints();
c1.fill = GridBagConstraints.NONE;
final JLabel typeLabel = new JLabel(" " + StringUtil.notNullize(presentation.getTypeText()) + " ");
typeLabel.setFont(typeLabel.getFont().deriveFont(Font.PLAIN, editorFont.getSize()));
row.add(typeLabel, c1);
pane.add(row, c);
}
}
}
if (items.size() > maxAutopopupItems) {
{
final GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = maxAutopopupItems;
c.gridwidth = 2;
c.ipadx = 5;
c.ipady = 2;
c.fill = GridBagConstraints.HORIZONTAL;
final String moreText = " ... (" +
KeymapUtil
.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(IdeActions.ACTION_CODE_COMPLETION)) +
" for more suggestions)";
final JLabel label = new JLabel(moreText);
label.setFont(label.getFont().deriveFont(Font.PLAIN, editorFont.getSize()));
pane.add(label, c);
{
final GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = maxAutopopupItems;
c.gridwidth = 2;
c.ipadx = 5;
c.ipady = 2;
c.fill = GridBagConstraints.HORIZONTAL;
final JPanel ad = new JPanel(new BorderLayout());
ad.setBorder(BorderFactory.createCompoundBorder(new MatteBorder(1, 0, 0, 0, Color.lightGray), new EmptyBorder(0, 2, 0, 7)));
ad.setOpaque(false);
if (items.size() > maxAutopopupItems) {
final String ctrlSpace = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(IdeActions.ACTION_CODE_COMPLETION));
if (StringUtil.isNotEmpty(ctrlSpace)) {
final String moreText = ctrlSpace + " for more";
final JLabel moreLabel = new JLabel(moreText);
moreLabel.setFont(moreLabel.getFont().deriveFont(Font.PLAIN, editorFont.getSize()));
ad.add(moreLabel, BorderLayout.WEST);
}
}
final String tab = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_REPLACE));
if (StringUtil.isNotEmpty(tab)) {
final String enter = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM));
String message = tab + (isFocused() ? ", " + enter : "") + " for the first item";
final JLabel fstLabel = new JLabel(message);
fstLabel.setFont(fstLabel.getFont().deriveFont(Font.PLAIN, editorFont.getSize()));
ad.add(fstLabel, BorderLayout.EAST);
}
pane.add(ad, c);
}
//pane.setBorder(new LineBorder(Color.darkGray, borderWidth));
return pane;
}
@@ -307,9 +307,31 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele
private void highlightUsages(TextRange oldCursorRange) {
if (myEditor == null || myShouldStop) return;
LiveOccurrence firstVisibleOccurrence = null;
LiveOccurrence firstOccurrence = null;
for (LiveOccurrence o : mySearchResults) {
for (TextRange textRange : o.getSecondaryRanges()) {
highlightRange(textRange, OTHER_TARGETS_ATTRIBUTES, myHighlighters);
}
highlightRange(o.getPrimaryRange(), MAIN_TARGET_ATTRIBUTES, myHighlighters);
}
if (!tryToRepairOldCursor(oldCursorRange)) {
LiveOccurrence afterCaret = firstOccurrenceAfterCaret();
if (afterCaret != null) {
setCursor(afterCaret);
} else {
LiveOccurrence occurrence = firstVisibleOccurrence();
if (occurrence != null) {
setCursor(occurrence);
}
}
}
}
@Nullable
private LiveOccurrence firstVisibleOccurrence() {
int offset = Integer.MAX_VALUE;
LiveOccurrence firstOccurrence = null;
LiveOccurrence firstVisibleOccurrence = null;
for (LiveOccurrence o : mySearchResults) {
if (insideVisibleArea(myEditor, o.getPrimaryRange())) {
if (firstVisibleOccurrence == null || o.getPrimaryRange().getStartOffset() < firstVisibleOccurrence.getPrimaryRange().getStartOffset()) {
@@ -320,16 +342,22 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele
offset = o.getPrimaryRange().getStartOffset();
firstOccurrence = o;
}
}
return firstVisibleOccurrence != null ? firstVisibleOccurrence : firstOccurrence;
}
for (TextRange textRange : o.getSecondaryRanges()) {
highlightRange(textRange, OTHER_TARGETS_ATTRIBUTES, myHighlighters);
@Nullable
private LiveOccurrence firstOccurrenceAfterCaret() {
LiveOccurrence afterCaret = null;
int caret = myEditor.getCaretModel().getOffset();
for (LiveOccurrence occurrence : mySearchResults) {
if (occurrence.getPrimaryRange().getStartOffset() >= caret) {
if (afterCaret == null || occurrence.getPrimaryRange().getStartOffset() < afterCaret.getPrimaryRange().getStartOffset() ) {
afterCaret = occurrence;
}
}
highlightRange(o.getPrimaryRange(), MAIN_TARGET_ATTRIBUTES, myHighlighters);
}
if (!tryToRepairOldCursor(oldCursorRange)) {
setCursor(firstVisibleOccurrence != null ? firstVisibleOccurrence : firstOccurrence);
}
return afterCaret;
}
private boolean tryToRepairOldCursor(TextRange oldCursorRange) {
@@ -223,9 +223,7 @@ class FormatProcessor {
return;
}
while (myCurrentState.getStateId() == FormattingStateId.PROCESSING_BLOCKS && !myCurrentState.isDone()) {
myCurrentState.iteration();
}
doIterationsSynchronously(FormattingStateId.PROCESSING_BLOCKS);
}
private void reset() {
@@ -246,15 +244,27 @@ class FormatProcessor {
assert !myDisposed;
myCurrentState.setNext(new ApplyChangesState(model));
if (!sequentially) {
if (sequentially) {
return;
}
while (myCurrentState.getStateId() == FormattingStateId.APPLYING_CHANGES && !myCurrentState.isDone()) {
doIterationsSynchronously(FormattingStateId.APPLYING_CHANGES);
}
/**
* Perform iterations against the {@link #myCurrentState current state} until it's {@link FormattingStateId type}
* is {@link FormattingStateId#getPreviousStates() less} or equal to the given state.
*
* @param state target state to process
*/
private void doIterationsSynchronously(@NotNull FormattingStateId state) {
while ((myCurrentState.getStateId() == state || state.getPreviousStates().contains(myCurrentState.getStateId()))
&& !myCurrentState.isDone())
{
myCurrentState.iteration();
}
}
public void setJavaIndentOptions(final CodeStyleSettings.IndentOptions javaIndentOptions) {
myJavaIndentOptions = javaIndentOptions;
}
@@ -214,6 +214,7 @@ public class FormatterImpl extends FormatterEx
}
finally {
enableFormatting();
myProgressIndicator = null;
}
}
else {
@@ -35,6 +35,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.HashMap;
@@ -81,10 +82,9 @@ public class FormattingProgressIndicatorImpl extends Task.Modal implements Forma
private final Map<EventType, Collection<Runnable>> myCallbacks = new HashMap<EventType, Collection<Runnable>>();
@Nullable
private final VirtualFile myFile;
private final Document myDocument;
private final int myFileTextLength;
private final WeakReference<VirtualFile> myFile;
private final WeakReference<Document> myDocument;
private final int myFileTextLength;
@NotNull
private FormattingStateId myLastState = FormattingStateId.WRAPPING_BLOCKS;
@@ -98,8 +98,8 @@ public class FormattingProgressIndicatorImpl extends Task.Modal implements Forma
public FormattingProgressIndicatorImpl(@Nullable Project project, @NotNull PsiFile file, @NotNull Document document) {
super(project, getTitle(file), true);
myFile = file.getVirtualFile();
myDocument = document;
myFile = new WeakReference<VirtualFile>(file.getVirtualFile());
myDocument = new WeakReference<Document>(document);
myFileTextLength = file.getTextLength();
addCallback(EventType.CANCEL, new MyCancelCallback());
}
@@ -140,7 +140,10 @@ public class FormattingProgressIndicatorImpl extends Task.Modal implements Forma
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
myDocumentModificationStampBefore = myDocument.getModificationStamp();
Document document = myDocument.get();
if (document != null) {
myDocumentModificationStampBefore = document.getModificationStamp();
}
task.prepare();
}
});
@@ -282,16 +285,18 @@ public class FormattingProgressIndicatorImpl extends Task.Modal implements Forma
@Override
public void run() {
myRunning = false;
if (myFile == null || myDocumentModificationStampBefore < 0) {
VirtualFile file = myFile.get();
Document document = myDocument.get();
if (file == null || document == null || myDocumentModificationStampBefore < 0) {
return;
}
FileEditor editor = FileEditorManager.getInstance(myProject).getSelectedEditor(myFile);
FileEditor editor = FileEditorManager.getInstance(myProject).getSelectedEditor(file);
if (editor == null) {
return;
}
UndoManager manager = UndoManager.getInstance(myProject);
while (manager.isUndoAvailable(editor) && myDocument.getModificationStamp() != myDocumentModificationStampBefore) {
while (manager.isUndoAvailable(editor) && document.getModificationStamp() != myDocumentModificationStampBefore) {
manager.undo(editor);
}
}
@@ -141,7 +141,7 @@ public abstract class FileEditorManager {
/**
* Adds specified <code>listener</code>
* @param listener listener to be added
* @deprecated Use MessageBus instead
* @deprecated Use MessageBus instead: see {@link FileEditorManagerListener#FILE_EDITOR_MANAGER}
*/
public abstract void addFileEditorManagerListener(@NotNull FileEditorManagerListener listener);
@@ -433,7 +433,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible {
}
g.setColor(color);
final int textBaseline = (getHeight() - metrics.getHeight()) / 2 + metrics.getAscent();
final int textBaseline = getTextBaseLine(metrics, getHeight());
if (!attributes.isSearchMatch()) g.drawString(fragment, xOffset, textBaseline);
@@ -497,6 +497,16 @@ public class SimpleColoredComponent extends JComponent implements Accessible {
}
}
@Override
public int getBaseline(int width, int height) {
super.getBaseline(width, height);
return getTextBaseLine(getFontMetrics(getFont()), height);
}
private static int getTextBaseLine(FontMetrics metrics, final int height) {
return (height - metrics.getHeight()) / 2 + metrics.getAscent();
}
private static void checkCanPaint(Graphics g) {
if (UIUtil.isPrinting(g)) return;
@@ -17,15 +17,18 @@ package com.intellij.util.concurrency;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.Pair;
import com.intellij.util.AsynchConsumer;
import com.intellij.util.Consumer;
import com.intellij.util.PairConsumer;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.*;
/**
* <p>QueueProcessor processes elements which are being added to a queue via {@link #add(Object)} and {@link #addFirst(Object)} methods.</p>
@@ -48,6 +51,7 @@ public class QueueProcessor<T> {
private final ThreadToUse myThreadToUse;
private final Condition<?> myDeathCondition;
private final Map<MyOverrideEquals, ModalityState> myModalityState;
/**
* Constructs a QueueProcessor with the given processor and autostart setting.
@@ -65,6 +69,7 @@ public class QueueProcessor<T> {
myStarted = autostart;
myThreadToUse = threadToUse;
myDeathCondition = deathCondition;
myModalityState = new HashMap<MyOverrideEquals, ModalityState>();
myContinuationContext = new Runnable() {
@Override
@@ -85,6 +90,11 @@ public class QueueProcessor<T> {
this(wrappingProcessor(processor), autostart, ThreadToUse.POOLED, deathCondition);
}
public void add(T t, ModalityState state) {
myModalityState.put(new MyOverrideEquals(t), state);
doAdd(t, false);
}
private static<T> PairConsumer<T, Runnable> wrappingProcessor(final Consumer<T> processor) {
return new PairConsumer<T, Runnable>() {
@Override
@@ -176,7 +186,12 @@ public class QueueProcessor<T> {
};
final Application application = ApplicationManager.getApplication();
if (ThreadToUse.AWT.equals(myThreadToUse)) {
application.invokeLater(runnable);
final ModalityState state = myModalityState.remove(new MyOverrideEquals(item));
if (state != null) {
application.invokeLater(runnable, state);
} else {
application.invokeLater(runnable);
}
} else {
application.executeOnPooledThread(runnable);
}
@@ -193,4 +208,22 @@ public class QueueProcessor<T> {
AWT,
POOLED
}
private static class MyOverrideEquals {
private final Object myDelegate;
private MyOverrideEquals(Object delegate) {
myDelegate = delegate;
}
@Override
public int hashCode() {
return myDelegate.hashCode();
}
@Override
public boolean equals(Object obj) {
return ((MyOverrideEquals) obj).myDelegate == myDelegate;
}
}
}
@@ -472,7 +472,8 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener
if (prefSizeOriginal.width > fitWidth) {
setSize(new Dimension(fitWidth, Integer.MAX_VALUE));
Dimension fixedWidthSize = super.getPreferredSize();
prefSize.set(new Dimension(fitWidth, fixedWidthSize.height));
Dimension minSize = super.getMinimumSize();
prefSize.set(new Dimension(fitWidth > minSize.width ? fitWidth : minSize.width, fixedWidthSize.height));
}
else {
prefSize.set(new Dimension(prefSizeOriginal));
@@ -24,9 +24,10 @@ public abstract class ApplicationStatisticsPersistence {
@NotNull
public Map<String, Set<UsageDescriptor>> getApplicationData(@NotNull GroupDescriptor groupDescriptor) {
final Map<String, Set<UsageDescriptor>> map = myApplicationData.get(groupDescriptor);
return map == null ? new HashMap<String, Set<UsageDescriptor>>(): map;
if (!myApplicationData.containsKey(groupDescriptor)) {
myApplicationData.put(groupDescriptor, new HashMap<String, Set<UsageDescriptor>>());
}
return myApplicationData.get(groupDescriptor);
}
@NotNull
@@ -16,10 +16,12 @@
package com.intellij.internal.statistic.persistence;
import com.intellij.ide.AppLifecycleListener;
import com.intellij.internal.statistic.AbstractApplicationUsagesCollector;
import com.intellij.internal.statistic.UsagesCollector;
import com.intellij.internal.statistic.beans.GroupDescriptor;
import com.intellij.internal.statistic.beans.UsageDescriptor;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.ApplicationComponent;
@@ -30,9 +32,11 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.HashSet;
import com.intellij.util.messages.MessageBus;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -52,6 +56,8 @@ import java.util.Set;
)
public class ApplicationStatisticsPersistenceComponent extends ApplicationStatisticsPersistence
implements ApplicationComponent, PersistentStateComponent<Element> {
private boolean persistOnClosing = true;
private static final String TOKENIZER = ",";
@NonNls
@@ -152,6 +158,11 @@ public class ApplicationStatisticsPersistenceComponent extends ApplicationStatis
}
public void initComponent() {
onAppClosing();
onProjectClosing();
}
private void onProjectClosing() {
ProjectManager.getInstance().addProjectManagerListener(new ProjectManagerListener() {
@Override
public void projectOpened(Project project) {
@@ -169,16 +180,56 @@ public class ApplicationStatisticsPersistenceComponent extends ApplicationStatis
@Override
public void projectClosing(Project project) {
if (project != null) {
for (UsagesCollector usagesCollector : Extensions.getExtensions(UsagesCollector.EP_NAME)) {
if (usagesCollector instanceof AbstractApplicationUsagesCollector) {
((AbstractApplicationUsagesCollector) usagesCollector).persistProjectUsages(project);
}
if (persistOnClosing) {
doPersistProjectUsages(project);
}
}
}
});
}
private static void doPersistProjectUsages(@NotNull Project project) {
for (UsagesCollector usagesCollector : Extensions.getExtensions(UsagesCollector.EP_NAME)) {
if (usagesCollector instanceof AbstractApplicationUsagesCollector) {
((AbstractApplicationUsagesCollector) usagesCollector).persistProjectUsages(project);
}
}
}
private void onAppClosing() {
final MessageBus messageBus = ApplicationManager.getApplication().getMessageBus();
messageBus.connect().subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener() {
@Override
public void appFrameCreated(String[] commandLineArgs, @NotNull Ref<Boolean> willOpenProject) {
}
@Override
public void appStarting(Project projectFromCommandLine) {
}
@Override
public void projectFrameClosed() {
}
@Override
public void projectOpenFailed() {
}
@Override
public void welcomeScreenDisplayed() {
}
@Override
public void appClosing() {
for (Project project : ProjectManager.getInstance().getOpenProjects()) {
doPersistProjectUsages(project);
}
persistOnClosing = false;
}
});
}
public void disposeComponent() {
}
}
@@ -17,16 +17,21 @@
package com.intellij.openapi.progress;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.PairConsumer;
import com.intellij.util.concurrency.QueueProcessor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
/**
* Runs backgroundable tasks one by one.
* To add a task to the queue use {@link #run(com.intellij.openapi.progress.Task.Backgroundable)}
@@ -39,7 +44,7 @@ import org.jetbrains.annotations.Nullable;
public class BackgroundTaskQueue {
private static final Logger LOG = Logger.getInstance(BackgroundTaskQueue.class.getName());
//private final Project myProject;
private final QueueProcessor<Task.Backgroundable> myProcessor;
private final QueueProcessor<Pair<Task.Backgroundable, Getter<ProgressIndicator>>> myProcessor;
private Boolean myForcedTestMode;
public BackgroundTaskQueue(@Nullable Project project, @NotNull String title) {
@@ -48,7 +53,7 @@ public class BackgroundTaskQueue {
public BackgroundTaskQueue(@Nullable final Project project, @NotNull String title, final Boolean forcedHeadlessMode) {
final boolean headless = forcedHeadlessMode != null ? forcedHeadlessMode : ApplicationManager.getApplication().isHeadlessEnvironment();
myProcessor = new QueueProcessor<Task.Backgroundable>(headless ?
myProcessor = new QueueProcessor<Pair<Task.Backgroundable, Getter<ProgressIndicator>>>(headless ?
new BackgroundableHeadlessRunner() : new BackgroundableUnderProgressRunner(title, project), true,
headless ? QueueProcessor.ThreadToUse.POOLED : QueueProcessor.ThreadToUse.AWT, new Condition<Object>() {
@Override
@@ -68,23 +73,28 @@ public class BackgroundTaskQueue {
}
public void run(Task.Backgroundable task) {
run(task, null, null);
}
public void run(Task.Backgroundable task, final ModalityState state, final Getter<ProgressIndicator> pi) {
if (isTestMode()) { // test tasks are executed in this thread without the progress manager
RunBackgroundable.runIfBackgroundThread(task, new EmptyProgressIndicator(), null);
} else {
myProcessor.add(task);
myProcessor.add(new Pair<Task.Backgroundable, Getter<ProgressIndicator>>(task, pi), state);
}
}
private static class BackgroundableHeadlessRunner implements PairConsumer<Task.Backgroundable, Runnable> {
private static class BackgroundableHeadlessRunner implements PairConsumer<Pair<Task.Backgroundable, Getter<ProgressIndicator>>, Runnable> {
@Override
public void consume(Task.Backgroundable backgroundable, Runnable runnable) {
public void consume(Pair<Task.Backgroundable, Getter<ProgressIndicator>> pair, Runnable runnable) {
final Task.Backgroundable backgroundable = pair.getFirst();
// synchronously
ProgressManager.getInstance().run(backgroundable);
runnable.run();
}
}
private static class BackgroundableUnderProgressRunner implements PairConsumer<Task.Backgroundable, Runnable> {
private static class BackgroundableUnderProgressRunner implements PairConsumer<Pair<Task.Backgroundable, Getter<ProgressIndicator>>, Runnable> {
private final String myTitle;
private final Project myProject;
@@ -94,7 +104,8 @@ public class BackgroundTaskQueue {
}
@Override
public void consume(final Task.Backgroundable backgroundable, final Runnable runnable) {
public void consume(final Pair<Task.Backgroundable, Getter<ProgressIndicator>> pair, final Runnable runnable) {
final Task.Backgroundable backgroundable = pair.getFirst();
final ProgressIndicator[] pi = new ProgressIndicator[1];
final boolean taskTitleIsEmpty = StringUtil.isEmptyOrSpaces(backgroundable.getTitle());
@@ -112,7 +123,12 @@ public class BackgroundTaskQueue {
pm.runProcessWithProgressSynchronously(wrappedTask, taskTitleIsEmpty ? myTitle : backgroundable.getTitle(),
backgroundable.isCancellable(), myProject);
} else {
pi[0] = new BackgroundableProcessIndicator(backgroundable);
if (pair.getSecond() != null) {
pi[0] = pair.getSecond().get();
}
if (pi[0] == null) {
pi[0] = new BackgroundableProcessIndicator(backgroundable);
}
if (taskTitleIsEmpty) {
((BackgroundableProcessIndicator) pi[0]).setTitle(myTitle);
}
@@ -678,7 +678,7 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa
protected void init() {
super.init();
setUndecorated(true);
myPanel.setBorder(PopupBorder.Factory.create(true));
myPanel.setBorder(PopupBorder.Factory.create(true, true));
}
protected boolean isProgressDialog() {
@@ -78,7 +78,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
private MyComponent myComp;
private JLayeredPane myLayeredPane;
private Position myPosition;
private AbstractPosition myPosition;
private Point myTargetPoint;
private final boolean myHideOnFrameResize;
@@ -226,7 +226,13 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
}
public void show(final RelativePoint target, final Balloon.Position position) {
Position pos = BELOW;
AbstractPosition pos = getAbstractPositionFor(position);
show(target, pos);
}
private static AbstractPosition getAbstractPositionFor(Position position) {
AbstractPosition pos = BELOW;
switch (position) {
case atLeft:
pos = AT_LEFT;
@@ -241,12 +247,11 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
pos = ABOVE;
break;
}
show(target, pos);
return pos;
}
public void show(PositionTracker<Balloon> tracker, Balloon.Position position) {
Position pos = BELOW;
AbstractPosition pos = BELOW;
switch (position) {
case atLeft:
pos = AT_LEFT;
@@ -266,11 +271,11 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
}
private void show(RelativePoint target, Position position) {
private void show(RelativePoint target, AbstractPosition position) {
show(new PositionTracker.Static<Balloon>(target), position);
}
private void show(PositionTracker<Balloon> tracker, Position position) {
private void show(PositionTracker<Balloon> tracker, AbstractPosition position) {
assert !myDisposed : "Balloon is already disposed";
if (isVisible()) return;
@@ -279,7 +284,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
myTracker = tracker;
myTracker.init(this);
Position originalPreferred = position;
AbstractPosition originalPreferred = position;
JRootPane root = null;
JDialog dialog = IJSwingUtilities.findParentOfType(tracker.getComponent(), JDialog.class);
@@ -324,9 +329,9 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
Rectangle2D currentSquare = lp.createIntersection(rec);
double maxSquare = currentSquare.getWidth() * currentSquare.getHeight();
Position targetPosition = myPosition;
AbstractPosition targetPosition = myPosition;
for (Position eachPosition : myPosition.getOtherPositions()) {
for (AbstractPosition eachPosition : myPosition.getOtherPositions()) {
Rectangle2D eachIntersection = lp.createIntersection(getRecForPosition(eachPosition, false));
double eachSquare = eachIntersection.getWidth() * eachIntersection.getHeight();
if (maxSquare < eachSquare) {
@@ -383,7 +388,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
}, this);
}
private Rectangle getRecForPosition(Position position, boolean adjust) {
private Rectangle getRecForPosition(AbstractPosition position, boolean adjust) {
Dimension size = getContentSizeFor(position);
Rectangle rec = new Rectangle(new Point(0, 0), size);
@@ -398,7 +403,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
return rec;
}
private Dimension getContentSizeFor(Position position) {
private Dimension getContentSizeFor(AbstractPosition position) {
Insets insets = position.createBorder(this).getBorderInsets();
if (insets == null) {
insets = new Insets(0, 0, 0, 0);
@@ -514,18 +519,23 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
return 3;
}
int getPointerWidth(Position position) {
int getPointerWidth(AbstractPosition position) {
return position.isTopBottomPointer() ? 14 : 11;
}
int getNormalInset() {
public static int getNormalInset() {
return 3;
}
int getPointerLength(Position position) {
static int getPointerLength(AbstractPosition position) {
return position.isTopBottomPointer() ? 10 : 8;
}
public static int getPointerLength(Position position) {
return getPointerLength((getAbstractPositionFor(position)));
}
public void hide() {
Disposer.dispose(this);
@@ -596,14 +606,14 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
}
}
public abstract static class Position {
public abstract static class AbstractPosition {
abstract EmptyBorder createBorder(final BalloonImpl balloon);
abstract void setRecToRelativePosition(Rectangle rec, Point targetPoint);
abstract int getChangeShift(Position original, int xShift, int yShift);
abstract int getChangeShift(AbstractPosition original, int xShift, int yShift);
public void updateBounds(final BalloonImpl balloon) {
balloon.myComp._setBounds(getUpdatedBounds(balloon.myLayeredPane.getSize(),
@@ -690,8 +700,8 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
protected abstract Rectangle getPointlessContentRec(Rectangle bounds, int pointerLength);
public Set<Position> getOtherPositions() {
HashSet<Position> all = new HashSet<Position>();
public Set<AbstractPosition> getOtherPositions() {
HashSet<AbstractPosition> all = new HashSet<AbstractPosition>();
all.add(BELOW);
all.add(ABOVE);
all.add(AT_RIGHT);
@@ -705,13 +715,13 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
public abstract Point getShiftedPoint(Point targetPoint, int shift);
}
public static final Position BELOW = new Below();
public static final Position ABOVE = new Above();
public static final Position AT_RIGHT = new AtRight();
public static final Position AT_LEFT = new AtLeft();
public static final AbstractPosition BELOW = new Below();
public static final AbstractPosition ABOVE = new Above();
public static final AbstractPosition AT_RIGHT = new AtRight();
public static final AbstractPosition AT_LEFT = new AtLeft();
private static class Below extends Position {
private static class Below extends AbstractPosition {
@Override
@@ -720,7 +730,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
}
@Override
int getChangeShift(Position original, int xShift, int yShift) {
int getChangeShift(AbstractPosition original, int xShift, int yShift) {
return original == ABOVE ? yShift : 0;
}
@@ -772,15 +782,15 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
}
private static class Above extends Position {
private static class Above extends AbstractPosition {
@Override
public Point getShiftedPoint(Point targetPoint, int shift) {
return new Point(targetPoint.x, targetPoint.y - shift);
return new Point(targetPoint.x, targetPoint.y + shift);
}
@Override
int getChangeShift(Position original, int xShift, int yShift) {
int getChangeShift(AbstractPosition original, int xShift, int yShift) {
return original == BELOW ? -yShift : 0;
}
@@ -834,7 +844,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
}
}
private static class AtRight extends Position {
private static class AtRight extends AbstractPosition {
@Override
public Point getShiftedPoint(Point targetPoint, int shift) {
@@ -842,7 +852,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
}
@Override
int getChangeShift(Position original, int xShift, int yShift) {
int getChangeShift(AbstractPosition original, int xShift, int yShift) {
return original == AT_LEFT ? xShift : 0;
}
@@ -892,7 +902,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
}
}
private static class AtLeft extends Position {
private static class AtLeft extends AbstractPosition {
@Override
public Point getShiftedPoint(Point targetPoint, int shift) {
@@ -900,7 +910,7 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
}
@Override
int getChangeShift(Position original, int xShift, int yShift) {
int getChangeShift(AbstractPosition original, int xShift, int yShift) {
return original == AT_RIGHT ? -xShift : 0;
}
@@ -20,14 +20,17 @@ import com.intellij.ide.IdeTooltip;
import com.intellij.ide.IdeTooltipManager;
import com.intellij.ide.TooltipEvent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.wm.ex.LayoutFocusTraversalPolicyExt;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.panels.OpaquePanel;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.event.EventListenerList;
import java.awt.*;
import java.awt.event.ActionEvent;
@@ -177,13 +180,26 @@ public class LightweightHint extends UserDataHolderBase implements Hint {
}
else {
myIsRealPopup = true;
myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(myComponent, myFocusRequestor)
Point actualPoint = new Point(x, y);
JComponent actualComponent = new OpaquePanel(new BorderLayout());
actualComponent.add(myComponent, BorderLayout.CENTER);
if (myHintHint.isAwtTooltip()) {
fixActualPoint(actualPoint);
int inset = BalloonImpl.getNormalInset();
actualComponent.setBorder(new LineBorder(hintHint.getTextBackground(), inset));
actualComponent.setBackground(hintHint.getTextBackground());
actualComponent.validate();
}
myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(actualComponent, myFocusRequestor)
.setRequestFocus(myFocusRequestor != null)
.setResizable(myResizable)
.setMovable(myTitle != null)
.setTitle(myTitle)
.setModalContext(false)
.setShowShadow(!myForceLightweightPopup && myForceShowAsPopup)
.setShowShadow(isRealPopup())
.setCancelKeyEnabled(false)
.setCancelOnClickOutside(myCancelOnClickOutside)
.setCancelOnOtherWindowOpen(myCancelOnOtherWindowOpen)
@@ -191,7 +207,30 @@ public class LightweightHint extends UserDataHolderBase implements Hint {
.createPopup();
beforeShow();
myPopup.show(new RelativePoint(myParentComponent, new Point(x, y)));
myPopup.show(new RelativePoint(myParentComponent, new Point(actualPoint.x, actualPoint.y)));
}
}
private void fixActualPoint(Point actualPoint) {
if (!myHintHint.isAwtTooltip()) return;
if (!myIsRealPopup) return;
Dimension size = myComponent.getPreferredSize();
Balloon.Position position = myHintHint.getPreferredPosition();
int shift = BalloonImpl.getPointerLength(position);
switch (position) {
case below:
actualPoint.y += shift;
break;
case above:
actualPoint.y -= (shift + size.height);
break;
case atLeft:
actualPoint.x -= (shift + size.width);
break;
case atRight:
actualPoint.y += shift;
break;
}
}
@@ -203,7 +242,17 @@ public class LightweightHint extends UserDataHolderBase implements Hint {
if (hintHint.isAwtTooltip()) {
Dimension size = component.getPreferredSize();
Dimension paneSize = pane.getSize();
return size.width < paneSize.width && size.height < paneSize.height;
Point target = desiredLocation.getPointOn(pane).getPoint();
Balloon.Position pos = hintHint.getPreferredPosition();
int pointer = BalloonImpl.getPointerLength(pos) + BalloonImpl.getNormalInset();
if (pos == Balloon.Position.above || pos == Balloon.Position.below) {
boolean hieghtFit = target.y - size.height - pointer > 0 || target.y + size.height + pointer < paneSize.height;
return hieghtFit && size.width + pointer < paneSize.width;
} else {
boolean widthFit = target.x - size.width - pointer > 0 || target.x + size.width + pointer < paneSize.width;
return widthFit && size.height + pointer < paneSize.height;
}
} else {
final Rectangle lpRect = new Rectangle(pane.getLocationOnScreen().x, pane.getLocationOnScreen().y, pane.getWidth(), pane.getHeight());
Rectangle componentRect = new Rectangle(desiredLocation.getScreenPoint().x,
@@ -296,7 +345,9 @@ public class LightweightHint extends UserDataHolderBase implements Hint {
private void updateBounds(int x, int y, boolean updateLocation) {
setSize(myComponent.getPreferredSize());
if (updateLocation) {
setLocation(new RelativePoint(myParentComponent, new Point(x, y)));
Point point = new Point(x, y);
fixActualPoint(point);
setLocation(new RelativePoint(myParentComponent, point));
}
}
@@ -16,7 +16,6 @@
package com.intellij.ui.popup;
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.JBAwtEventQueue;
@@ -27,7 +26,6 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.impl.ShadowBorderPainter;
import com.intellij.openapi.ui.popup.*;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.registry.Registry;
@@ -50,17 +48,13 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static com.intellij.openapi.ui.impl.ShadowBorderPainter.*;
public class AbstractPopup implements JBPopup {
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.popup.AbstractPopup");
@@ -196,7 +190,7 @@ public class AbstractPopup implements JBPopup {
myProject = project;
myComponent = component;
myPopupBorder = PopupBorder.Factory.create(true);
myPopupBorder = PopupBorder.Factory.create(true, showShadow);
myShadowed = showShadow;
myPaintShadow = showShadow && !SystemInfo.isMac && !movable && !resizable && Registry.is("ide.popup.dropShadow");
myContent = createContentPanel(resizable, myPopupBorder, isToDrawMacCorner() && resizable);
@@ -301,7 +295,7 @@ public class AbstractPopup implements JBPopup {
@NotNull
protected MyContentPanel createContentPanel(final boolean resizable, PopupBorder border, boolean isToDrawMacCorner) {
return new MyContentPanel(resizable, border, isToDrawMacCorner, myPaintShadow);
return new MyContentPanel(resizable, border, isToDrawMacCorner);
}
public static boolean isToDrawMacCorner() {
@@ -1030,40 +1024,15 @@ public class AbstractPopup implements JBPopup {
public static class MyContentPanel extends JPanel {
private final boolean myResizable;
private final boolean myDrawMacCorner;
private final boolean myPaintShadow;
public MyContentPanel(final boolean resizable, final PopupBorder border, boolean drawMacCorner) {
this(resizable, border, drawMacCorner, false);
}
public MyContentPanel(final boolean resizable, final PopupBorder border, boolean drawMacCorner, boolean shadowed) {
super(new BorderLayout());
myResizable = resizable;
myDrawMacCorner = drawMacCorner;
myPaintShadow = shadowed && !UISettings.isRemoteDesktopConnected();
if (myPaintShadow) {
setOpaque(false);
setBorder(new EmptyBorder(POPUP_TOP_SIZE, POPUP_SIDE_SIZE, POPUP_BOTTOM_SIZE, POPUP_SIDE_SIZE) {
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
border.paintBorder(c, g,
x + POPUP_SIDE_SIZE - 1,
y + POPUP_TOP_SIZE - 1,
width - 2 * POPUP_SIDE_SIZE + 2,
height - POPUP_TOP_SIZE - POPUP_BOTTOM_SIZE + 2);
}
});
}
else {
setBorder(border);
}
setBorder(border);
}
public void paint(Graphics g) {
if (myPaintShadow) {
paintShadow(g);
}
super.paint(g);
if (myResizable && myDrawMacCorner) {
@@ -1073,21 +1042,6 @@ public class AbstractPopup implements JBPopup {
this);
}
}
private void paintShadow(final Graphics g) {
BufferedImage capture = null;
try {
final Point onScreen = getLocationOnScreen();
capture = new Robot().createScreenCapture(
new Rectangle(onScreen.x, onScreen.y, getWidth() + 2 * POPUP_SIDE_SIZE, getHeight() + POPUP_TOP_SIZE + POPUP_BOTTOM_SIZE));
final BufferedImage shadow = ShadowBorderPainter.createPopupShadow(this, getWidth(), getHeight());
((Graphics2D)capture.getGraphics()).drawImage(shadow, null, null);
}
catch (Exception e) {
LOG.info(e);
}
if (capture != null) g.drawImage(capture, 0, 0, null);
}
}
public boolean isCancelOnClickOutside() {
@@ -26,6 +26,7 @@ import com.intellij.usages.rules.MergeableUsage;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
@@ -43,7 +44,7 @@ public class GroupNode extends Node implements Navigatable, Comparable<GroupNode
private final List<UsageNode> myUsageNodes = new ArrayList<UsageNode>();
private volatile int myRecursiveUsageCount = 0;
public GroupNode(UsageGroup group, int ruleIndex, UsageViewTreeModelBuilder treeModel) {
public GroupNode(@Nullable UsageGroup group, int ruleIndex, @NotNull UsageViewTreeModelBuilder treeModel) {
super(treeModel);
setUserObject(group);
myGroup = group;
@@ -73,7 +74,7 @@ public class GroupNode extends Node implements Navigatable, Comparable<GroupNode
}
}
void addNode(final DefaultMutableTreeNode node) {
void addNode(@NotNull final DefaultMutableTreeNode node) {
if (!getBuilder().isDetachedMode()) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
@@ -99,20 +100,21 @@ public class GroupNode extends Node implements Navigatable, Comparable<GroupNode
myTreeModel.reload(this);
}
private UsageNode tryMerge(Usage usage) {
private UsageNode tryMerge(@NotNull Usage usage) {
if (!(usage instanceof MergeableUsage)) return null;
if (!UsageViewSettings.getInstance().isFilterDuplicatedLine()) return null;
MergeableUsage mergeableUsage = (MergeableUsage)usage;
for (UsageNode node : myUsageNodes) {
Usage original = node.getUsage();
assert original != mergeableUsage : "Double add: " + usage +"; node: "+ node+"; already added: "+myUsageNodes;
if (original instanceof MergeableUsage) {
if (((MergeableUsage)original).merge((MergeableUsage)usage)) return node;
if (((MergeableUsage)original).merge(mergeableUsage)) return node;
}
}
return null;
}
public boolean removeUsage(UsageNode usage) {
public boolean removeUsage(@NotNull UsageNode usage) {
ApplicationManager.getApplication().assertIsDispatchThread();
final Collection<GroupNode> groupNodes = mySubgroupNodes.values();
for(Iterator<GroupNode> iterator = groupNodes.iterator();iterator.hasNext();) {
@@ -129,7 +131,11 @@ public class GroupNode extends Node implements Navigatable, Comparable<GroupNode
}
}
if (myUsageNodes.remove(usage)) {
boolean removed;
synchronized (lock) {
removed = myUsageNodes.remove(usage);
}
if (removed) {
doUpdate();
return true;
}
@@ -143,12 +149,14 @@ public class GroupNode extends Node implements Navigatable, Comparable<GroupNode
myTreeModel.nodeChanged(this);
}
public UsageNode addUsage(Usage usage) {
public UsageNode addUsage(@NotNull Usage usage) {
final UsageNode node;
synchronized (lock) {
UsageNode mergedWith = tryMerge(usage);
if (mergedWith != null) {
return mergedWith;
if (UsageViewSettings.getInstance().isFilterDuplicatedLine()) {
UsageNode mergedWith = tryMerge(usage);
if (mergedWith != null) {
return mergedWith;
}
}
node = new UsageNode(usage, getBuilder());
myUsageNodes.add(node);
@@ -165,12 +173,12 @@ public class GroupNode extends Node implements Navigatable, Comparable<GroupNode
return node;
}
private int getNodeIndex(final UsageNode node) {
private int getNodeIndex(@NotNull UsageNode node) {
int index = indexedBinarySearch(node);
return index >= 0 ? index : -index-1;
}
private int indexedBinarySearch(UsageNode key) {
private int indexedBinarySearch(@NotNull UsageNode key) {
int low = 0;
int high = getChildCount() - 1;
@@ -246,7 +254,7 @@ public class GroupNode extends Node implements Navigatable, Comparable<GroupNode
return false;
}
private int getNodeInsertionIndex(DefaultMutableTreeNode node) {
private int getNodeInsertionIndex(@NotNull DefaultMutableTreeNode node) {
Enumeration children = children();
int idx = 0;
while (children.hasMoreElements()) {
@@ -663,7 +663,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
}
private final TransferToEDTQueue<Usage> myTransferToEDTQueue;
public void appendUsageLater(Usage usage) {
public void appendUsageLater(@NotNull Usage usage) {
myTransferToEDTQueue.offer(usage);
}
@@ -18,11 +18,11 @@ package com.intellij.usages.impl;
import com.intellij.openapi.fileEditor.FileEditorLocation;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.testFramework.LightPlatformTestCase;
import com.intellij.usages.*;
import com.intellij.usages.rules.UsageFilteringRule;
import com.intellij.usages.rules.UsageGroupingRule;
import com.intellij.util.ui.UIUtil;
import junit.framework.TestCase;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -30,12 +30,7 @@ import javax.swing.*;
/**
* @author max
*/
public class UsageNodeTreeBuilderTest extends TestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
}
public class UsageNodeTreeBuilderTest extends LightPlatformTestCase {
public void testNoGroupingRules() throws Exception {
GroupNode groupNode = buildUsageTree(new int[]{2, 3, 0}, new UsageGroupingRule[] {});
@@ -90,14 +85,13 @@ public class UsageNodeTreeBuilderTest extends TestCase {
usages[i] = createUsage(indices[i]);
}
//DefaultTreeModel model = new DefaultTreeModel(new DefaultMutableTreeNode("temp"));
UsageViewTreeModelBuilder model = new UsageViewTreeModelBuilder(new UsageViewPresentation(), new UsageTarget[0]);
GroupNode rootNode = new GroupNode(null, 0, model);
model.setRoot(rootNode);
UsageNodeTreeBuilder usageNodeTreeBuilder = new UsageNodeTreeBuilder(rules, UsageFilteringRule.EMPTY_ARRAY, rootNode);
for (Usage usage : usages) {
usageNodeTreeBuilder.appendUsage(usage);
UIUtil.pump();
UIUtil.dispatchAllInvocationEvents();
}
return rootNode;
@@ -29,9 +29,9 @@ public interface PopupBorder extends Border {
private Factory() {
}
public static PopupBorder create(boolean active) {
public static PopupBorder create(boolean active, boolean windowWithShadow) {
final BaseBorder border =
SystemInfo.isMac ? new BaseBorder() : new BaseBorder(true, CaptionPanel.getBorderColor(true), CaptionPanel.getBorderColor(false));
SystemInfo.isMac && windowWithShadow ? new BaseBorder() : new BaseBorder(true, CaptionPanel.getBorderColor(true), CaptionPanel.getBorderColor(false));
border.setActive(active);
return border;
}
@@ -70,7 +70,7 @@ public class TransferToEDTQueue<T> {
myShutUpCondition = shutUpCondition;
}
public void offer(final T thing) {
public void offer(@NotNull T thing) {
myQueue.offer(thing);
scheduleUpdate();
}
@@ -39,8 +39,8 @@ public class MessageBusTest extends TestCase {
void t22();
}
private final static Topic<T1Listener> T1 = new Topic<T1Listener>("T1", T1Listener.class);
private final static Topic<T2Listener> T2 = new Topic<T2Listener>("T1", T2Listener.class);
private static final Topic<T1Listener> TOPIC1 = new Topic<T1Listener>("T1", T1Listener.class);
private static final Topic<T2Listener> TOPIC2 = new Topic<T2Listener>("T2", T2Listener.class);
private class T1Handler implements T1Listener {
private final String id;
@@ -86,58 +86,57 @@ public class MessageBusTest extends TestCase {
}
public void testNoListenersSubscribed() {
myBus.syncPublisher(T1).t11();
myBus.syncPublisher(TOPIC1).t11();
assertEvents();
}
public void testSingleMessage() {
final MessageBusConnection connection = myBus.connect();
connection.subscribe(T1, new T1Handler("c"));
myBus.syncPublisher(T1).t11();
connection.subscribe(TOPIC1, new T1Handler("c"));
myBus.syncPublisher(TOPIC1).t11();
assertEvents("c:t11");
}
public void testSingleMessageToTwoConnections() {
final MessageBusConnection c1 = myBus.connect();
c1.subscribe(T1, new T1Handler("c1"));
c1.subscribe(TOPIC1, new T1Handler("c1"));
final MessageBusConnection c2 = myBus.connect();
c2.subscribe(T1, new T1Handler("c2"));
c2.subscribe(TOPIC1, new T1Handler("c2"));
myBus.syncPublisher(T1).t11();
myBus.syncPublisher(TOPIC1).t11();
assertEvents("c1:t11", "c2:t11");
}
public void testTwoMessagesWithSingleSubscription() {
final MessageBusConnection connection = myBus.connect();
connection.subscribe(T1, new T1Handler("c"));
myBus.syncPublisher(T1).t11();
myBus.syncPublisher(T1).t12();
connection.subscribe(TOPIC1, new T1Handler("c"));
myBus.syncPublisher(TOPIC1).t11();
myBus.syncPublisher(TOPIC1).t12();
assertEvents("c:t11", "c:t12");
}
public void testTwoMessagesWithDoubleSubscription() {
final MessageBusConnection c1 = myBus.connect();
c1.subscribe(T1, new T1Handler("c1"));
c1.subscribe(TOPIC1, new T1Handler("c1"));
final MessageBusConnection c2 = myBus.connect();
c2.subscribe(T1, new T1Handler("c2"));
c2.subscribe(TOPIC1, new T1Handler("c2"));
myBus.syncPublisher(T1).t11();
myBus.syncPublisher(T1).t12();
myBus.syncPublisher(TOPIC1).t11();
myBus.syncPublisher(TOPIC1).t12();
assertEvents("c1:t11", "c2:t11", "c1:t12", "c2:t12");
}
public void testEventFiresAnotherEvent() {
final MessageBusConnection c1 = myBus.connect();
c1.subscribe(T1, new T1Listener() {
myBus.connect().subscribe(TOPIC1, new T1Listener() {
@Override
public void t11() {
myLog.add("c1:t11");
myBus.syncPublisher(T2).t21();
myLog.add("c1:t11:done");
myLog.add("inside:t11");
myBus.syncPublisher(TOPIC2).t21();
myLog.add("inside:t11:done");
}
@Override
@@ -146,50 +145,62 @@ public class MessageBusTest extends TestCase {
}
});
final MessageBusConnection c2 = myBus.connect();
c2.subscribe(T1, new T1Handler("c2"));
c2.subscribe(T2, new T2Handler("c2"));
final MessageBusConnection conn = myBus.connect();
conn.subscribe(TOPIC1, new T1Handler("handler1"));
conn.subscribe(TOPIC2, new T2Handler("handler2"));
myBus.syncPublisher(T1).t12();
myBus.syncPublisher(T1).t11();
myBus.syncPublisher(TOPIC1).t12();
assertEvents("c1:t12", "handler1:t12");
assertEvents("c1:t12", "c2:t12", "c1:t11", "c2:t11", "c2:t21", "c1:t11:done");
myBus.syncPublisher(TOPIC1).t11();
assertEvents("c1:t12\n" +
"handler1:t12\n" +
"inside:t11\n" +
"handler1:t11\n" +
"handler2:t21\n" +
"inside:t11:done");
}
public void testConnectionTerminatedInDispatch() {
final MessageBusConnection c1 = myBus.connect();
c1.subscribe(T1, new T1Listener() {
final MessageBusConnection conn1 = myBus.connect();
conn1.subscribe(TOPIC1, new T1Listener() {
@Override
public void t11() {
c1.disconnect();
myLog.add("c1:t11");
myBus.syncPublisher(T2).t21();
myLog.add("c1:t11:done");
conn1.disconnect();
myLog.add("inside:t11");
myBus.syncPublisher(TOPIC2).t21();
myLog.add("inside:t11:done");
}
@Override
public void t12() {
myLog.add("c1:t12");
myLog.add("inside:t12");
}
});
c1.subscribe(T2, new T2Handler("c1"));
conn1.subscribe(TOPIC2, new T2Handler("C1T2Handler"));
final MessageBusConnection c2 = myBus.connect();
c2.subscribe(T1, new T1Handler("c2"));
c2.subscribe(T2, new T2Handler("c2"));
final MessageBusConnection conn2 = myBus.connect();
conn2.subscribe(TOPIC1, new T1Handler("C2T1Handler"));
conn2.subscribe(TOPIC2, new T2Handler("C2T2Handler"));
myBus.syncPublisher(T1).t11();
myBus.syncPublisher(T1).t12();
myBus.syncPublisher(TOPIC1).t11();
assertEvents("inside:t11",
"C2T1Handler:t11",
"C2T2Handler:t21",
"inside:t11:done");
myBus.syncPublisher(TOPIC1).t12();
assertEvents("c1:t11", "c2:t11", "c2:t21", "c1:t11:done", "c2:t12");
assertEvents("inside:t11",
"C2T1Handler:t11",
"C2T2Handler:t21",
"inside:t11:done",
"C2T1Handler:t12");
}
private void assertEvents(String... expected) {
String joinExpected = StringUtil.join(expected, "\n");
String joinActual = StringUtil.join(myLog.toArray(new String[0]), "\n");
String joinActual = StringUtil.join(myLog, "\n");
assertEquals("events mismatch", joinExpected, joinActual);
}
}
@@ -1,17 +1,17 @@
package org.jetbrains.plugins.groovy.debugger;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.*;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.runners.JavaProgramPatcher;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.PluginPathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JdkUtil;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.LanguageLevelModuleExtension;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
@@ -78,10 +78,20 @@ public class GroovyHotSwapper extends JavaProgramPatcher {
return;
}
if (LanguageLevelProjectExtension.getInstance(project).getLanguageLevel().compareTo(LanguageLevel.JDK_1_5) < 0) {
if (!LanguageLevelProjectExtension.getInstance(project).getLanguageLevel().isAtLeast(LanguageLevel.JDK_1_5)) {
return;
}
if (configuration instanceof ModuleBasedConfiguration) {
final Module module = ((ModuleBasedConfiguration)configuration).getConfigurationModule().getModule();
if (module != null) {
final LanguageLevel level = LanguageLevelModuleExtension.getInstance(module).getLanguageLevel();
if (level != null && !level.isAtLeast(LanguageLevel.JDK_1_5)) {
return;
}
}
}
Sdk jdk = javaParameters.getJdk();
if (jdk != null) {
String vendor = JdkUtil.getJdkMainAttribute(jdk, Attributes.Name.IMPLEMENTATION_VENDOR);
@@ -221,6 +221,13 @@ readonly
refactor
refactored
refactoring
reifiable
reification
reifications
reified
reifies
reify
reifying
reindex
renderer
resetlogs