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