diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/CompilerParsingThread.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/CompilerParsingThread.java index 5c786f9a2207..63c851a8cb06 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/CompilerParsingThread.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/CompilerParsingThread.java @@ -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 myLines = new LinkedBlockingQueue(); 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() { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index a04bc0bf4dcb..81807cd7b863 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -177,6 +177,7 @@ public class JavaCompletionContributor extends CompletionContributor { } if (AFTER_NUMBER_LITERAL.accepts(position)) { + _result.stopHere(); return; } diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InsertLiteralUnderscoresAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InsertLiteralUnderscoresAction.java index 40762fde4f14..281a18d78abc 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/InsertLiteralUnderscoresAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/InsertLiteralUnderscoresAction.java @@ -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 diff --git a/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java b/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java index a916513e5a5d..afd8c91f32b5 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java @@ -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]); + } + } + } } diff --git a/java/java-impl/src/com/intellij/codeInspection/SafeVarargsCanBeUsedInspection.java b/java/java-impl/src/com/intellij/codeInspection/SafeVarargsCanBeUsedInspection.java index 63eaa00f3c94..c5ed564fa65a 100644 --- a/java/java-impl/src/com/intellij/codeInspection/SafeVarargsCanBeUsedInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/SafeVarargsCanBeUsedInspection.java @@ -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); + } + } + } } diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java b/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java index 6e00723653a6..d7ba93b430ae 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java @@ -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)); diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java b/java/java-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java index a7676dc247f2..14527352e906 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java @@ -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 { + @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 substituted = ContainerUtil.map(disjunctionType.getDisjunctions(), new Function() { + @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); diff --git a/java/java-impl/src/com/intellij/psi/impl/smartPointers/SmartTypePointerManagerImpl.java b/java/java-impl/src/com/intellij/psi/impl/smartPointers/SmartTypePointerManagerImpl.java index fe1db0118759..ae32fccd1998 100644 --- a/java/java-impl/src/com/intellij/psi/impl/smartPointers/SmartTypePointerManagerImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/smartPointers/SmartTypePointerManagerImpl.java @@ -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 myMap; - - public ClassTypePointer(PsiType type, - SmartPsiElementPointer aClass, - Map map) { + public ClassTypePointer(PsiType type, SmartPsiElementPointer aClass, Map 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 myPointers; + + private DisjunctionTypePointer(final PsiDisjunctionType type) { + myType = type; + myPointers = ContainerUtil.map(type.getDisjunctions(), new Function() { + @Override public SmartTypePointer fun(PsiType psiType) { return createSmartTypePointer(psiType); } + }); + } + + @Override + public PsiType getType() { + if (myType.isValid()) return myType; + + final List types = ContainerUtil.map(myPointers, new NullableFunction() { + @Override public PsiType fun(SmartTypePointer typePointer) { return typePointer.getType(); } + }); + return new PsiDisjunctionType(types, PsiManager.getInstance(myProject)); + } + } + private class SmartTypeCreatingVisitor extends PsiTypeVisitor { + @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); + } + } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java index bc34754b5053..b24b1e46c962 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java @@ -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 typeElements = PsiTreeUtil.getChildrenOfTypeAsList(this, PsiTypeElement.class); + if (typeElements.size() < 2) LOG.error("Incorrect nested type: " + this); + final List types = ContainerUtil.map(typeElements, new Function() { + @Override public PsiType fun(final PsiTypeElement psiTypeElement) { return psiTypeElement.getType(); } + }); + cachedType = new PsiDisjunctionType(types, getManager()); } } else if (elementType == JavaElementType.JAVA_CODE_REFERENCE) { diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaChangeUtilSupport.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaChangeUtilSupport.java index 69eaa196df72..8dd87bc0b290 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaChangeUtilSupport.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaChangeUtilSupport.java @@ -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.treeToPsiNotNull(original).resolve(); if (target instanceof PsiClass) { ref.putCopyableUserData(REFERENCED_CLASS_KEY, (PsiClass)target); } diff --git a/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java b/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java index e5b588e196d2..a4ae0cdf045b 100644 --- a/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java @@ -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 occurrenceClasses = new HashSet(); - 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 allowedTypes = new ArrayList(); 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 expectedTypesFromAll = new ArrayList(); 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) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/MultiCatch.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/MultiCatch.java index 69cf037ebaae..705ecd8a6550 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/MultiCatch.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/MultiCatch.java @@ -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 { } + private static class IE1 extends E implements I { } + private static class IE2 extends E implements I { } + private static class F { 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>(e); } try { f(); } catch (E1 | E2 | E3 e) { } try { f(); } catch (E3 | E e) { } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/before4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/before4.java deleted file mode 100644 index aed4ed01314a..000000000000 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/safeVarargs/before4.java +++ /dev/null @@ -1,7 +0,0 @@ -// "Annotate as @SafeVarargs" "false" -public class Test { - public void main(T... args) { - - } -} - diff --git a/java/java-tests/testData/refactoring/introduceVariable/MultiCatchSimple.after.java b/java/java-tests/testData/refactoring/introduceVariable/MultiCatchSimple.after.java new file mode 100644 index 000000000000..cf16e0b4b794 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/MultiCatchSimple.after.java @@ -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; + } + } +} diff --git a/java/java-tests/testData/refactoring/introduceVariable/MultiCatchSimple.java b/java/java-tests/testData/refactoring/introduceVariable/MultiCatchSimple.java new file mode 100644 index 000000000000..582755caaab1 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/MultiCatchSimple.java @@ -0,0 +1,11 @@ +class C { + static class E1 extends Exception { } + static class E2 extends Exception { } + + void m() { + try { } + catch (E1 | E2 ex) { + ex; + } + } +} diff --git a/java/java-tests/testData/refactoring/introduceVariable/MultiCatchTyped.after.java b/java/java-tests/testData/refactoring/introduceVariable/MultiCatchTyped.after.java new file mode 100644 index 000000000000..aed77f0ac0b7 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/MultiCatchTyped.after.java @@ -0,0 +1,12 @@ +class C { + interface B { } + static class E1 extends Exception implements B { } + static class E2 extends Exception implements B { } + + void m() { + try { } + catch (E1 | E2 ex) { + final B b = ex; + } + } +} diff --git a/java/java-tests/testData/refactoring/introduceVariable/MultiCatchTyped.java b/java/java-tests/testData/refactoring/introduceVariable/MultiCatchTyped.java new file mode 100644 index 000000000000..6a8ce4f135ce --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/MultiCatchTyped.java @@ -0,0 +1,12 @@ +class C { + interface B { } + static class E1 extends Exception implements B { } + static class E2 extends Exception implements B { } + + void m() { + try { } + catch (E1 | E2 ex) { + ex; + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy index 658c03401b20..1439b3b55f83 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -476,5 +476,14 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase { assert !lookup } + public void testDoubleLiteralInField() { + myFixture.configureByText "a.java", """ +public interface Test { + double FULL = 1.0 +}""" + type 'd' + assert !lookup + } + } diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java index 2094231236f5..6bbc35d63484 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java @@ -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"); diff --git a/java/openapi/src/com/intellij/psi/PsiDisjunctionType.java b/java/openapi/src/com/intellij/psi/PsiDisjunctionType.java index e764b3bde987..0ae89e9850b4 100644 --- a/java/openapi/src/com/intellij/psi/PsiDisjunctionType.java +++ b/java/openapi/src/com/intellij/psi/PsiDisjunctionType.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. FileNotFoundException | EOFException. + * In most cases should be threatened via its least upper bound * (IOException in the example above). + */ public class PsiDisjunctionType extends PsiType { - private final PsiTypeElement myTypeElement; + private final PsiManager myManager; private final List myTypes; private final CachedValue myLubCache; - public PsiDisjunctionType(final PsiTypeElement typeElement) { + public PsiDisjunctionType(final List types, final PsiManager psiManager) { super(PsiAnnotation.EMPTY_ARRAY); - myTypeElement = typeElement; + myManager = psiManager; + myTypes = Collections.unmodifiableList(types); - final List typeElements = PsiTreeUtil.getChildrenOfTypeAsList(myTypeElement, PsiTypeElement.class); - myTypes = Collections.unmodifiableList(ContainerUtil.map(typeElements, new Function() { - @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() { public Result 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() { @@ -101,11 +104,7 @@ public class PsiDisjunctionType extends PsiType { @Override public A accept(final PsiTypeVisitor visitor) { - final PsiType lub = getLeastUpperBound(); - if (lub instanceof PsiClassType) { - return visitor.visitClassType((PsiClassType)lub); - } - return visitor.visitType(lub); + return visitor.visitDisjunctionType(this); } @Override diff --git a/java/openapi/src/com/intellij/psi/PsiParameter.java b/java/openapi/src/com/intellij/psi/PsiParameter.java index cee4c3820388..4d0c63d8fed3 100644 --- a/java/openapi/src/com/intellij/psi/PsiParameter.java +++ b/java/openapi/src/com/intellij/psi/PsiParameter.java @@ -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(); diff --git a/java/openapi/src/com/intellij/psi/PsiSubstitutor.java b/java/openapi/src/com/intellij/psi/PsiSubstitutor.java index 7ded0e1a995b..c60ece83b8a7 100644 --- a/java/openapi/src/com/intellij/psi/PsiSubstitutor.java +++ b/java/openapi/src/com/intellij/psi/PsiSubstitutor.java @@ -38,7 +38,7 @@ public interface PsiSubstitutor { /** * Empty, or natural, substitutor. For any type parameter T, - * substitues type T. + * substitutes type T. * Example: consider class List<E>. this * inside class List has type List with EMPTY substitutor. */ @@ -56,7 +56,7 @@ public interface PsiSubstitutor { PsiType substitute(@NotNull PsiTypeParameter typeParameter); /** - * Substitutes type parameters occuring in type with their values. + * Substitutes type parameters occurring in type with their values. * If value for type parameter is null, 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. */ diff --git a/java/openapi/src/com/intellij/psi/PsiTryStatement.java b/java/openapi/src/com/intellij/psi/PsiTryStatement.java index deb2c0560af2..a74ae8d52e61 100644 --- a/java/openapi/src/com/intellij/psi/PsiTryStatement.java +++ b/java/openapi/src/com/intellij/psi/PsiTryStatement.java @@ -40,7 +40,7 @@ public interface PsiTryStatement extends PsiStatement { PsiCodeBlock[] getCatchBlocks(); /** - * Returns the array of parametets for catch sections. + * Returns the array of parameters for catch sections. * * @return the array of parameters, or an empty array if the statement has no catch sections. */ diff --git a/java/openapi/src/com/intellij/psi/PsiTypeVisitor.java b/java/openapi/src/com/intellij/psi/PsiTypeVisitor.java index 59c52a49e931..045060685ce0 100644 --- a/java/openapi/src/com/intellij/psi/PsiTypeVisitor.java +++ b/java/openapi/src/com/intellij/psi/PsiTypeVisitor.java @@ -48,4 +48,8 @@ public class PsiTypeVisitor { public A visitEllipsisType(PsiEllipsisType ellipsisType) { return visitArrayType(ellipsisType); } + + public A visitDisjunctionType(PsiDisjunctionType disjunctionType) { + return visitType(disjunctionType); + } } diff --git a/java/openapi/src/com/intellij/psi/util/TypeConversionUtil.java b/java/openapi/src/com/intellij/psi/util/TypeConversionUtil.java index cad7a05a0836..bbe345501d62 100644 --- a/java/openapi/src/com/intellij/psi/util/TypeConversionUtil.java +++ b/java/openapi/src/com/intellij/psi/util/TypeConversionUtil.java @@ -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() { + @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 erased = ContainerUtil.map(disjunctionType.getDisjunctions(), new Function() { + @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()); - } } diff --git a/platform/lang-api/src/com/intellij/patterns/PsiElementPattern.java b/platform/lang-api/src/com/intellij/patterns/PsiElementPattern.java index cd72d658f331..c0339cb46e4c 100644 --- a/platform/lang-api/src/com/intellij/patterns/PsiElementPattern.java +++ b/platform/lang-api/src/com/intellij/patterns/PsiElementPattern.java @@ -66,11 +66,11 @@ public abstract class PsiElementPattern pattern) { - return afterLeafSkipping(psiElement().whitespaceCommentOrError(), pattern); + return afterLeafSkipping(psiElement().whitespaceCommentEmptyOrError(), pattern); } public Self beforeLeaf(@NotNull final ElementPattern pattern) { - return beforeLeafSkipping(psiElement().whitespaceCommentOrError(), pattern); + return beforeLeafSkipping(psiElement().whitespaceCommentEmptyOrError(), pattern); } public Self whitespace() { @@ -81,6 +81,10 @@ public abstract class PsiElementPattern pattern) { return withChildren(collection(PsiElement.class).filter(not(psiElement().whitespace()), collection(PsiElement.class).first(pattern))); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java index f747e3e324d2..5c459cde6457 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/ParameterInfoComponent.java @@ -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)); } } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java index f606603161fe..bbba75b5f69b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java @@ -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); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index 8a4982f74396..983e113d15ac 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -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; } diff --git a/platform/lang-impl/src/com/intellij/find/impl/LivePreview.java b/platform/lang-impl/src/com/intellij/find/impl/LivePreview.java index 5882ea6c05a9..e092ac5293fe 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/LivePreview.java +++ b/platform/lang-impl/src/com/intellij/find/impl/LivePreview.java @@ -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) { diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java index f59a387a9fb4..19f37c372305 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java @@ -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; } diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java index 052a2ca8a559..02a7cc6ff350 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java @@ -214,6 +214,7 @@ public class FormatterImpl extends FormatterEx } finally { enableFormatting(); + myProgressIndicator = null; } } else { diff --git a/platform/lang-impl/src/com/intellij/formatting/FormattingProgressIndicatorImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormattingProgressIndicatorImpl.java index 6916a1dcedcb..1a57f2c4a1bc 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormattingProgressIndicatorImpl.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormattingProgressIndicatorImpl.java @@ -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> myCallbacks = new HashMap>(); - @Nullable - private final VirtualFile myFile; - private final Document myDocument; - private final int myFileTextLength; + private final WeakReference myFile; + private final WeakReference 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(file.getVirtualFile()); + myDocument = new WeakReference(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); } } diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java index 6c0a2151931e..6d708c9103cd 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java @@ -141,7 +141,7 @@ public abstract class FileEditorManager { /** * Adds specified listener * @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); diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java index aff4263398ee..eb099fce193a 100644 --- a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java +++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java @@ -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; diff --git a/platform/platform-api/src/com/intellij/util/concurrency/QueueProcessor.java b/platform/platform-api/src/com/intellij/util/concurrency/QueueProcessor.java index 60e026f93b3e..b1d095ac5870 100644 --- a/platform/platform-api/src/com/intellij/util/concurrency/QueueProcessor.java +++ b/platform/platform-api/src/com/intellij/util/concurrency/QueueProcessor.java @@ -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.*; /** *

QueueProcessor processes elements which are being added to a queue via {@link #add(Object)} and {@link #addFirst(Object)} methods.

@@ -48,6 +51,7 @@ public class QueueProcessor { private final ThreadToUse myThreadToUse; private final Condition myDeathCondition; + private final Map myModalityState; /** * Constructs a QueueProcessor with the given processor and autostart setting. @@ -65,6 +69,7 @@ public class QueueProcessor { myStarted = autostart; myThreadToUse = threadToUse; myDeathCondition = deathCondition; + myModalityState = new HashMap(); myContinuationContext = new Runnable() { @Override @@ -85,6 +90,11 @@ public class QueueProcessor { 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 PairConsumer wrappingProcessor(final Consumer processor) { return new PairConsumer() { @Override @@ -176,7 +186,12 @@ public class QueueProcessor { }; 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 { 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; + } + } } diff --git a/platform/platform-impl/src/com/intellij/ide/IdeTooltipManager.java b/platform/platform-impl/src/com/intellij/ide/IdeTooltipManager.java index 7d4d43dd76c1..4de43e5babbb 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeTooltipManager.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeTooltipManager.java @@ -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)); diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistence.java b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistence.java index b5021df47287..2b5586ec17c4 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistence.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistence.java @@ -24,9 +24,10 @@ public abstract class ApplicationStatisticsPersistence { @NotNull public Map> getApplicationData(@NotNull GroupDescriptor groupDescriptor) { - final Map> map = myApplicationData.get(groupDescriptor); - - return map == null ? new HashMap>(): map; + if (!myApplicationData.containsKey(groupDescriptor)) { + myApplicationData.put(groupDescriptor, new HashMap>()); + } + return myApplicationData.get(groupDescriptor); } @NotNull diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistenceComponent.java b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistenceComponent.java index fb8d0fd6bffe..23b03085c414 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistenceComponent.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistenceComponent.java @@ -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 { + 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 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() { } } diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java b/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java index 0b38bee82dd0..dd2c56c12d81 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java @@ -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 myProcessor; + private final QueueProcessor>> 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(headless ? + myProcessor = new QueueProcessor>>(headless ? new BackgroundableHeadlessRunner() : new BackgroundableUnderProgressRunner(title, project), true, headless ? QueueProcessor.ThreadToUse.POOLED : QueueProcessor.ThreadToUse.AWT, new Condition() { @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 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, pi), state); } } - private static class BackgroundableHeadlessRunner implements PairConsumer { + private static class BackgroundableHeadlessRunner implements PairConsumer>, Runnable> { @Override - public void consume(Task.Backgroundable backgroundable, Runnable runnable) { + public void consume(Pair> pair, Runnable runnable) { + final Task.Backgroundable backgroundable = pair.getFirst(); // synchronously ProgressManager.getInstance().run(backgroundable); runnable.run(); } } - private static class BackgroundableUnderProgressRunner implements PairConsumer { + private static class BackgroundableUnderProgressRunner implements PairConsumer>, 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> 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); } diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java index d2a297431da3..c055dd7739a8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java @@ -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() { diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java index 92373029be56..c13aca602281 100644 --- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java @@ -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 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(target), position); } - private void show(PositionTracker tracker, Position position) { + private void show(PositionTracker 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 getOtherPositions() { - HashSet all = new HashSet(); + public Set getOtherPositions() { + HashSet all = new HashSet(); 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; } diff --git a/platform/platform-impl/src/com/intellij/ui/LightweightHint.java b/platform/platform-impl/src/com/intellij/ui/LightweightHint.java index ee8865ba3a0e..900089dc08a2 100644 --- a/platform/platform-impl/src/com/intellij/ui/LightweightHint.java +++ b/platform/platform-impl/src/com/intellij/ui/LightweightHint.java @@ -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)); } } diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index 87d293e51546..ad17e1a026f7 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -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() { diff --git a/platform/usageView/src/com/intellij/usages/impl/GroupNode.java b/platform/usageView/src/com/intellij/usages/impl/GroupNode.java index cd256daa4a35..583fce9f8caa 100644 --- a/platform/usageView/src/com/intellij/usages/impl/GroupNode.java +++ b/platform/usageView/src/com/intellij/usages/impl/GroupNode.java @@ -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 myUsageNodes = new ArrayList(); 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 groupNodes = mySubgroupNodes.values(); for(Iterator iterator = groupNodes.iterator();iterator.hasNext();) { @@ -129,7 +131,11 @@ public class GroupNode extends Node implements Navigatable, Comparable= 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 myTransferToEDTQueue; - public void appendUsageLater(Usage usage) { + public void appendUsageLater(@NotNull Usage usage) { myTransferToEDTQueue.offer(usage); } diff --git a/platform/usageView/testSrc/com/intellij/usages/impl/UsageNodeTreeBuilderTest.java b/platform/usageView/testSrc/com/intellij/usages/impl/UsageNodeTreeBuilderTest.java index 0d01f31bbcb5..11fb2df0b0b2 100644 --- a/platform/usageView/testSrc/com/intellij/usages/impl/UsageNodeTreeBuilderTest.java +++ b/platform/usageView/testSrc/com/intellij/usages/impl/UsageNodeTreeBuilderTest.java @@ -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; diff --git a/platform/util/src/com/intellij/ui/PopupBorder.java b/platform/util/src/com/intellij/ui/PopupBorder.java index 1eff0a877522..675a7edb52a2 100644 --- a/platform/util/src/com/intellij/ui/PopupBorder.java +++ b/platform/util/src/com/intellij/ui/PopupBorder.java @@ -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; } diff --git a/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java b/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java index 8c51af670634..4f374caaa6c0 100644 --- a/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java +++ b/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java @@ -70,7 +70,7 @@ public class TransferToEDTQueue { myShutUpCondition = shutUpCondition; } - public void offer(final T thing) { + public void offer(@NotNull T thing) { myQueue.offer(thing); scheduleUpdate(); } diff --git a/platform/util/testSrc/com/intellij/util/messages/MessageBusTest.java b/platform/util/testSrc/com/intellij/util/messages/MessageBusTest.java index 0e7dd44b4b2b..a016060a1605 100644 --- a/platform/util/testSrc/com/intellij/util/messages/MessageBusTest.java +++ b/platform/util/testSrc/com/intellij/util/messages/MessageBusTest.java @@ -39,8 +39,8 @@ public class MessageBusTest extends TestCase { void t22(); } - private final static Topic T1 = new Topic("T1", T1Listener.class); - private final static Topic T2 = new Topic("T1", T2Listener.class); + private static final Topic TOPIC1 = new Topic("T1", T1Listener.class); + private static final Topic TOPIC2 = new Topic("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); } - - } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapper.java index 4acba2698cfd..d8085109a7bd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapper.java @@ -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); diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index 3d84c3e01c53..5e4a963686c2 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/plugins/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -221,6 +221,13 @@ readonly refactor refactored refactoring +reifiable +reification +reifications +reified +reifies +reify +reifying reindex renderer resetlogs