From dff00a0e7ee4ca97f6af1106d554583219296e35 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 4 Aug 2010 20:11:01 +0100 Subject: [PATCH 01/18] idiomatic groovy constructors don't start with def (IDEA-27066) --- .../psi/impl/GroovyPsiElementFactoryImpl.java | 35 ++++++++++--------- .../generate/GroovyGenerateMembersTest.groovy | 2 +- .../generate/ConstructorAtEnd_after.groovy | 2 +- .../generate/ConstructorAtOffset_after.groovy | 2 +- .../generate/LonelyConstructor_after.groovy | 2 +- .../ImplicitDefaultConstructorAfter.groovy | 2 +- 6 files changed, 24 insertions(+), 21 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index bf538c0048d1..2ba1c96e7463 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -354,13 +354,13 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { String[] paramNames, String body, PsiElement context) { - final GrMethod method = createMethodFromText(null, constructorName, null, paramTypes, paramNames, body, context); + final String text = generateMethodText(null, constructorName, null, paramTypes, paramNames, body, true); - GroovyFileImpl file = createDummyFile("class " + constructorName + "{" + method.getText() + "}"); + GroovyFileImpl file = createDummyFile("class " + constructorName + "{" + text + "}"); file.setContext(context); - GrTopLevelDefintion defintion = file.getTopLevelDefinitions()[0]; - assert defintion != null && defintion instanceof GrClassDefinition; - final PsiMethod constructor = ((GrClassDefinition) defintion).getMethods()[0]; + GrTopLevelDefintion definition = file.getTopLevelDefinitions()[0]; + assert definition != null && definition instanceof GrClassDefinition; + final PsiMethod constructor = ((GrClassDefinition) definition).getMethods()[0]; assert constructor instanceof GrConstructorImpl; return ((GrConstructorImpl) constructor); } @@ -502,13 +502,13 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { } - private GrMethod createMethodFromText(String modifier, - String name, - String type, - @Nullable String[] paramTypes, - @NotNull String[] paramNames, - String body, - PsiElement context) { + private static String generateMethodText(String modifier, + String name, + String type, + String[] paramTypes, + String[] paramNames, + String body, + boolean isConstructor) { StringBuilder builder = new StringBuilder(); if (modifier != null){ @@ -516,7 +516,9 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { builder.append(" "); } - builder.append("def "); + if (!isConstructor) { + builder.append("def "); + } //This is for constructor creation if (type != null) { @@ -547,7 +549,7 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { builder.append("}"); } - return createMethodFromText(builder.toString(), context); + return builder.toString(); } public GrMethod createMethodFromText(String modifier, String name, @Nullable String type, String[] paramTypes, PsiElement context) { @@ -565,8 +567,9 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { res.add(psiType); } - return createMethodFromText(modifier, name, type, paramTypes, - QuickfixUtil.getMethodArgumentsNames(myProject, res.toArray(new PsiType[res.size()])), null, context); + String[] paramNames = QuickfixUtil.getMethodArgumentsNames(myProject, res.toArray(new PsiType[res.size()])); + final String text = generateMethodText(modifier, name, type, paramTypes, paramNames, null, false); + return createMethodFromText(text, context); } public GrDocComment createDocCommentFromText(String text) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/generate/GroovyGenerateMembersTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/generate/GroovyGenerateMembersTest.groovy index a0d9cac99121..25a2bab0634c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/generate/GroovyGenerateMembersTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/generate/GroovyGenerateMembersTest.groovy @@ -59,7 +59,7 @@ class Foo extends Super { Object d final e - def Foo(a, int b, int c, Object d, e) { + Foo(a, int b, int c, Object d, e) { super(a, b) this.c = c this.d = d diff --git a/plugins/groovy/testdata/generate/ConstructorAtEnd_after.groovy b/plugins/groovy/testdata/generate/ConstructorAtEnd_after.groovy index e66f9654f021..ef24405d6fd0 100644 --- a/plugins/groovy/testdata/generate/ConstructorAtEnd_after.groovy +++ b/plugins/groovy/testdata/generate/ConstructorAtEnd_after.groovy @@ -4,6 +4,6 @@ class ConstructorAtEnd { } - def ConstructorAtEnd() { + ConstructorAtEnd() { } } \ No newline at end of file diff --git a/plugins/groovy/testdata/generate/ConstructorAtOffset_after.groovy b/plugins/groovy/testdata/generate/ConstructorAtOffset_after.groovy index 799b0208cb76..cb313720239f 100644 --- a/plugins/groovy/testdata/generate/ConstructorAtOffset_after.groovy +++ b/plugins/groovy/testdata/generate/ConstructorAtOffset_after.groovy @@ -4,7 +4,7 @@ class ConstructorAtOffset { } - def ConstructorAtOffset() { + ConstructorAtOffset() { } def bar() { diff --git a/plugins/groovy/testdata/generate/LonelyConstructor_after.groovy b/plugins/groovy/testdata/generate/LonelyConstructor_after.groovy index 97b761702aa6..ec1c72136e52 100644 --- a/plugins/groovy/testdata/generate/LonelyConstructor_after.groovy +++ b/plugins/groovy/testdata/generate/LonelyConstructor_after.groovy @@ -1,5 +1,5 @@ class LonelyConstructor { - def LonelyConstructor() { + LonelyConstructor() { } } \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/introduceParameter/implicitDefaultConstructor/ImplicitDefaultConstructorAfter.groovy b/plugins/groovy/testdata/refactoring/introduceParameter/implicitDefaultConstructor/ImplicitDefaultConstructorAfter.groovy index 71c2f34d1813..42d1bbcf8451 100644 --- a/plugins/groovy/testdata/refactoring/introduceParameter/implicitDefaultConstructor/ImplicitDefaultConstructorAfter.groovy +++ b/plugins/groovy/testdata/refactoring/introduceParameter/implicitDefaultConstructor/ImplicitDefaultConstructorAfter.groovy @@ -1,5 +1,5 @@ class B extends A { - def B() { + B() { super(27) } } From cbe8a8d06d17e04ef9b043cfd1f8a53ce33ce630 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 4 Aug 2010 20:58:00 +0100 Subject: [PATCH 02/18] find overloaded constructor usages in literals --- .../ConstructorReferencesSearcher.java | 2 +- .../GroovyConstructorUsagesSearcher.java | 8 +-- .../LiteralConstructorReference.java | 53 ++++++++++++++++ .../LiteralConstructorSearcher.java | 63 ++++++------------- .../lang/psi/api/auxiliary/GrListOrMap.java | 4 ++ .../psi/impl/auxiliary/GrListOrMapImpl.java | 11 ++++ .../lang/LiteralConstructorUsagesTest.groovy | 19 +++++- 7 files changed, 110 insertions(+), 50 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorReference.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/ConstructorReferencesSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/ConstructorReferencesSearcher.java index 1e8ee89c70ff..beab58cf4968 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/ConstructorReferencesSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/ConstructorReferencesSearcher.java @@ -36,7 +36,7 @@ public class ConstructorReferencesSearcher extends QueryExecutorBase consumer) { - processConstructorUsages(p.getMethod(), p.getScope(), consumer, p.getOptimizer(), true); + processConstructorUsages(p.getMethod(), p.getScope(), consumer, p.getOptimizer(), true, !p.isStrictSignatureSearch()); } - static void processConstructorUsages(final PsiMethod constructor, final SearchScope searchScope, final Processor consumer, final SearchRequestCollector collector, final boolean searchGppCalls) { + static void processConstructorUsages(final PsiMethod constructor, final SearchScope searchScope, final Processor consumer, final SearchRequestCollector collector, final boolean searchGppCalls, final boolean includeOverloads) { if (!constructor.isConstructor()) return; SearchScope onlyGroovy = PsiUtil.restrictScopeToGroovyFiles(searchScope); @@ -103,7 +103,7 @@ public class GroovyConstructorUsagesSearcher extends QueryExecutorBase newExpressionProcessor = new Processor() { @Override @@ -230,7 +230,7 @@ public class GroovyConstructorUsagesSearcher extends QueryExecutorBase { + private final PsiClassType myConstructedClass; + + public LiteralConstructorReference(@NotNull GrListOrMap element, @NotNull PsiClassType constructedClassType) { + super(element, TextRange.from(0, 1), false); + myConstructedClass = constructedClassType; + } + + @Nullable + private PsiType[] argTypes() { + final GrListOrMap literal = getElement(); + final PsiType listType = literal.getType(); + if (listType instanceof GrTupleType) { + return ((GrTupleType)listType).getComponentTypes(); + } + else if (listType instanceof GrMapType && ((GrMapType)listType).getValueType("super") == null) { + return PsiType.EMPTY_ARRAY; + } + return null; + } + + @NotNull + @Override + public ResolveResult[] multiResolve(boolean incompleteCode) { + final PsiType[] psiTypes = argTypes(); + if (psiTypes == null) return ResolveResult.EMPTY_ARRAY; + + return PsiUtil.getConstructorCandidates(myConstructedClass, psiTypes, getElement()); + } + + @NotNull + @Override + public Object[] getVariants() { + return EMPTY_ARRAY; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorSearcher.java index 470b6a2625b2..5cf0ef6ddf39 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorSearcher.java @@ -1,14 +1,13 @@ package org.jetbrains.plugins.groovy.findUsages; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.*; +import com.intellij.psi.PsiClassType; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiReference; +import com.intellij.util.ObjectUtils; import com.intellij.util.Processor; -import org.jetbrains.plugins.groovy.gpp.GppReferenceContributor; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; -import org.jetbrains.plugins.groovy.lang.psi.impl.GrMapType; -import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType; /** * @author peter @@ -16,53 +15,29 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType; public class LiteralConstructorSearcher { private final PsiMethod myConstructor; private final Processor myConsumer; + private final boolean myIncludeOverloads; - public LiteralConstructorSearcher(PsiMethod constructor, Processor consumer) { + public LiteralConstructorSearcher(PsiMethod constructor, Processor consumer, boolean includeOverloads) { myConstructor = constructor; myConsumer = consumer; + myIncludeOverloads = includeOverloads; } - private static boolean checkLiteralInstantiation(PsiMethod constructor, - Processor consumer, - GrListOrMap literal, - PsiClassType expectedType) { - final PsiType listType = literal.getType(); - if (listType instanceof GrTupleType) { - if (GppReferenceContributor.isConstructorCall(expectedType, ((GrTupleType)listType).getComponentTypes(), constructor, literal)) { - return consumer.process(PsiReferenceBase.createSelfReference(literal, TextRange.from(0, literal.getTextLength()), constructor)); + public boolean processLiteral(GrListOrMap literal, PsiClassType expectedType) { + if (literal.isMap()) { + final GrNamedArgument argument = literal.findNamedArgument("super"); + if (argument != null) { + return processConstructorReference(ObjectUtils.assertNotNull(argument.getLabel()).getReference()); } } - else if (listType instanceof GrMapType) { - final PsiType constructorArgs = ((GrMapType)listType).getValueType("super"); - if (constructorArgs == null) { - if (constructor.getParameterList().getParametersCount() == 0) { - if (!consumer.process(PsiReferenceBase.createSelfReference(literal, TextRange.from(0, literal.getTextLength()), constructor))) { - return false; - } - } - return true; - } - for (GrNamedArgument argument : literal.getNamedArguments()) { - final GrArgumentLabel label = argument.getLabel(); - if (label != null && "super".equals(label.getName())) { - final PsiReference reference = label.getReference(); - if (reference != null && reference.isReferenceTo(constructor)) { - return consumer.process(reference); - } - return true; - } - } + return processConstructorReference(new LiteralConstructorReference(literal, expectedType)); + } - //no 'super', only default constructor applicable - if (constructor.getParameterList().getParametersCount() == 0) { - return consumer.process(PsiReferenceBase.createSelfReference(literal, TextRange.from(0, literal.getTextLength()), constructor)); - } - } + private boolean processConstructorReference(@Nullable PsiReference reference) { + if (reference != null && (myIncludeOverloads || reference.isReferenceTo(myConstructor))) { + return myConsumer.process(reference); + } return true; } - - public boolean processLiteral(GrListOrMap list, PsiClassType expectedType) { - return checkLiteralInstantiation(myConstructor, myConsumer, list, expectedType); - } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/auxiliary/GrListOrMap.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/auxiliary/GrListOrMap.java index d69643b07845..4df2e4b140c4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/auxiliary/GrListOrMap.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/auxiliary/GrListOrMap.java @@ -22,6 +22,7 @@ import com.intellij.openapi.util.UserDataHolderEx; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiArrayInitializerMemberValue; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; @@ -42,5 +43,8 @@ public interface GrListOrMap extends UserDataHolderEx, Cloneable, Iconable, PsiE @NotNull GrNamedArgument[] getNamedArguments(); + @Nullable + GrNamedArgument findNamedArgument(@NotNull String label); + boolean isMap(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java index e1e3d6d9d631..77c33eb34ab6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java @@ -92,6 +92,17 @@ public class GrListOrMapImpl extends GrExpressionImpl implements GrListOrMap { return findChildrenByClass(GrNamedArgument.class); } + @Override + public GrNamedArgument findNamedArgument(@NotNull String labelName) { + for (GrNamedArgument argument : getNamedArguments()) { + final GrArgumentLabel label = argument.getLabel(); + if (label != null && labelName.equals(label.getName())) { + return argument; + } + } + return null; + } + private static class MyTypesCalculator implements Function { @Nullable public PsiType fun(GrListOrMapImpl listOrMap) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/LiteralConstructorUsagesTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/LiteralConstructorUsagesTest.groovy index 4faa4cb1b0b3..3e97b48a842c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/LiteralConstructorUsagesTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/LiteralConstructorUsagesTest.groovy @@ -1,7 +1,8 @@ package org.jetbrains.plugins.groovy.lang -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import com.intellij.psi.search.searches.MethodReferencesSearch import com.intellij.psi.search.searches.ReferencesSearch +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase /** * @author peter @@ -160,4 +161,20 @@ class LiteralConstructorUsagesTest extends LightCodeInsightFixtureTestCase { assertEquals(2, ReferencesSearch.search(foo.constructors[1]).findAll().size()) } + public void testOverloadedConstructorUsages() throws Exception { + def foo = myFixture.addClass(""" + class Foo { + Foo() {} + Foo(int a) {} + } + """) + + myFixture.addFileToProject "a.gpp", """ + Foo b = [] + Foo b1 = [2] + """ + assertEquals(2, MethodReferencesSearch.search(foo.constructors[0], false).findAll().size()) + assertEquals(2, MethodReferencesSearch.search(foo.constructors[1], false).findAll().size()) + } + } From caca2f772854253e247e7cea2d61ff3f2b8aeaae Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 4 Aug 2010 22:05:57 +0100 Subject: [PATCH 03/18] navigation from literals to the constructors they represent overloaded constructors found in groovy 'new' syntax, too --- .../GroovyConstructorUsagesSearcher.java | 18 ++- .../LiteralConstructorReference.java | 90 +++++++++++++-- .../LiteralConstructorSearcher.java | 9 +- .../groovy/gpp/GppReferenceContributor.java | 107 +++++------------- .../GroovyExpectedTypesProvider.java | 35 ++++-- .../psi/impl/auxiliary/GrListOrMapImpl.java | 11 ++ .../groovy/lang/GppFunctionalTest.groovy | 23 ++++ .../lang/LiteralConstructorUsagesTest.groovy | 10 +- .../lang/findUsages/FindUsagesTest.java | 8 +- 9 files changed, 199 insertions(+), 112 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GroovyConstructorUsagesSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GroovyConstructorUsagesSearcher.java index f1d626e3eeea..6697fcbb68d2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GroovyConstructorUsagesSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GroovyConstructorUsagesSearcher.java @@ -109,7 +109,7 @@ public class GroovyConstructorUsagesSearcher extends QueryExecutorBase getConstructorCandidates(PsiClassType classType, + @NotNull GroovyPsiElement context, @Nullable PsiType[] argTypes) { + PsiClass psiClass = classType.resolve(); + if (psiClass == null) return Collections.emptyList(); + + List applicable = CollectionFactory.arrayList(); + final List byName = CollectionFactory.arrayList(); + for (PsiMethod constructor : psiClass.getConstructors()) { + final ResolveResult resolveResult = new PsiElementResolveResult(constructor); + byName.add(resolveResult); + if (argTypes != null && isConstructorCall(classType, argTypes, constructor, context)) { + applicable.add(resolveResult); + } + } + if (applicable.isEmpty()) { + applicable.addAll(byName); + } + return applicable; + } + + @Nullable + public static PsiClassType getTargetConversionType(@NotNull GrExpression expression) { + //todo hack + if (expression.getParent() instanceof GrSafeCastExpression) { + final PsiType type = ((GrSafeCastExpression)expression.getParent()).getType(); + if (type instanceof PsiClassType) { + return (PsiClassType)type; + } + } + if (expression.getParent() instanceof GrTypeCastExpression) { + final PsiType type = ((GrTypeCastExpression)expression.getParent()).getType(); + if (type instanceof PsiClassType) { + return (PsiClassType)type; + } + } + + for (PsiType type : GroovyExpectedTypesProvider.getDefaultExpectedTypes(expression)) { + if (type instanceof PsiClassType) { + return (PsiClassType)type; + } + } + return null; + } + @Nullable private PsiType[] argTypes() { final GrListOrMap literal = getElement(); @@ -30,7 +95,7 @@ public class LiteralConstructorReference extends PsiReferenceBase.Poly candidates = getConstructorCandidates(myConstructedClass, literal, argTypes()); + return candidates.toArray(new ResolveResult[candidates.size()]); } @NotNull diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorSearcher.java index 5cf0ef6ddf39..8afac2f50637 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorSearcher.java @@ -1,6 +1,5 @@ package org.jetbrains.plugins.groovy.findUsages; -import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiReference; import com.intellij.util.ObjectUtils; @@ -23,7 +22,7 @@ public class LiteralConstructorSearcher { myIncludeOverloads = includeOverloads; } - public boolean processLiteral(GrListOrMap literal, PsiClassType expectedType) { + public boolean processLiteral(GrListOrMap literal) { if (literal.isMap()) { final GrNamedArgument argument = literal.findNamedArgument("super"); if (argument != null) { @@ -31,13 +30,13 @@ public class LiteralConstructorSearcher { } } - return processConstructorReference(new LiteralConstructorReference(literal, expectedType)); + return processConstructorReference(literal.getReference()); } private boolean processConstructorReference(@Nullable PsiReference reference) { if (reference != null && (myIncludeOverloads || reference.isReferenceTo(myConstructor))) { - return myConsumer.process(reference); - } + return myConsumer.process(reference); + } return true; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppReferenceContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppReferenceContributor.java index 91e0f21bb3c4..563ca10694c4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppReferenceContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppReferenceContributor.java @@ -9,54 +9,38 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.ProcessingContext; import com.intellij.util.containers.CollectionFactory; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; -import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.findUsages.LiteralConstructorReference; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSafeCastExpression; -import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider; import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType; import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType; -import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; -import java.util.Collections; import java.util.List; -import java.util.Set; /** * @author peter */ public class GppReferenceContributor extends PsiReferenceContributor { - public static boolean mayInvokeConstructor(PsiClassType expectedType, PsiMethod constructor, GrExpression args) { - if (args == null) { - return true; + @Nullable + private static PsiType[] getSuperConstructorArguments(GrExpression superAttributeValue) { + if (superAttributeValue == null) { + return null; } - final PsiType type = args.getType(); + final PsiType type = superAttributeValue.getType(); if (type == null) { - return true; + return null; } if (type instanceof GrTupleType) { - return isConstructorCall(expectedType, ((GrTupleType)type).getComponentTypes(), constructor, args); + return ((GrTupleType)type).getComponentTypes(); } - return isConstructorCall(expectedType, new PsiType[]{type}, constructor, args); - } - - public static boolean isConstructorCall(PsiClassType expectedType, - PsiType[] argTypes, - PsiMethod constructor, - GroovyPsiElement context) { - for (GroovyResolveResult candidate : PsiUtil.getConstructorCandidates(expectedType, argTypes, context)) { - if (constructor.getManager().areElementsEquivalent(candidate.getElement(), constructor)) { - return true; - } - } - return false; + return new PsiType[]{type}; } @Override @@ -90,67 +74,38 @@ public class GppReferenceContributor extends PsiReferenceContributor { public ResolveResult[] multiResolve(boolean incompleteCode) { final GrArgumentLabel context = getElement(); final GrNamedArgument namedArgument = (GrNamedArgument) context.getParent(); - for (PsiType type : getTargetConversionTypes((GrExpression)namedArgument.getParent())) { - if (type instanceof PsiClassType) { - final PsiClassType classType = (PsiClassType)type; - final PsiClass psiClass = classType.resolve(); - if (psiClass != null) { - final GrExpression value = namedArgument.getExpression(); + final PsiClassType classType = LiteralConstructorReference.getTargetConversionType((GrExpression)namedArgument.getParent()); + if (classType != null) { + final PsiClass psiClass = classType.resolve(); + if (psiClass != null) { + final GrExpression value = namedArgument.getExpression(); - final List applicable = addMethodCandidates(classType, value); + final List applicable = addMethodCandidates(classType, value); - final String memberName = getValue(); - if ("super".equals(memberName) && GppTypeConverter.hasTypedContext(myElement)) { - applicable.addAll(addConstructorCandidates(classType, psiClass, value)); - } + final String memberName = getValue(); + if ("super".equals(memberName) && GppTypeConverter.hasTypedContext(myElement)) { + applicable.addAll(LiteralConstructorReference.getConstructorCandidates(classType, context, getSuperConstructorArguments(value))); + } - if (value == null || applicable.isEmpty()) { - final PsiMethod setter = PropertyUtil.findPropertySetter(psiClass, memberName, false, true); - if (setter != null) { - applicable.add(new PsiElementResolveResult(setter)); - } else { - final PsiField field = PropertyUtil.findPropertyField(psiClass.getProject(), psiClass, memberName, false); - if (field != null) { - applicable.add(new PsiElementResolveResult(field)); - } + if (value == null || applicable.isEmpty()) { + final PsiMethod setter = PropertyUtil.findPropertySetter(psiClass, memberName, false, true); + if (setter != null) { + applicable.add(new PsiElementResolveResult(setter)); + } else { + final PsiField field = PropertyUtil.findPropertyField(psiClass.getProject(), psiClass, memberName, false); + if (field != null) { + applicable.add(new PsiElementResolveResult(field)); } } - - return applicable.toArray(new ResolveResult[applicable.size()]); } + + return applicable.toArray(new ResolveResult[applicable.size()]); } } + return ResolveResult.EMPTY_ARRAY; } - private static Set getTargetConversionTypes(GrExpression expression) { - //todo hack - if (expression.getParent() instanceof GrSafeCastExpression) { - final PsiType type = ((GrSafeCastExpression)expression.getParent()).getType(); - if (type != null) { - return Collections.singleton(type); - } - } - - return GroovyExpectedTypesProvider.getDefaultExpectedTypes(expression); - } - - - private static List addConstructorCandidates(PsiClassType classType, PsiClass psiClass, GrExpression value) { - List applicable = CollectionFactory.arrayList(); - final List byName = CollectionFactory.arrayList(); - for (PsiMethod constructor : psiClass.getConstructors()) { - final ResolveResult resolveResult = new PsiElementResolveResult(constructor); - byName.add(resolveResult); - if (mayInvokeConstructor(classType, constructor, value)) { - applicable.add(resolveResult); - } - } - if (applicable.isEmpty()) { - applicable.addAll(byName); - } - return applicable; - } private List addMethodCandidates(PsiClassType classType, GrExpression value) { PsiType valueType = value == null ? null : value.getType(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java index 4e88b3b348ec..7f7705c0d2fa 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java @@ -21,6 +21,8 @@ import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.*; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; @@ -37,6 +39,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryE import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; +import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; @@ -142,14 +145,9 @@ public class GroovyExpectedTypesProvider { @Override public void visitOpenBlock(GrOpenBlock block) { - if (block.getParent() instanceof PsiMethod) { - final GrStatement[] statements = block.getStatements(); - if (statements.length > 0 && myExpression.equals(statements[statements.length - 1])) { - final PsiType type = ((PsiMethod)block.getParent()).getReturnType(); - if (type != null) { - myResult = new TypeConstraint[]{new SubtypeConstraint(type, type)}; - } - } + final GrStatement[] statements = block.getStatements(); + if (statements.length > 0 && myExpression.equals(statements[statements.length - 1])) { + checkExitPoint(); } } @@ -157,6 +155,27 @@ public class GroovyExpectedTypesProvider { if (myExpression.equals(ifStatement.getCondition())) { myResult = new TypeConstraint[]{new SubtypeConstraint(TypesUtil.getJavaLangObject(ifStatement), PsiType.BOOLEAN)}; } + else if (myExpression.equals(ifStatement.getThenBranch()) || myExpression.equals(ifStatement.getElseBranch())) { + checkExitPoint(); + } + } + + private void checkExitPoint() { + final PsiElement element = PsiTreeUtil.getParentOfType(myExpression, PsiMethod.class, GrClosableBlock.class); + if (element instanceof GrMethod) { + final GrMethod method = (GrMethod)element; + ControlFlowUtils.visitAllExitPoints(method.getBlock(), new ControlFlowUtils.ExitPointVisitor() { + @Override + public boolean visitExitPoint(Instruction instruction, @Nullable GrExpression returnValue) { + if (returnValue == myExpression) { + final PsiType returnType = method.getReturnType(); + myResult = new TypeConstraint[]{new SubtypeConstraint(returnType, returnType)}; + return false; + } + return true; + } + }); + } } public void visitWhileStatement(GrWhileStatement whileStatement) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java index 77c33eb34ab6..53867b119ecf 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java @@ -24,6 +24,7 @@ import com.intellij.psi.tree.TokenSet; import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.findUsages.LiteralConstructorReference; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; @@ -103,6 +104,16 @@ public class GrListOrMapImpl extends GrExpressionImpl implements GrListOrMap { return null; } + @Override + public PsiReference getReference() { + final PsiClassType conversionType = LiteralConstructorReference.getTargetConversionType(this); + if (conversionType != null) { + return new LiteralConstructorReference(this, conversionType); + } + + return null; + } + private static class MyTypesCalculator implements Function { @Nullable public PsiType fun(GrListOrMapImpl listOrMap) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy index 9dc6436c8373..8c61002d1d16 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy @@ -407,6 +407,29 @@ class Point { assertEquals 2, multiResolveReference().size() } + public void testGotoSuperConstructorFromLiteralOnsets() throws Exception { + PsiClass point = myFixture.addClass(""" +class Point { + Point() {} + Point(int y) {} +}""") + + configureGppScript "Point p = [super: 2]" + assertEquals point.constructors[1], resolveReference() + + configureGppScript "Point p = [2]" + assertEquals point.constructors[1], resolveReference() + + configureGppScript "Point p = []" + assertEquals point.constructors[0], resolveReference() + + configureGppScript "Point p = [:]" + assertEquals point.constructors[0], resolveReference() + + configureGppScript "Point p = [239, 42]" + assertEquals 2, multiResolveReference().size() + } + public void testResolveTraitMethod() throws Exception { configureScript """ @Trait diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/LiteralConstructorUsagesTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/LiteralConstructorUsagesTest.groovy index 3e97b48a842c..73a53fb5b441 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/LiteralConstructorUsagesTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/LiteralConstructorUsagesTest.groovy @@ -27,8 +27,14 @@ class LiteralConstructorUsagesTest extends LightCodeInsightFixtureTestCase { Foo() {} } """) - myFixture.addFileToProject "a.groovy", "Foo foo() { if (true) [] else return [] }" - assertEquals(2, ReferencesSearch.search(foo.constructors[0]).findAll().size()) + myFixture.addFileToProject "a.groovy", """ +Foo foo() { + if (true) [] + else return [] +} +Foo bar() { [] } +""" + assertEquals(3, ReferencesSearch.search(foo.constructors[0]).findAll().size()) } public void testList_Cast() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java index 224db22aa5a1..ed398d693eb6 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java @@ -71,7 +71,13 @@ public class FindUsagesTest extends LightGroovyTestCase { } public void testConstructorUsageInNewExpression() throws Throwable { - doTestImpl("ConstructorUsageInNewExpression.groovy", 2); + myFixture.configureByFile("ConstructorUsageInNewExpression.groovy"); + final PsiElement resolved = TargetElementUtilBase.findTargetElement(myFixture.getEditor(), + TargetElementUtilBase.getInstance().getReferenceSearchFlags()); + assertNotNull("Could not resolve reference", resolved); + final GlobalSearchScope projectScope = GlobalSearchScope.projectScope(myFixture.getProject()); + assertEquals(2, MethodReferencesSearch.search((PsiMethod)resolved, projectScope, true).findAll().size()); + assertEquals(4, MethodReferencesSearch.search((PsiMethod)resolved, projectScope, false).findAll().size()); } public void testGotoConstructor() throws Throwable { From e43cdebd16ea8244676636dd92ec21d6bf3aa6f5 Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 5 Aug 2010 09:08:01 +0400 Subject: [PATCH 04/18] correctly fixed not-null instrumentation for enums (IDEA-56943) --- .../NotNullVerifyingInstrumenter.java | 6 ++--- .../EnumConstructorSecondParam.java | 23 +++++++++++++++++++ .../NotNullVerifyingInstrumenterTest.java | 6 +++++ 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/compiler/notNullVerification/EnumConstructorSecondParam.java diff --git a/java/compiler/notNull/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java b/java/compiler/notNull/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java index 7990ab4d73f1..62cf1608aa7d 100644 --- a/java/compiler/notNull/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java +++ b/java/compiler/notNull/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java @@ -122,8 +122,8 @@ public class NotNullVerifyingInstrumenter extends ClassAdapter implements Opcode } for (int p = 0; p < myNotNullParams.size(); ++p) { int var = ((access & ACC_STATIC) == 0) ? 1 : 0; - int param = ((Integer)myNotNullParams.get(p)).intValue() - mySyntheticCount; - for (int i = 0; i < param + startParameter; ++i) { + int param = ((Integer)myNotNullParams.get(p)).intValue(); + for (int i = 0; i < startParameter + param; ++i) { var += args[i].getSize(); } mv.visitVarInsn(ALOAD, var); @@ -132,7 +132,7 @@ public class NotNullVerifyingInstrumenter extends ClassAdapter implements Opcode mv.visitJumpInsn(IFNONNULL, end); generateThrow(IAE_CLASS_NAME, - "Argument " + param + " for @NotNull parameter of " + myClassName + "." + name + " must not be null", end); + "Argument " + (param - mySyntheticCount) + " for @NotNull parameter of " + myClassName + "." + name + " must not be null", end); } } diff --git a/java/java-tests/testData/compiler/notNullVerification/EnumConstructorSecondParam.java b/java/java-tests/testData/compiler/notNullVerification/EnumConstructorSecondParam.java new file mode 100644 index 000000000000..2081b5fa7142 --- /dev/null +++ b/java/java-tests/testData/compiler/notNullVerification/EnumConstructorSecondParam.java @@ -0,0 +1,23 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import org.jetbrains.annotations.NotNull; + +public enum EnumConstructorSecondParam { + Value("1", "2"); + + EnumConstructorSecondParam(String s1, @NotNull String s2) { + } +} diff --git a/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java b/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java index 12f5e0aa4f84..e8d6dd9d56cf 100644 --- a/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java +++ b/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java @@ -63,6 +63,12 @@ public class NotNullVerifyingInstrumenterTest extends UsefulTestCase { assertNotNull(field); } + public void testEnumConstructorSecondParam() throws Exception { + Class testClass = prepareTest(); + Object field = testClass.getField("Value"); + assertNotNull(field); + } + private static void verifyCallThrowsException(final String expectedError, final Object instance, final Method method, final Object... args) throws IllegalAccessException { String exceptionText = null; try { From a3366f371cb083ecbaeff083cd2a8758706101cf Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 5 Aug 2010 10:09:41 +0400 Subject: [PATCH 05/18] IDEA-56359 Soft wrap: commas could append previous symbol when wrapping 1. Added mini unit test framework for soft wrap appliance tests; 2. Corrected soft wrap appliance algorithm in order to avoid wrapping before comma; --- ...DefaultEditorTextRepresentationHelper.java | 6 +- .../impl/EditorTextRepresentationHelper.java | 13 +- .../editor/impl/SoftWrapModelImpl.java | 10 +- .../DefaultSoftWrapApplianceManager.java | 31 ++- .../impl/softwrap/SoftWrapDataMapper.java | 9 +- .../DefaultSoftWrapApplianceManagerTest.java | 196 ++++++++++++++++++ .../MockEditorTextRepresentationHelper.java | 83 ++++++++ .../impl/softwrap/SoftWrapDataMapperTest.java | 66 +----- 8 files changed, 329 insertions(+), 85 deletions(-) create mode 100644 platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManagerTest.java create mode 100644 platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/MockEditorTextRepresentationHelper.java diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/DefaultEditorTextRepresentationHelper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/DefaultEditorTextRepresentationHelper.java index 790256ccfcd5..204c3c99a4d2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/DefaultEditorTextRepresentationHelper.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/DefaultEditorTextRepresentationHelper.java @@ -19,8 +19,6 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ex.util.EditorUtil; import org.jetbrains.annotations.NotNull; -import java.awt.*; - /** * @author Denis Zhdanov * @since Jul 27, 2010 4:06:27 PM @@ -39,7 +37,7 @@ public class DefaultEditorTextRepresentationHelper implements EditorTextRepresen } @Override - public int textWidth(@NotNull CharSequence text, int start, int end, int x) { - return EditorUtil.textWidth(myEditor, text, start, end, Font.PLAIN, x); + public int textWidth(@NotNull CharSequence text, int start, int end, int fontType, int x) { + return EditorUtil.textWidth(myEditor, text, start, end, fontType, x); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorTextRepresentationHelper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorTextRepresentationHelper.java index fcf97a1f59be..640cfdc38f52 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorTextRepresentationHelper.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorTextRepresentationHelper.java @@ -48,11 +48,12 @@ public interface EditorTextRepresentationHelper { * Note: target region is allows to contain line feeds, the width is calculated as a difference between 'x' * coordinates of the last and first symbols. * - * @param text target text holder - * @param start start offset of the target text sub-sequence (inclusive) - * @param end end offset of the target text sub-sequence (exclusive) - * @param x 'x' offset from the visual line start - * @return width in pixels necessary for the target text sub-sequence representation + * @param text target text holder + * @param start start offset of the target text sub-sequence (inclusive) + * @param end end offset of the target text sub-sequence (exclusive) + * @param fontType font type used for the given substring representation + * @param x 'x' offset from the visual line start + * @return width in pixels necessary for the target text sub-sequence representation */ - int textWidth(@NotNull CharSequence text, int start, int end, int x); + int textWidth(@NotNull CharSequence text, int start, int end, int fontType, int x); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index dbc0f41192d5..c1283a0b4a02 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -58,10 +58,14 @@ public class SoftWrapModelImpl implements SoftWrapModelEx { } public SoftWrapModelImpl(@NotNull final EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter) { + this(editor, storage, painter, new DefaultEditorTextRepresentationHelper(editor)); + } + + public SoftWrapModelImpl(@NotNull final EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter, + EditorTextRepresentationHelper representationHelper) { this( - editor, storage, painter, new DefaultSoftWrapApplianceManager(storage, editor, painter), - new SoftWrapDataMapper(editor, storage, new DefaultEditorTextRepresentationHelper(editor)), - new SoftWrapDocumentChangeManager(editor, storage) + editor, storage, painter, new DefaultSoftWrapApplianceManager(storage, editor, painter, representationHelper), + new SoftWrapDataMapper(editor, storage, representationHelper), new SoftWrapDocumentChangeManager(editor, storage) ); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java index 89cd087c580f..ae37f75e8c83 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java @@ -20,6 +20,7 @@ import com.intellij.openapi.editor.VisualPosition; import com.intellij.openapi.editor.actions.EditorActionUtil; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.util.EditorUtil; +import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -103,16 +104,22 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager private final TIntHashSet myProcessedLogicalLines = new TIntHashSet(); - private final SoftWrapsStorage myStorage; - private final EditorEx myEditor; - private final SoftWrapPainter myPainter; + private final EditorTextRepresentationHelper myTextRepresentationHelper; + private final SoftWrapsStorage myStorage; + private final EditorEx myEditor; + private final SoftWrapPainter myPainter; private int myVisibleAreaWidth; - public DefaultSoftWrapApplianceManager(SoftWrapsStorage storage, EditorEx editor, SoftWrapPainter painter) { + public DefaultSoftWrapApplianceManager(SoftWrapsStorage storage, + EditorEx editor, + SoftWrapPainter painter, + EditorTextRepresentationHelper textRepresentationHelper) + { myStorage = storage; myEditor = editor; myPainter = painter; + myTextRepresentationHelper = textRepresentationHelper; init(editor.getDocument()); } @@ -215,10 +222,11 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager // Find offsets where soft wraps should be applied for the logical line in case of no indent usage. int x = myPainter.getMinDrawingWidth(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED); int prevSoftWrapOffset = start; + CharBuffer buffer = CharBuffer.wrap(text); for (int i = start; i < end; i++) { - int symbolWidth = EditorUtil.textWidth(myEditor, CharBuffer.wrap(text), i, i + 1, fontType, x); + int symbolWidth = myTextRepresentationHelper.textWidth(buffer, i, i + 1, fontType, x); if (x + symbolWidth >= myVisibleAreaWidth) { - int offset = calculateSoftWrapOffset(text, i - 1, prevSoftWrapOffset, end); + int offset = calculateSoftWrapOffset(text, i, prevSoftWrapOffset, end); if (offset >= end || offset <= prevSoftWrapOffset) { // There is no way to insert soft wrap. return result; @@ -272,8 +280,8 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager for (int i = preferred; i > min; i--) { char c = text[i]; - if (i < preferred && WHITE_SPACES.contains(c)) { - return i + 1; + if (WHITE_SPACES.contains(c)) { + return i < preferred ? i + 1 : i; } // Don't wrap on the non-id symbol preceded by another non-id symbol. E.g. consider that we have a statement @@ -281,8 +289,11 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager if (i > min + 1 && !isIdSymbol(c) && !isIdSymbol(text[i - 1])) { continue; } - if ((i < preferred) && SPECIAL_SYMBOLS_TO_WRAP_AFTER.contains(c)) { - return i + 1; + if (SPECIAL_SYMBOLS_TO_WRAP_AFTER.contains(c)) { + if (i < preferred) { + return i + 1; + } + continue; } if (SPECIAL_SYMBOLS_TO_WRAP_BEFORE.contains(c) || WHITE_SPACES.contains(c)) { return i; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapper.java index 87889a12274a..c162cdaafdde 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapper.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapper.java @@ -23,6 +23,7 @@ import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.awt.*; import java.util.List; /** @@ -264,7 +265,7 @@ public class SoftWrapDataMapper { int i = CharArrayUtil.shiftBackwardUntil(text, region.getEndOffset() - 1, "\n"); // Process multi-line folding. if (i >= region.getStartOffset()) { - afterFolding.x = myTextRepresentationHelper.textWidth(text, i + 1, region.getEndOffset(), 0); + afterFolding.x = myTextRepresentationHelper.textWidth(text, i + 1, region.getEndOffset(), Font.PLAIN, 0); afterFolding.logicalColumn = myTextRepresentationHelper.toVisualColumnSymbolsNumber(text, i + 1, region.getEndOffset(), 0); afterFolding.softWrapLinesBefore += afterFolding.softWrapLinesCurrent; afterFolding.softWrapLinesCurrent = 0; @@ -274,7 +275,7 @@ public class SoftWrapDataMapper { } // Process single-line folding else { - int width = myTextRepresentationHelper.textWidth(text, region.getStartOffset(), region.getEndOffset(), context.x); + int width = myTextRepresentationHelper.textWidth(text, region.getStartOffset(), region.getEndOffset(), Font.PLAIN, context.x); int logicalColumnInc = myTextRepresentationHelper.toVisualColumnSymbolsNumber( text, region.getStartOffset(), region.getEndOffset(), context.x ); @@ -342,7 +343,7 @@ public class SoftWrapDataMapper { // Update state to the offset that corresponds to the same logical line that was used last time. if (currentLogicalLine == lastUsedLogicalLine) { - int width = myTextRepresentationHelper.textWidth(text, result.offset, newOffset, result.x); + int width = myTextRepresentationHelper.textWidth(text, result.offset, newOffset, Font.PLAIN, result.x); int columnDiff = myTextRepresentationHelper.toVisualColumnSymbolsNumber(text, result.offset, newOffset, result.x); result.x += width; result.logicalColumn += columnDiff; @@ -354,7 +355,7 @@ public class SoftWrapDataMapper { result.logicalLine += lineDiff; result.visualLine += lineDiff; int startLineOffset = document.getLineStartOffset(currentLogicalLine); - int newX = myTextRepresentationHelper.textWidth(text, startLineOffset, newOffset, result.x); + int newX = myTextRepresentationHelper.textWidth(text, startLineOffset, newOffset, Font.PLAIN, result.x); result.visualColumn = myTextRepresentationHelper.toVisualColumnSymbolsNumber(text, startLineOffset, newOffset, 0); result.x = newX; result.logicalColumn = result.visualColumn; diff --git a/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManagerTest.java b/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManagerTest.java new file mode 100644 index 000000000000..3baa67b01c81 --- /dev/null +++ b/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManagerTest.java @@ -0,0 +1,196 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.editor.impl.softwrap; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.ScrollingModel; +import com.intellij.openapi.editor.event.DocumentListener; +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.util.text.StringUtil; +import org.jmock.Expectations; +import org.junit.Test; +import org.junit.Before; +import org.junit.After; +import org.jmock.integration.junit4.JUnit4Mockery; +import org.jmock.Mockery; +import org.jmock.lib.legacy.ClassImposteriser; + +import java.awt.*; +import java.util.Collections; + +/** + * @author Denis Zhdanov + * @since 08/04/2010 + */ +public class DefaultSoftWrapApplianceManagerTest { + + private static final String EDGE_MARKER = ""; + private static final String WRAP_MARKER = ""; + private static final int SOFT_WRAP_DRAWING_SIZE = 11; + + private DefaultSoftWrapApplianceManager myManager; + private Mockery myMockery; + private SoftWrapsStorage myStorage; + private EditorEx myEditor; + private SoftWrapPainter myPainter; + private Document myDocument; + private ScrollingModel myScrollingModel; + + @Before + public void setUp() { + myMockery = new JUnit4Mockery() {{ + setImposteriser(ClassImposteriser.INSTANCE); + }}; + myStorage = myMockery.mock(SoftWrapsStorage.class); + myEditor = myMockery.mock(EditorEx.class); + myPainter = myMockery.mock(SoftWrapPainter.class); + myDocument = myMockery.mock(Document.class); + myScrollingModel = myMockery.mock(ScrollingModel.class); + + myMockery.checking(new Expectations() {{ + // Editor. + allowing(myEditor).isViewer(); will(returnValue(false)); + + // Document. + allowing(myEditor).getDocument(); will(returnValue(myDocument)); + allowing(myDocument).addDocumentListener(with(any(DocumentListener.class))); + allowing(myDocument).getLineNumber(with(any(int.class))); will(returnValue(0)); // Expecting to work only with single lines here. + allowing(myDocument).getLineStartOffset(0); will(returnValue(0)); // Expecting to work only with single lines here. + allowing(myDocument).isWritable(); will(returnValue(true)); + + // Scrolling model. + allowing(myEditor).getScrollingModel(); will(returnValue(myScrollingModel)); + + // Storage. + allowing(myStorage).removeAll(); + + // Soft wrap drawings. + allowing(myPainter).getMinDrawingWidth(with(any(SoftWrapDrawingType.class))); will(returnValue(SOFT_WRAP_DRAWING_SIZE)); + }}); + + myManager = new DefaultSoftWrapApplianceManager(myStorage, myEditor, myPainter, new MockEditorTextRepresentationHelper()); + } + + @After + public void checkExpectations() { + myMockery.assertIsSatisfied(); + } + + @Test + public void commaNotSeparated() { + String document = + "void method(String p1, String p2) {}"; + doTest(document); + } + + @Test + public void wrapOnExceedingWhiteSpace() { + String document = + "void method(String p1, String p2) {}"; + doTest(document); + } + + private void doTest(final String document) { + final Context context = new Context(document); + context.init(); + myMockery.checking(new Expectations() {{ + allowing(myScrollingModel).getVisibleArea(); will(returnValue(new Rectangle(0, 0, context.visualWidth, Integer.MAX_VALUE))); + allowing(myDocument).getLineEndOffset(0); will(returnValue(context.document.length())); + }}); + char[] documentChars = context.document.toCharArray(); + myManager.registerSoftWrapIfNecessary(documentChars, 0, documentChars.length, 0, Font.PLAIN); + } + + private static TextChangeImpl createSoftWrap(int offset, int indent) { + String text = "\n" + StringUtil.join(Collections.nCopies(indent, " "), ""); + return new TextChangeImpl(text, offset, offset); + } + + /** + * Utility class for parsing and initialising test data. + *

+ * Note: this class is line-oriented, i.e. it assumes that target document doesn't contain line feeds. + */ + private class Context { + + private final StringBuilder buffer = new StringBuilder(); + private final String rawDocument; + + private String document; + private int visualWidth; + private int index; + private int wrapIndex; + private int edgeIndex; + + Context(String rawDocument) { + if (rawDocument.contains("\n")) { + throw new IllegalArgumentException( + String.format("Don't expect to test multi-line documents but the one is detected: '%s'", rawDocument) + ); + } + this.rawDocument = rawDocument; + } + + public void init() { + wrapIndex = rawDocument.indexOf(WRAP_MARKER); + edgeIndex = rawDocument.indexOf(EDGE_MARKER); + while (wrapIndex >= 0 || edgeIndex >= 0) { + if (wrapIndex >= 0 && edgeIndex >= 0) { + if (wrapIndex < edgeIndex) { + processWrap(); + } + else { + processEdge(); + } + continue; + } + + if (wrapIndex >= 0) { + processWrap(); + continue; + } + + if (edgeIndex >= 0) { + processEdge(); + continue; + } + break; + } + buffer.append(rawDocument.substring(index)); + assert visualWidth > 0; + document = buffer.toString(); + } + + private void processWrap() { + buffer.append(rawDocument.substring(index, wrapIndex)); + myMockery.checking(new Expectations() {{ + one(myStorage).storeOrReplace(createSoftWrap(buffer.length(), 0)); + }}); + index = wrapIndex + WRAP_MARKER.length(); + wrapIndex = rawDocument.indexOf(WRAP_MARKER, index); + } + + private void processEdge() { + if (visualWidth > 0) { + throw new IllegalArgumentException(String.format("More than one visual edge sign found at the document '%s'", rawDocument)); + } + buffer.append(rawDocument.substring(index, edgeIndex)); + visualWidth = (buffer.length() * MockEditorTextRepresentationHelper.DEFAULT_SPACE_SIZE_IN_PIXELS) + SOFT_WRAP_DRAWING_SIZE + 1; + index = edgeIndex + EDGE_MARKER.length(); + edgeIndex = rawDocument.indexOf(EDGE_MARKER, index); + } + } +} diff --git a/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/MockEditorTextRepresentationHelper.java b/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/MockEditorTextRepresentationHelper.java new file mode 100644 index 000000000000..1c273ab05379 --- /dev/null +++ b/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/MockEditorTextRepresentationHelper.java @@ -0,0 +1,83 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.editor.impl.softwrap; + +import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; +import org.jetbrains.annotations.NotNull; + +/** +* @author Denis Zhdanov +* @since Aug 5, 2010 9:18:15 AM +*/ +public class MockEditorTextRepresentationHelper implements EditorTextRepresentationHelper { + + public static final int DEFAULT_TAB_SIZE_IN_COLUMNS = 4; + public static final int DEFAULT_SPACE_SIZE_IN_PIXELS = 7; + + private final int mySpaceSizeInPixels; + private final int myTabSizeInColumns; + + public MockEditorTextRepresentationHelper() { + this(DEFAULT_SPACE_SIZE_IN_PIXELS, DEFAULT_TAB_SIZE_IN_COLUMNS); + } + + MockEditorTextRepresentationHelper(int spaceSizeInPixels, int tabSizeInColumns) { + mySpaceSizeInPixels = spaceSizeInPixels; + myTabSizeInColumns = tabSizeInColumns; + } + + public int toVisualColumnSymbolsNumber(char c, int x) { + return toVisualColumnSymbolsNumber(new String(new char[] {c}), 0, 1, x); + } + + @Override + public int toVisualColumnSymbolsNumber(@NotNull CharSequence text, int start, int end, int x) { + int result = 0; + for (int i = start; i < end; i++) { + int width = charWidth(text.charAt(i), x); + result += width / mySpaceSizeInPixels; + if (width % mySpaceSizeInPixels > 0) { + result++; + } + x += width; + } + return result; + } + + @Override + public int textWidth(@NotNull CharSequence text, int start, int end, int fontType, int x) { + int result = 0; + for (int i = start; i < end; i++) { + char c = text.charAt(i); + switch (c) { + case '\n': result = 0; break; + default: result += charWidth(c, result); + } + } + return result; + } + + public int charWidth(char c, int x) { + if (c == '\t') { + int tabWidth = mySpaceSizeInPixels * myTabSizeInColumns; + int tabsNumber = x / tabWidth; + return (tabsNumber + 1) * tabWidth - x; + } + else { + return mySpaceSizeInPixels; + } + } +} diff --git a/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapperTest.java b/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapperTest.java index a1dd059acccb..16dc3764f6ef 100644 --- a/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapperTest.java +++ b/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapperTest.java @@ -5,11 +5,9 @@ import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.FoldingModelEx; import com.intellij.openapi.editor.ex.SoftWrapModelEx; -import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import gnu.trove.TIntHashSet; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jmock.Expectations; import org.jmock.Mockery; @@ -21,6 +19,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +import java.awt.*; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -207,7 +206,7 @@ public class SoftWrapDataMapperTest { allowing(painter).getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP); will(returnValue(SOFT_WRAP_DRAWING_WIDTH)); }}); - myRepresentationHelper = new MockEditorTextRepresentationHelper(); + myRepresentationHelper = new MockEditorTextRepresentationHelper(SPACE_SIZE, TAB_SIZE); myAdjuster = new SoftWrapDataMapper(myEditor, myStorage, myRepresentationHelper/*, new MockFontTypeProvider()*/); } @@ -398,7 +397,7 @@ public class SoftWrapDataMapperTest { if (text.charAt(i) == '\n') { break; } - result += myRepresentationHelper.textWidth(text, i, i + 1, 0); + result += myRepresentationHelper.textWidth(text, i, i + 1, Font.PLAIN, 0); } result += SOFT_WRAP_DRAWING_WIDTH; return result; @@ -493,8 +492,6 @@ public class SoftWrapDataMapperTest { // We don't want to perform the check for logical positions that correspond to the folded space because all of them relate to // the same logical position of the folding start. if (!data.foldedSpace && !data.insideTab && !equals(data.logical, actualLogicalByVisual)) { - //TODO den remove - myAdjuster.visualToLogical(data.visual); throw new AssertionError( String.format("Detected unmatched logical position by visual (%s). Expected: '%s', actual: '%s'. Calculation was performed " + "against soft wrap-unaware logical: '%s'", @@ -507,8 +504,6 @@ public class SoftWrapDataMapperTest { // We don't to perform the check for the data that points to soft wrap location here. The reason is that it shares offset // with the first document symbol after soft wrap, hence, examination always fails. if (!data.virtualSpace && !data.insideTab && !equals(data.logical, actualLogicalByOffset)) { - //TODO den remove - myAdjuster.offsetToLogicalPosition(data.offset); throw new AssertionError( String.format("Detected unmatched logical position by offset. Expected: '%s', actual: '%s'. Calculation was performed " + "against offset: '%d' and soft wrap-unaware logical: '%s'", @@ -698,7 +693,7 @@ public class SoftWrapDataMapperTest { } else if (c == '\t') { int tabWidthInColumns = myRepresentationHelper.toVisualColumnSymbolsNumber(c, x); - x += MockEditorTextRepresentationHelper.charWidth(c, x); + x += myRepresentationHelper.charWidth(c, x); // There is a possible case that single tabulation symbols is shown in more than one visual column at IntelliJ editor. // We store data entry only for the first tab column without 'inside tab' flag then. @@ -715,7 +710,7 @@ public class SoftWrapDataMapperTest { } else { logicalColumn++; offset++; - x += MockEditorTextRepresentationHelper.charWidth(c, x); + x += myRepresentationHelper.charWidth(c, x); foldingColumnDiff--; } return; @@ -748,7 +743,7 @@ public class SoftWrapDataMapperTest { visualColumn++; softWrapColumnDiff++; softWrapSymbolsOnCurrentVisualLine++; - x += MockEditorTextRepresentationHelper.charWidth(c, x); + x += myRepresentationHelper.charWidth(c, x); } return; } @@ -769,7 +764,7 @@ public class SoftWrapDataMapperTest { } else if (c == '\t') { int tabWidthInColumns = myRepresentationHelper.toVisualColumnSymbolsNumber(c, x); - x += MockEditorTextRepresentationHelper.charWidth(c, x); + x += myRepresentationHelper.charWidth(c, x); // There is a possible case that single tabulation symbols is shown in more than one visual column at IntelliJ editor. // We store data entry only for the first tab column without 'inside tab' flag then. @@ -789,7 +784,7 @@ public class SoftWrapDataMapperTest { visualColumn++; logicalColumn++; offset++; - x += MockEditorTextRepresentationHelper.charWidth(c, x); + x += myRepresentationHelper.charWidth(c, x); } } @@ -838,51 +833,6 @@ public class SoftWrapDataMapperTest { } } - private static class MockEditorTextRepresentationHelper implements EditorTextRepresentationHelper { - - public int toVisualColumnSymbolsNumber(char c, int x) { - return toVisualColumnSymbolsNumber(new String(new char[] {c}), 0, 1, x); - } - - @Override - public int toVisualColumnSymbolsNumber(@NotNull CharSequence text, int start, int end, int x) { - int result = 0; - for (int i = start; i < end; i++) { - int width = charWidth(text.charAt(i), x); - result += width / SPACE_SIZE; - if (width % SPACE_SIZE > 0) { - result++; - } - x += width; - } - return result; - } - - @Override - public int textWidth(@NotNull CharSequence text, int start, int end, int x) { - int result = 0; - for (int i = start; i < end; i++) { - char c = text.charAt(i); - switch (c) { - case '\n': result = 0; break; - default: result += charWidth(c, result); - } - } - return result; - } - - public static int charWidth(char c, int x) { - if (c == '\t') { - int tabWidth = SPACE_SIZE * TAB_SIZE; - int tabsNumber = x / tabWidth; - return (tabsNumber + 1) * tabWidth - x; - } - else { - return SPACE_SIZE; - } - } - } - //private static class MockFontTypeProvider implements SoftWrapDataMapper.FontTypeProvider { // @Override // public void init(int start) { From b466cc4026e10d3d3cd2d6d9ca54e012bd7f69f3 Mon Sep 17 00:00:00 2001 From: "Rustam.Vishnyakov" Date: Thu, 5 Aug 2010 12:09:21 +0400 Subject: [PATCH 06/18] IDEA-21113: Formatting for auto-generated CDATA section in mx:Script blocks --- .../psi/codeStyle/CodeStyleSettings.java | 8 ++++++++ .../formatter/xml/AbstractSyntheticBlock.java | 5 +++++ .../psi/formatter/xml/AbstractXmlBlock.java | 9 +++++++++ .../psi/formatter/xml/HtmlPolicy.java | 10 ++++++++++ .../psi/formatter/xml/SyntheticBlock.java | 13 +++++++++++++ .../intellij/psi/formatter/xml/XmlBlock.java | 2 +- .../formatter/xml/XmlFormattingPolicy.java | 4 ++++ .../intellij/psi/formatter/xml/XmlPolicy.java | 10 ++++++++++ .../psi/formatter/xml/XmlTagBlock.java | 19 +++++++++++++++++++ .../psi/impl/source/xml/XmlTextImpl.java | 16 ++++++++++++---- 10 files changed, 91 insertions(+), 5 deletions(-) diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java index a3a4de778af6..c6c2b7572eac 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java @@ -1095,6 +1095,11 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { // ---------------------------------- XML formatting options ------------------------- + + public final static int WS_AROUND_CDATA_PRESERVE = 0; + public final static int WS_AROUND_CDATA_NONE = 1; + public final static int WS_AROUND_CDATA_NEW_LINES = 2; + public boolean XML_KEEP_WHITESPACES = false; public int XML_ATTRIBUTE_WRAP = WRAP_AS_NEEDED; public int XML_TEXT_WRAP = WRAP_AS_NEEDED; @@ -1110,6 +1115,9 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { public boolean XML_SPACE_AFTER_TAG_NAME = false; public boolean XML_SPACE_INSIDE_EMPTY_TAG = false; + public boolean XML_KEEP_WHITE_SPACES_INSIDE_CDATA = false; + public int XML_WHITE_SPACE_AROUND_CDATA = WS_AROUND_CDATA_PRESERVE; + // --------------------------------------------------------------------------------------- // ---------------------------------- HTML formatting options ------------------------- diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractSyntheticBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractSyntheticBlock.java index 5bb57c207c35..0eb42a2f0fc0 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractSyntheticBlock.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractSyntheticBlock.java @@ -198,6 +198,11 @@ public abstract class AbstractSyntheticBlock implements Block { return node != null && node.getElementType() == XmlElementType.XML_CDATA; } + public boolean containsCDATA() { + return myStartTreeNode.getElementType() == XmlElementType.XML_CDATA_START && + myEndTreeNode.getElementType() == XmlElementType.XML_CDATA_END; + } + public boolean endsWithCDATA() { return isCDATA(myStartTreeNode.getLastChildNode()); } diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java index e21f7f74d3c2..fd0f52fd503f 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java @@ -414,4 +414,13 @@ public abstract class AbstractXmlBlock extends AbstractBlock { return false; } + + public boolean isCDATAStart() { + return myNode.getElementType() == XmlElementType.XML_CDATA_START; + } + + public boolean isCDATAEnd() { + return myNode.getElementType() == XmlElementType.XML_CDATA_END; + } + } diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/HtmlPolicy.java b/xml/impl/src/com/intellij/psi/formatter/xml/HtmlPolicy.java index f3e35acaff1d..be96c21df13d 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/HtmlPolicy.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/HtmlPolicy.java @@ -211,6 +211,16 @@ public class HtmlPolicy extends XmlFormattingPolicy { return mySettings.HTML_KEEP_LINE_BREAKS_IN_TEXT; } + @Override + public boolean getKeepWhiteSpacesInsideCDATA() { + return true; + } + + @Override + public int getWhiteSpaceAroundCDATAOption() { + return CodeStyleSettings.WS_AROUND_CDATA_PRESERVE; + } + public CodeStyleSettings getSettings() { return mySettings; } diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/SyntheticBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/SyntheticBlock.java index af5056555479..b4f878dd815b 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/SyntheticBlock.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/SyntheticBlock.java @@ -62,6 +62,19 @@ public class SyntheticBlock extends AbstractSyntheticBlock implements Block, Rea boolean firstIsText = isTextFragment(node1); boolean secondIsText = isTextFragment(node2); + if (type1 == XmlElementType.XML_CDATA_START || type2 == XmlElementType.XML_CDATA_END) { + if (myXmlFormattingPolicy.getKeepWhiteSpacesInsideCDATA()) { + return Spacing.getReadOnlySpacing(); + } + if (type1 == XmlElementType.XML_CDATA_START && type2 == XmlElementType.XML_CDATA_END) { + return Spacing.createSpacing(0, 0, 0, myXmlFormattingPolicy.getShouldKeepLineBreaks(), 0); + } + if (type1 == XmlElementType.XML_CDATA_START && child2 instanceof AnotherLanguageBlockWrapper || + type2 == XmlElementType.XML_CDATA_END && child1 instanceof AnotherLanguageBlockWrapper) { + return Spacing.createSpacing(0, 0, 1, myXmlFormattingPolicy.getShouldKeepLineBreaks(), 0); + } + } + boolean firstIsTag = node1.getPsi() instanceof XmlTag && !firstIsText; boolean secondIsTag = node2.getPsi() instanceof XmlTag && !secondIsText; diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java index 88701d97e4ea..1686c7f53c12 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java @@ -56,7 +56,7 @@ public class XmlBlock extends AbstractXmlBlock { @NotNull public TextRange getTextRange() { - if (myTextRange != null) { + if (myTextRange != null && !(isCDATAStart() || isCDATAEnd())) { return myTextRange; } else { diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlFormattingPolicy.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlFormattingPolicy.java index c12815d7fa49..44ba07f43aff 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/XmlFormattingPolicy.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlFormattingPolicy.java @@ -115,6 +115,10 @@ public abstract class XmlFormattingPolicy { public abstract boolean getShouldKeepLineBreaksInText(); + public abstract boolean getKeepWhiteSpacesInsideCDATA(); + + public abstract int getWhiteSpaceAroundCDATAOption(); + public abstract CodeStyleSettings getSettings(); public boolean processJsp() { diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlPolicy.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlPolicy.java index aa74224778be..0ee2bf668eb6 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/XmlPolicy.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlPolicy.java @@ -102,6 +102,16 @@ public class XmlPolicy extends XmlFormattingPolicy{ return mySettings.XML_KEEP_LINE_BREAKS_IN_TEXT; } + @Override + public boolean getKeepWhiteSpacesInsideCDATA() { + return mySettings.XML_KEEP_WHITE_SPACES_INSIDE_CDATA; + } + + @Override + public int getWhiteSpaceAroundCDATAOption() { + return mySettings.XML_WHITE_SPACE_AROUND_CDATA; + } + public CodeStyleSettings getSettings() { return mySettings; } diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlTagBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlTagBlock.java index 9370145ae91b..6ece1da7a721 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/XmlTagBlock.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlTagBlock.java @@ -18,6 +18,7 @@ package com.intellij.psi.formatter.xml; import com.intellij.formatting.*; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; +import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.xml.XmlElementType; @@ -206,6 +207,24 @@ public class XmlTagBlock extends AbstractXmlBlock{ return Spacing.getReadOnlySpacing(); } + if (syntheticBlock1.containsCDATA() && syntheticBlock2.isTagDescription() + || syntheticBlock1.isTagDescription() && syntheticBlock2.containsCDATA()) { + int lineFeeds = 0; + switch(myXmlFormattingPolicy.getWhiteSpaceAroundCDATAOption()) { + case CodeStyleSettings.WS_AROUND_CDATA_NONE: + break; + case CodeStyleSettings.WS_AROUND_CDATA_NEW_LINES: + lineFeeds = 1; + break; + case CodeStyleSettings.WS_AROUND_CDATA_PRESERVE: + return Spacing.getReadOnlySpacing(); + default: + assert false : "Unexpected whitespace around CDATA code style option."; + } + return Spacing.createSpacing(0, 0, lineFeeds, myXmlFormattingPolicy.getShouldKeepLineBreaks(), + myXmlFormattingPolicy.getKeepBlankLines()); + } + if (syntheticBlock2.isJspTextBlock() || syntheticBlock1.isJspTextBlock()) { return Spacing.createSafeSpacing(myXmlFormattingPolicy.getShouldKeepLineBreaks(), myXmlFormattingPolicy.getKeepBlankLines()); } diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTextImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTextImpl.java index ff759239a353..fb627d5bf548 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTextImpl.java +++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTextImpl.java @@ -366,15 +366,23 @@ public class XmlTextImpl extends XmlElementImpl implements XmlText, PsiLanguageI public TextRange getCDATAInterior() { PsiElement[] elements = getChildren(); int start = 0; - if (elements.length != 0 && elements[0].getNode().getElementType() == XmlElementType.XML_CDATA) { - ASTNode startNode = elements[0].getNode().findChildByType(XmlTokenType.XML_CDATA_START); + int first = 0; + if (elements.length > 0 && elements[0] instanceof PsiWhiteSpace) { + first ++; + } + if (elements.length > first && elements[first].getNode().getElementType() == XmlElementType.XML_CDATA) { + ASTNode startNode = elements[first].getNode().findChildByType(XmlTokenType.XML_CDATA_START); if (startNode != null) { start = startNode.getTextRange().getEndOffset() - getTextRange().getStartOffset(); } } int end = getTextLength(); - if (elements.length != 0 && elements[elements.length-1].getNode().getElementType() == XmlElementType.XML_CDATA) { - ASTNode startNode = elements[elements.length-1].getNode().findChildByType(XmlTokenType.XML_CDATA_END); + int last = elements.length - 1; + if (last > 0 && elements[last] instanceof PsiWhiteSpace) { + last --; + } + if (last >= 0 && elements[last].getNode().getElementType() == XmlElementType.XML_CDATA) { + ASTNode startNode = elements[last].getNode().findChildByType(XmlTokenType.XML_CDATA_END); if (startNode != null) { end = startNode.getTextRange().getStartOffset() - getTextRange().getStartOffset(); } From 034e88f85a545209e40fb3535eb6780700d9f6c9 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Thu, 5 Aug 2010 12:48:18 +0400 Subject: [PATCH 07/18] caching for groovy categories --- .../resources/standardDsls/metaDsl.gdsl | 4 +- .../groovy/dsl/CustomMembersGenerator.java | 6 ++ .../groovy/dsl/GdslMembersHolderConsumer.java | 3 + .../dsl/toplevel/CategoryMethodProvider.java | 72 +++++++++++++++++++ .../toplevel/GdslMetaClassProperties.groovy | 43 +---------- .../plugins/groovy/dsl/GroovyDslTest.groovy | 14 ++++ .../dsl/CategoryWhenMethodRenamed.groovy | 2 + .../CategoryWhenMethodRenamed_after.groovy | 2 + 8 files changed, 103 insertions(+), 43 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/CategoryMethodProvider.java create mode 100644 plugins/groovy/testdata/groovy/dsl/CategoryWhenMethodRenamed.groovy create mode 100644 plugins/groovy/testdata/groovy/dsl/CategoryWhenMethodRenamed_after.groovy diff --git a/plugins/groovy/resources/standardDsls/metaDsl.gdsl b/plugins/groovy/resources/standardDsls/metaDsl.gdsl index 796d1bf178d6..eeb0a67e64c8 100644 --- a/plugins/groovy/resources/standardDsls/metaDsl.gdsl +++ b/plugins/groovy/resources/standardDsls/metaDsl.gdsl @@ -22,8 +22,8 @@ contributor([gdslScriptContext]) { method name: "contributor", params: [contexts: "java.util.Map", body: {}], type: void method name: "contributor", params: [contexts: "java.lang.Object", body: {}], type: void - method name: "category", params: [categoryClass: "java.lang.String", isStatic:"java.lang.Boolean", body: {}], type: void - method name: "category", params: [categoryClass: "java.lang.String", body: {}], type: void + method name: "category", params: [categoryClass: "java.lang.String", isStatic:"java.lang.Boolean"], type: void + method name: "category", params: [categoryClass: "java.lang.String"], type: void method name: "supportsVersion", params: [version: "java.lang.String"], type: boolean diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java index 362e8c7370b7..0853ae4e9eba 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java @@ -2,6 +2,7 @@ package org.jetbrains.plugins.groovy.dsl; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; import groovy.lang.Closure; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.dsl.holders.CompoundMembersHolder; @@ -60,6 +61,11 @@ public class CustomMembersGenerator implements GdslMembersHolderConsumer { return JavaPsiFacade.getInstance(myProject).findClass(myQualifiedName, myDescriptor.getResolveScope()); } + @Override + public GlobalSearchScope getResolveScope() { + return myDescriptor.getResolveScope(); + } + public Project getProject() { return myProject; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GdslMembersHolderConsumer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GdslMembersHolderConsumer.java index e96b7244095f..5894e4c33e3e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GdslMembersHolderConsumer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GdslMembersHolderConsumer.java @@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiType; +import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.dsl.holders.CustomMembersHolder; @@ -34,4 +35,6 @@ public interface GdslMembersHolderConsumer { PsiType getPsiType(); @Nullable PsiClass getPsiClass(); + + GlobalSearchScope getResolveScope(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/CategoryMethodProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/CategoryMethodProvider.java new file mode 100644 index 000000000000..8efd1fe470db --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/CategoryMethodProvider.java @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.dsl.toplevel; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.util.Key; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.*; +import com.intellij.util.Function; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * @author Maxim.Medvedev + */ +public class CategoryMethodProvider { + private static final Key>> METHOD_KEY = Key.create("Category methods"); + + private CategoryMethodProvider() { + } + + public static List provideMethods(@NotNull PsiType psiType, + final Project project, + String className, + GlobalSearchScope scope, + final Function converter) { + final PsiClass categoryClass = JavaPsiFacade.getInstance(project).findClass(className, scope); + if (categoryClass == null) return Collections.emptyList(); + final MultiMap map = CachedValuesManager.getManager(project) + .getCachedValue(categoryClass, METHOD_KEY, new CachedValueProvider>() { + @Override + public Result> compute() { + MultiMap map = new MultiMap(); + for (PsiMethod m : categoryClass.getMethods()) { + final PsiParameter[] params = m.getParameterList().getParameters(); + if (params.length == 0) continue; + final PsiType parameterType = params[0].getType(); + PsiType targetType = TypeConversionUtil.erasure(parameterType); + map.putValue(targetType.getCanonicalText(), converter.fun(m)); + } + return Result.create(map, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT, ProjectRootManager.getInstance(project)); + } + }, false); + Set superTypes = ResolveUtil.getAllSuperTypes(psiType, project).keySet(); + List result = new ArrayList(); + for (String superType : superTypes) { + result.addAll(map.get(superType)); + } + return result; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/GdslMetaClassProperties.groovy b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/GdslMetaClassProperties.groovy index 168563eb2fd0..4c4a913054b0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/GdslMetaClassProperties.groovy +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/GdslMetaClassProperties.groovy @@ -7,17 +7,7 @@ import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.AnnotatedScope import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ClassScope import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ClosureScope import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ScriptScope -import com.intellij.psi.util.TypeConversionUtil -import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil -import com.intellij.psi.util.CachedValuesManager -import com.intellij.openapi.util.Key -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod -import com.intellij.psi.util.CachedValue -import com.intellij.psi.util.CachedValueProvider -import com.intellij.psi.util.CachedValueProvider.Result import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl -import com.intellij.psi.util.PsiModificationTracker -import com.intellij.openapi.roots.ProjectRootManager import com.intellij.psi.PsiMethod import com.intellij.util.Function @@ -73,41 +63,12 @@ class GdslMetaClassProperties { private def processCategoryMethods (def className, Function converter) { contributor(context()) { if (!psiType) return; - - def categoryClass = findClass(className) - if (!categoryClass) return; - categoryClass.methods.each {m -> - def params = m.parameterList.parameters - if (!params) return; - def targetType = TypeConversionUtil.erasure(params[0].type) - if (!ResolveUtil.isInheritor(psiType, targetType.getCanonicalText(), project)) return; - - add CachedValuesManager.getManager(project). - getCachedValue(m, CategoryMethodProvider.CATEGORY_METHOD, new CategoryMethodProvider(m, converter), false) - } + List methods = CategoryMethodProvider.provideMethods(psiType, project, className, resolveScope, converter) + for (m in methods) add m } } - static class CategoryMethodProvider implements CachedValueProvider { - static final Key> CATEGORY_METHOD = Key.create("category method"); - - def method - def converter - - def CategoryMethodProvider(def method, def converter) { - this.method = method; - this.converter = converter - } - - Result compute() { - return Result.create( - converter.fun(method), - PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT, - ProjectRootManager.getInstance(method.project)); - } - } - /** * Auxiliary methods for context definition */ diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyDslTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyDslTest.groovy index cdcabd3c709a..e57c7f4a2956 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyDslTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyDslTest.groovy @@ -25,6 +25,7 @@ import com.intellij.testFramework.PsiTestUtil import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import org.jetbrains.plugins.groovy.util.TestUtils +import com.intellij.psi.PsiClass /** * @author peter @@ -123,4 +124,17 @@ public class GroovyDslTest extends LightCodeInsightFixtureTestCase { return descriptor; } + public void testCategoryWhenMethodRenamed() { + PsiClass category = myFixture.addClass(""" +public class MyCategory { + public void foo(String s) {} +}""") + def foo = category.getMethods()[0] + final PsiFile file = myFixture.addFileToProject(getTestName(false) + "Enhancer.gdsl", """ +category 'MyCategory'"""); + GroovyDslFileIndex.activateUntilModification(file.virtualFile) + myFixture.renameElement foo, "bar", false, false + + myFixture.testCompletion(getTestName(false) + ".groovy", getTestName(false) + "_after.groovy") + } } diff --git a/plugins/groovy/testdata/groovy/dsl/CategoryWhenMethodRenamed.groovy b/plugins/groovy/testdata/groovy/dsl/CategoryWhenMethodRenamed.groovy new file mode 100644 index 000000000000..2d2365d834e1 --- /dev/null +++ b/plugins/groovy/testdata/groovy/dsl/CategoryWhenMethodRenamed.groovy @@ -0,0 +1,2 @@ +def s = "foo" +s.ba \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/dsl/CategoryWhenMethodRenamed_after.groovy b/plugins/groovy/testdata/groovy/dsl/CategoryWhenMethodRenamed_after.groovy new file mode 100644 index 000000000000..c6a76d20ee76 --- /dev/null +++ b/plugins/groovy/testdata/groovy/dsl/CategoryWhenMethodRenamed_after.groovy @@ -0,0 +1,2 @@ +def s = "foo" +s.bar() \ No newline at end of file From 478fabb58c866227f0967c918b98baa13789d7a3 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 3 Aug 2010 14:10:25 +0400 Subject: [PATCH 08/18] Maven: loosened error level when cannot save maven structure --- .../org/jetbrains/idea/maven/project/MavenProjectsManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java index 8c87b9318323..89f7e2758537 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java @@ -224,7 +224,7 @@ public class MavenProjectsManager extends SimpleProjectComponent myProjectsTree.save(getProjectsTreeFile()); } catch (IOException e) { - MavenLog.LOG.warn(e); + MavenLog.LOG.info(e); } } } From dc7f38b834456c538e85e161818494da6a4cc389 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 3 Aug 2010 17:17:11 +0400 Subject: [PATCH 09/18] UI: non-focusable scrollbars LH: fixed traversal policy --- .../intellij/ui/ExcludingTraversalPolicy.java | 74 ++++++++++++++----- .../intellij/ui/components/JBScrollBar.java | 1 - .../util/ui/ButtonlessScrollBarUI.java | 7 ++ 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/ExcludingTraversalPolicy.java b/platform/platform-api/src/com/intellij/ui/ExcludingTraversalPolicy.java index e6fedf213f80..52f58a17a900 100644 --- a/platform/platform-api/src/com/intellij/ui/ExcludingTraversalPolicy.java +++ b/platform/platform-api/src/com/intellij/ui/ExcludingTraversalPolicy.java @@ -27,6 +27,7 @@ import java.util.Set; public class ExcludingTraversalPolicy extends FocusTraversalPolicy { private final FocusTraversalPolicy myWrappee; private final Set myExcludes = new THashSet(); + private final Set myRecursionGuard = new THashSet(); public ExcludingTraversalPolicy(Component... excludes) { this(KeyboardFocusManager.getCurrentKeyboardFocusManager().getDefaultFocusTraversalPolicy(), excludes); @@ -43,26 +44,40 @@ public class ExcludingTraversalPolicy extends FocusTraversalPolicy { @Override public Component getComponentAfter(Container aContainer, Component aComponent) { - return traverse(aContainer, aComponent, new Function, Component>() { - public Component fun(Pair param) { - return myWrappee.getComponentAfter(param.first, param.second); - } - }); + try { + if (!myRecursionGuard.add("getComponentAfter")) return null; + + return traverse(aContainer, aComponent, new Function, Component>() { + public Component fun(Pair param) { + return myWrappee.getComponentAfter(param.first, param.second); + } + }); + } + finally { + myRecursionGuard.clear(); + } } @Override public Component getComponentBefore(Container aContainer, Component aComponent) { - return traverse(aContainer, aComponent, new Function, Component>() { - public Component fun(Pair param) { - return myWrappee.getComponentBefore(param.first, param.second); - } - }); + try { + if (!myRecursionGuard.add("getComponentBefore")) return null; + + return traverse(aContainer, aComponent, new Function, Component>() { + public Component fun(Pair param) { + return myWrappee.getComponentBefore(param.first, param.second); + } + }); + } + finally { + myRecursionGuard.clear(); + } } private Component traverse(Container aContainer, Component aComponent, Function, Component> func) { - Set guard = new THashSet(); + Set loopGuard = new THashSet(); do { - if (!guard.add(aComponent)) return null; + if (!loopGuard.add(aComponent)) return null; aComponent = func.fun(Pair.create(aContainer, aComponent)); } while (aComponent != null && myExcludes.contains(aComponent)); @@ -71,20 +86,41 @@ public class ExcludingTraversalPolicy extends FocusTraversalPolicy { @Override public Component getFirstComponent(Container aContainer) { - Component result = myWrappee.getFirstComponent(aContainer); - if (result == null) return null; - return myExcludes.contains(result) ? getComponentAfter(aContainer, result) : result; + try { + if (!myRecursionGuard.add("getFirstComponent")) return null; + + Component result = myWrappee.getFirstComponent(aContainer); + if (result == null) return null; + return myExcludes.contains(result) ? getComponentAfter(aContainer, result) : result; + } + finally { + myRecursionGuard.clear(); + } } @Override public Component getLastComponent(Container aContainer) { - Component result = myWrappee.getLastComponent(aContainer); - if (result == null) return null; - return myExcludes.contains(result) ? getComponentBefore(aContainer, result) : result; + try { + if (!myRecursionGuard.add("getLastComponent")) return null; + + Component result = myWrappee.getLastComponent(aContainer); + if (result == null) return null; + return myExcludes.contains(result) ? getComponentBefore(aContainer, result) : result; + } + finally { + myRecursionGuard.clear(); + } } @Override public Component getDefaultComponent(Container aContainer) { - return getFirstComponent(aContainer); + try { + if (!myRecursionGuard.add("getDefaultComponent")) return null; + + return getFirstComponent(aContainer); + } + finally { + myRecursionGuard.clear(); + } } } diff --git a/platform/platform-api/src/com/intellij/ui/components/JBScrollBar.java b/platform/platform-api/src/com/intellij/ui/components/JBScrollBar.java index 0c5a5506e843..6cf8483e3a6e 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBScrollBar.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBScrollBar.java @@ -36,7 +36,6 @@ public class JBScrollBar extends JScrollBar{ private void init() { putClientProperty("JScrollBar.fastWheelScrolling", Boolean.TRUE); // fast scrolling for JDK 6 - setFocusable(false); } @Override diff --git a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java index 556cbbaf494b..2f48b7bc17de 100644 --- a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java +++ b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java @@ -70,6 +70,12 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { return new ButtonlessScrollBarUI(); } + @Override + public void installUI(JComponent c) { + super.installUI(c); + scrollbar.setFocusable(false); + } + @Override protected void installListeners() { super.installListeners(); @@ -195,6 +201,7 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { private static class EmptyButton extends JButton { private EmptyButton() { setFocusable(false); + setRequestFocusEnabled(false); } @Override From e5ab7a0ebca257fef59b4fab88fe17571967a08a Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 4 Aug 2010 12:44:58 +0400 Subject: [PATCH 10/18] LH: simplified storage LH: dumb component in headless environment --- .../com/intellij/history/core/ChangeList.java | 58 +++++++------------ .../history/core/ChangeListStorage.java | 8 +-- .../history/core/ChangeListStorageImpl.java | 47 +++++---------- ...angeSetBlock.java => ChangeSetHolder.java} | 35 ++--------- .../history/integration/LocalHistoryImpl.java | 5 ++ .../command/impl/FileUndoProvider.java | 4 +- .../core/InMemoryChangeListStorage.java | 20 +++---- 7 files changed, 57 insertions(+), 120 deletions(-) rename platform/lvcs-impl/src/com/intellij/history/core/{ChangeSetBlock.java => ChangeSetHolder.java} (51%) diff --git a/platform/lvcs-impl/src/com/intellij/history/core/ChangeList.java b/platform/lvcs-impl/src/com/intellij/history/core/ChangeList.java index 955953227739..583b2a0675e1 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/ChangeList.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/ChangeList.java @@ -21,10 +21,9 @@ import com.intellij.history.core.changes.Change; import com.intellij.history.core.changes.ChangeSet; import com.intellij.history.core.changes.ChangeVisitor; import com.intellij.history.core.storage.Content; -import com.intellij.openapi.application.Application; +import com.intellij.history.utils.LocalHistoryLog; import com.intellij.openapi.application.ApplicationManager; import com.intellij.util.Consumer; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.TestOnly; import java.util.ArrayList; @@ -34,24 +33,23 @@ import java.util.List; public class ChangeList { private final ChangeListStorage myStorage; - private ChangeSetBlock myCurrentBlock; - - private ChangeSet myCurrentChangeSet; private int myChangeSetDepth; + private ChangeSet myCurrentChangeSet; private int myIntervalBetweenActivities = 12 * 60 * 60 * 1000; // one day public ChangeList(ChangeListStorage storage) { myStorage = storage; - myCurrentBlock = storage.createNewBlock(); } public synchronized void save() { - flushChanges(true); + myStorage.flush(); } public synchronized void close() { - flushChanges(true); + if (!ApplicationManager.getApplication().isUnitTestMode()) { + LocalHistoryLog.LOG.assertTrue(myCurrentChangeSet == null, "current changes won't be saved: " + myCurrentChangeSet); + } myStorage.close(); } @@ -73,7 +71,6 @@ public class ChangeList { private void doBeginChangeSet() { myCurrentChangeSet = new ChangeSet(myStorage.nextId(), Clock.getCurrentTimestamp()); - myCurrentBlock.add(myCurrentChangeSet); } public synchronized boolean forceBeginChangeSet() { @@ -86,7 +83,7 @@ public class ChangeList { } public synchronized boolean endChangeSet(String name) { - assert myChangeSetDepth > 0; + LocalHistoryLog.LOG.assertTrue(myChangeSetDepth > 0, "not balanced 'begin/end-change set' calls"); myChangeSetDepth--; if (myChangeSetDepth > 0) return false; @@ -96,14 +93,14 @@ public class ChangeList { private boolean doEndChangeSet(String name) { if (myCurrentChangeSet.getChanges().isEmpty()) { - myCurrentBlock.removeLast(); + myCurrentChangeSet = null; return false; } myCurrentChangeSet.setName(name); + myStorage.writeNextSet(myCurrentChangeSet); myCurrentChangeSet = null; - flushChanges(false); return true; } @@ -116,13 +113,12 @@ public class ChangeList { return result; } + // todo synchronization issue: changeset may me modified while being iterated public synchronized Iterable iterChanges() { return new Iterable() { public Iterator iterator() { return new Iterator() { - private ChangeSetBlock currentBlock; - private Iterator currentIter; - + private ChangeSetHolder currentBlock; private ChangeSet next = fetchNext(); public boolean hasNext() { @@ -138,19 +134,21 @@ public class ChangeList { private ChangeSet fetchNext() { if (currentBlock == null) { synchronized (ChangeList.this) { - currentBlock = myCurrentBlock; - List copy = new ArrayList(currentBlock.changes); - currentIter = ContainerUtil.iterateBackward(copy).iterator(); + if (myCurrentChangeSet != null) { + currentBlock = new ChangeSetHolder(-1, myCurrentChangeSet); + } + else { + currentBlock = myStorage.readPrevious(-1); + } } } - while (!currentIter.hasNext()) { + else { synchronized (ChangeList.this) { - currentBlock = myStorage.readPrevious(currentBlock); + currentBlock = myStorage.readPrevious(currentBlock.id); } - if (currentBlock == null) return null; - currentIter = ContainerUtil.iterateBackward(currentBlock.changes).iterator(); } - return currentIter.next(); + if (currentBlock == null) return null; + return currentBlock.changeSet; } public void remove() { @@ -161,20 +159,6 @@ public class ChangeList { }; } - private void flushChanges(boolean force) { - if (myChangeSetDepth > 0) return; - if (myCurrentBlock.shouldFlush(force) || flushEveryChangeSetInTests()) { - myStorage.writeNextBlock(myCurrentBlock); - myCurrentBlock = myStorage.createNewBlock(); - } - myStorage.flush(); - } - - private boolean flushEveryChangeSetInTests() { - Application app = ApplicationManager.getApplication(); - return app == null || app.isUnitTestMode(); - } - public void accept(ChangeVisitor v) { try { for (ChangeSet change : iterChanges()) { diff --git a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorage.java b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorage.java index 4764778b8bd3..21ea33013745 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorage.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorage.java @@ -20,21 +20,17 @@ import com.intellij.history.core.changes.ChangeSet; import com.intellij.util.Consumer; import org.jetbrains.annotations.Nullable; -import java.util.List; - public interface ChangeListStorage { void close(); long nextId(); - ChangeSetBlock createNewBlock(); - @Nullable - ChangeSetBlock readPrevious(ChangeSetBlock block); + ChangeSetHolder readPrevious(int id); void purge(long period, int intervalBetweenActivities, Consumer processor); - void writeNextBlock(ChangeSetBlock block); + void writeNextSet(ChangeSet changeSet); void flush(); } \ No newline at end of file diff --git a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java index ec49a27bbd64..4966417e24eb 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java @@ -27,21 +27,16 @@ import com.intellij.util.io.storage.AbstractStorage; import java.io.DataInputStream; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; public class ChangeListStorageImpl implements ChangeListStorage { - private static final int VERSION = 3; - + private static final int VERSION = 4; private static final String STORAGE_FILE = "changes"; - - private final File myStorageDir; + private final LinkedStorage myStorage; public ChangeListStorageImpl(File storageDir) { - myStorageDir = storageDir; try { - myStorage = createStorage(myStorageDir); + myStorage = createStorage(storageDir); } catch (IOException e) { throw handleError(e); @@ -90,27 +85,18 @@ public class ChangeListStorageImpl implements ChangeListStorage { return myStorage.nextId(); } - public synchronized ChangeSetBlock createNewBlock() { - return new ChangeSetBlock(0); - } - - public synchronized ChangeSetBlock readPrevious(ChangeSetBlock block) { - int prevId = block.id == 0 ? myStorage.getLastRecord() : myStorage.getPrevRecord(block.id); + public synchronized ChangeSetHolder readPrevious(int id) { + int prevId = id == -1 ? myStorage.getLastRecord() : myStorage.getPrevRecord(id); if (prevId == 0) return null; - assert prevId != block.id; + return doReadBlock(prevId); } - private ChangeSetBlock doReadBlock(int id) { + private ChangeSetHolder doReadBlock(int id) { try { DataInputStream in = myStorage.readStream(id); try { - int size = in.readInt(); - List changes = new ArrayList(size); - while (size-- > 0) { - changes.add(new ChangeSet(in)); - } - return new ChangeSetBlock(id, changes); + return new ChangeSetHolder(id, new ChangeSet(in)); } finally { in.close(); @@ -121,15 +107,12 @@ public class ChangeListStorageImpl implements ChangeListStorage { } } - public synchronized void writeNextBlock(ChangeSetBlock block) { + public synchronized void writeNextSet(ChangeSet changeSet) { try { - block.id = myStorage.createNextRecord(); - AbstractStorage.StorageDataOutput out = myStorage.writeStream(block.id); + int id = myStorage.createNextRecord(); + AbstractStorage.StorageDataOutput out = myStorage.writeStream(id); try { - out.writeInt(block.changes.size()); - for (ChangeSet each : block.changes) { - each.write(out); - } + changeSet.write(out); } finally { out.close(); @@ -143,10 +126,8 @@ public class ChangeListStorageImpl implements ChangeListStorage { public synchronized void purge(long period, int intervalBetweenActivities, Consumer processor) { int eachBlockId = findFirstObsoleteBlock(period, intervalBetweenActivities); try { - while(eachBlockId != 0) { - for (ChangeSet eachChangeSet : doReadBlock(eachBlockId).changes) { - processor.consume(eachChangeSet); - } + while (eachBlockId != 0) { + processor.consume(doReadBlock(eachBlockId).changeSet); myStorage.deleteRecord(eachBlockId); eachBlockId = myStorage.getPrevRecord(eachBlockId); } diff --git a/platform/lvcs-impl/src/com/intellij/history/core/ChangeSetBlock.java b/platform/lvcs-impl/src/com/intellij/history/core/ChangeSetHolder.java similarity index 51% rename from platform/lvcs-impl/src/com/intellij/history/core/ChangeSetBlock.java rename to platform/lvcs-impl/src/com/intellij/history/core/ChangeSetHolder.java index 7660c051757f..aee1e52a0ae2 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/ChangeSetBlock.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/ChangeSetHolder.java @@ -20,37 +20,12 @@ import com.intellij.history.core.changes.ChangeSet; import java.util.ArrayList; import java.util.List; -public class ChangeSetBlock { - private static final int BLOCK_SIZE = 1000; - public int id; - public final List changes; +public class ChangeSetHolder { + public final int id; + public final ChangeSet changeSet; - public ChangeSetBlock(int id) { + public ChangeSetHolder(int id, ChangeSet changeSet) { this.id = id; - this.changes = new ArrayList(BLOCK_SIZE); - } - - ChangeSetBlock(int id, List changes) { - this.id = id; - this.changes = changes; - } - - public void add(ChangeSet changeSet) { - changes.add(changeSet); - } - - public void removeLast() { - changes.remove(changes.size() - 1); - } - - public boolean shouldFlush(boolean force) { - int count = 0; - for (ChangeSet each : changes) { - count += each.getChanges().size(); - - if (count >= BLOCK_SIZE) return true; - if (force && count > 0) return true; - } - return false; + this.changeSet = changeSet; } } diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java index da907dbcdcab..6319d17b35eb 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryImpl.java @@ -35,6 +35,7 @@ import com.intellij.openapi.vfs.ex.VirtualFileManagerEx; import com.intellij.util.io.storage.HeavyProcessLatch; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import java.io.File; @@ -58,6 +59,8 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone } public void initComponent() { + if (!ApplicationManager.getApplication().isUnitTestMode() && ApplicationManager.getApplication().isHeadlessEnvironment()) return; + myShutdownTask = new Runnable() { public void run() { disposeComponent(); @@ -193,10 +196,12 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone return "Local History"; } + @Nullable public LocalHistoryFacade getFacade() { return myVcs; } + @Nullable public IdeaGateway getGateway() { return myGateway; } diff --git a/platform/lvcs-impl/src/com/intellij/openapi/command/impl/FileUndoProvider.java b/platform/lvcs-impl/src/com/intellij/openapi/command/impl/FileUndoProvider.java index c65e73fc4aa2..ae3b5026bd5a 100644 --- a/platform/lvcs-impl/src/com/intellij/openapi/command/impl/FileUndoProvider.java +++ b/platform/lvcs-impl/src/com/intellij/openapi/command/impl/FileUndoProvider.java @@ -23,6 +23,7 @@ import com.intellij.history.core.changes.ContentChange; import com.intellij.history.core.changes.StructuralChange; import com.intellij.history.integration.IdeaGateway; import com.intellij.history.integration.LocalHistoryImpl; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.undo.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -50,11 +51,12 @@ public class FileUndoProvider extends VirtualFileAdapter implements UndoProvider } public FileUndoProvider(Project project) { - myProject = project; + myProject = project; if (myProject == null) return; myLocalHistory = LocalHistoryImpl.getInstanceImpl().getFacade(); myGateway = LocalHistoryImpl.getInstanceImpl().getGateway(); + if (myLocalHistory == null || myGateway == null) return; // local history was not initialized (e.g. in headless environment) getFileManager().addVirtualFileListener(this, project); myLocalHistory.addListener(new LocalHistoryFacade.Listener() { diff --git a/platform/lvcs-impl/testSrc/com/intellij/history/core/InMemoryChangeListStorage.java b/platform/lvcs-impl/testSrc/com/intellij/history/core/InMemoryChangeListStorage.java index f48e4604d60a..6a8182c104c1 100644 --- a/platform/lvcs-impl/testSrc/com/intellij/history/core/InMemoryChangeListStorage.java +++ b/platform/lvcs-impl/testSrc/com/intellij/history/core/InMemoryChangeListStorage.java @@ -23,7 +23,7 @@ import java.util.List; public class InMemoryChangeListStorage implements ChangeListStorage { private int myCurrentId; - private List myBlocks = new ArrayList(); + private List mySets = new ArrayList(); public void close() { } @@ -32,20 +32,14 @@ public class InMemoryChangeListStorage implements ChangeListStorage { return myCurrentId++; } - public ChangeSetBlock createNewBlock() { - return new ChangeSetBlock(-1); + public ChangeSetHolder readPrevious(int id) { + if (mySets.isEmpty()) return null; + if (id == -1) return new ChangeSetHolder(mySets.size() - 1, mySets.get(mySets.size() - 1)); + return id == 0 ? null : new ChangeSetHolder(id -1, mySets.get(id - 1)); } - public ChangeSetBlock readPrevious(ChangeSetBlock block) { - if (myBlocks.isEmpty()) return null; - if (block.id == 0) return null; - if (block.id == -1) return myBlocks.get(myBlocks.size() - 1); - return myBlocks.get(block.id - 1); - } - - public void writeNextBlock(ChangeSetBlock block) { - myBlocks.add(block); - block.id = myBlocks.size() - 1; + public void writeNextSet(ChangeSet changeSet) { + mySets.add(changeSet); } public void purge(long period, int intervalBetweenActivities, Consumer processor) { From 7637f0f39212b49ebf1bf48f8e618183e858d271 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 4 Aug 2010 14:10:28 +0400 Subject: [PATCH 11/18] JBTable: empty text rendering fix --- .../platform-api/src/com/intellij/ui/table/JBTable.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/ui/table/JBTable.java b/platform/platform-api/src/com/intellij/ui/table/JBTable.java index a3f4395aeb76..281e9d90ca2d 100644 --- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java +++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java @@ -59,12 +59,14 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component myEmptyTextHelper = new EmptyTextHelper(this) { @Override protected boolean isEmpty() { - return getRowCount() == 0; + return JBTable.this.isEmpty(); } }; myExpandableItemsHandler = ExpandableItemsHandlerFactory.install(this); + setFillsViewportHeight(true); + addMouseListener(new MyMouseListener()); getColumnModel().addColumnModelListener(new TableColumnModelListener() { public void columnMarginChanged(ChangeEvent e) { @@ -82,6 +84,10 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component boolean marker = Patches.SUN_BUG_ID_4503845; // Don't remove. It's a marker for find usages } + public boolean isEmpty() { + return getRowCount() == 0; + } + @Override protected void paintComponent(Graphics g) { super.paintComponent(g); From 0603f12ed11345e1505ea2309796a4bf07fc5e8e Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 4 Aug 2010 15:17:36 +0400 Subject: [PATCH 12/18] File Structure dialog: borders --- .../src/com/intellij/ide/util/FileStructureDialog.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java index b30722da209e..be11301b2b6a 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java +++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java @@ -51,6 +51,7 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiUtilBase; +import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.ListScrollingUtil; import com.intellij.ui.SpeedSearchBase; import com.intellij.util.ArrayUtil; @@ -219,6 +220,7 @@ public class FileStructureDialog extends DialogWrapper { addFilterCheckbox(panel, filter); } + myCommanderPanel.setBorder(IdeBorderFactory.createSimpleBorder(1, 0, 0, 0)); panel.add(myCommanderPanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); From 7082c09efef6cfc7b97f0693be0bf710b3d4b18f Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Thu, 5 Aug 2010 11:21:06 +0400 Subject: [PATCH 13/18] UI: borders --- .../intention/impl/CreateClassDialog.java | 2 +- .../inCallers/CallerChooser.java | 2 +- .../refactoring/copy/CopyClassDialog.java | 2 +- .../EnclosingMethodSelectionDialog.java | 2 +- .../IntroduceParameterDialog.java | 2 +- .../MakeParameterizedStaticDialog.java | 2 +- .../makeStatic/SimpleMakeStaticDialog.java | 2 +- .../memberPullUp/PullUpDialog.java | 3 +- .../migration/EditMigrationDialog.java | 2 +- .../migration/EditMigrationEntryDialog.java | 2 +- .../TurnRefsToSuperDialog.java | 2 +- .../refactoring/typeCook/TypeCookDialog.java | 2 +- .../src/com/intellij/slicer/SlicePanel.java | 11 +- .../createTest/CreateTestDialog.java | 2 +- .../hint/ImplementationViewComponent.java | 2 +- .../intention/impl/config/LazyEditor.java | 6 + .../console/LanguageConsoleImpl.java | 2 +- .../ide/util/FileStructureDialog.java | 3 +- .../injected/editor/EditorWindow.java | 6 + .../copy/CopyFilesOrDirectoriesDialog.java | 2 +- .../lang/ExtractIncludeDialog.java | 2 +- .../MoveFilesOrDirectoriesDialog.java | 2 +- .../refactoring/rename/RenameDialog.java | 2 +- .../integration/ui/views/HistoryDialog.java | 11 +- .../com/intellij/openapi/editor/Editor.java | 3 + .../src/com/intellij/ui/GuiUtils.java | 2 +- .../src/com/intellij/ui/IdeBorderFactory.java | 35 +++-- .../intellij/ui/components/JBScrollPane.java | 3 +- .../openapi/diff/ex/DiffStatusBar.java | 2 +- .../intellij/openapi/editor/ex/EditorEx.java | 1 + .../openapi/editor/impl/EditorImpl.java | 15 +- .../editor/textarea/TextComponentEditor.java | 5 + .../wm/impl/ActivatableLineBorder.java | 52 ------- .../openapi/wm/impl/InternalDecorator.java | 2 +- .../intellij/openapi/wm/impl/TitlePanel.java | 2 +- .../src/com/intellij/ui/EditorTextField.java | 2 +- .../src/messages/UsageView.properties | 1 - .../usages/impl/UsagePreviewPanel.java | 12 +- .../intellij/usages/impl/UsageViewImpl.java | 15 +- .../util/src/com/intellij/util/ui/UIUtil.java | 138 +++++++++++------- .../CommittedChangesTreeBrowser.java | 2 +- .../vcs/changes/committed/WiseSplitter.java | 5 +- .../vcs/history/FileHistoryPanelImpl.java | 4 +- ...tIgnorePatternsToRemoveOnDeleteDialog.java | 2 +- .../xml/refactoring/XmlTagRenameDialog.java | 2 +- 45 files changed, 197 insertions(+), 184 deletions(-) delete mode 100644 platform/platform-impl/src/com/intellij/openapi/wm/impl/ActivatableLineBorder.java diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java index f612d9f45f8d..dbbe7f9a22a1 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java @@ -110,7 +110,7 @@ public class CreateClassDialog extends DialogWrapper { gbConstraints.weightx = 0; gbConstraints.gridwidth = 1; panel.add(myInformationLabel, gbConstraints); - panel.setBorder(IdeBorderFactory.createBorder()); + panel.setBorder(IdeBorderFactory.createRoundedBorder()); gbConstraints.insets = new Insets(4, 8, 4, 8); gbConstraints.gridx = 1; gbConstraints.weightx = 1; diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/CallerChooser.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/CallerChooser.java index 66d22e96c558..c2fbc35717ab 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/CallerChooser.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/inCallers/CallerChooser.java @@ -185,7 +185,7 @@ public abstract class CallerChooser extends DialogWrapper { final JComponent calleeComponent = myCalleeEditor.getComponent(); calleeComponent.setBorder(IdeBorderFactory.createTitledBorder(RefactoringBundle.message("caller.chooser.callee.method"))); splitter.setSecondComponent(calleeComponent); - splitter.setBorder(IdeBorderFactory.createBorder()); + splitter.setBorder(IdeBorderFactory.createRoundedBorder()); return splitter; } diff --git a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java index d8de9dcd485b..9af238c9d839 100644 --- a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java @@ -95,7 +95,7 @@ class CopyClassDialog extends DialogWrapper{ JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbConstraints = new GridBagConstraints(); - panel.setBorder(IdeBorderFactory.createBorder()); + panel.setBorder(IdeBorderFactory.createRoundedBorder()); gbConstraints.insets = new Insets(4,8,4,8); gbConstraints.weightx = 1; diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/EnclosingMethodSelectionDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/EnclosingMethodSelectionDialog.java index 94d1829fba9d..61d9337db533 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/EnclosingMethodSelectionDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/EnclosingMethodSelectionDialog.java @@ -72,7 +72,7 @@ public class EnclosingMethodSelectionDialog extends DialogWrapper { protected JComponent createNorthPanel() { JPanel panel = new JPanel(); - panel.setBorder(IdeBorderFactory.createBorder()); + panel.setBorder(IdeBorderFactory.createRoundedBorder()); panel.setLayout(new GridBagLayout()); GridBagConstraints gbConstraints = new GridBagConstraints(); diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterDialog.java index a5d948db3fad..5bb05430be78 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterDialog.java @@ -353,7 +353,7 @@ public class IntroduceParameterDialog extends RefactoringDialog { private JPanel createReplaceFieldsWithGettersPanel() { JPanel radioButtonPanel = new JPanel(new GridBagLayout()); - radioButtonPanel.setBorder(IdeBorderFactory.createBorder()); + radioButtonPanel.setBorder(IdeBorderFactory.createRoundedBorder()); GridBagConstraints gbConstraints = new GridBagConstraints(); gbConstraints.insets = new Insets(4, 8, 4, 8); diff --git a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeParameterizedStaticDialog.java b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeParameterizedStaticDialog.java index 29ed7126b135..d73c07a7f4a2 100644 --- a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeParameterizedStaticDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeParameterizedStaticDialog.java @@ -126,7 +126,7 @@ public class MakeParameterizedStaticDialog extends AbstractMakeStaticDialog { GridBagConstraints gbConstraints = new GridBagConstraints(); JPanel panel = new JPanel(new GridBagLayout()); - panel.setBorder(IdeBorderFactory.createBorder()); + panel.setBorder(IdeBorderFactory.createRoundedBorder()); gbConstraints.insets = new Insets(4, 8, 4, 8); gbConstraints.weighty = 0; diff --git a/java/java-impl/src/com/intellij/refactoring/makeStatic/SimpleMakeStaticDialog.java b/java/java-impl/src/com/intellij/refactoring/makeStatic/SimpleMakeStaticDialog.java index 2fffcb59372f..359e9ea264d0 100644 --- a/java/java-impl/src/com/intellij/refactoring/makeStatic/SimpleMakeStaticDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/makeStatic/SimpleMakeStaticDialog.java @@ -75,7 +75,7 @@ public class SimpleMakeStaticDialog extends AbstractMakeStaticDialog { GridBagConstraints gbConstraints = new GridBagConstraints(); JPanel panel = new JPanel(new GridBagLayout()); - panel.setBorder(IdeBorderFactory.createBorder()); + panel.setBorder(IdeBorderFactory.createRoundedBorder()); gbConstraints.insets = new Insets(4, 8, 4, 8); gbConstraints.weighty = 1; diff --git a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java index f09f2f0385c7..77bc209ba764 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java @@ -27,7 +27,6 @@ package com.intellij.refactoring.memberPullUp; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.project.Project; import com.intellij.psi.*; -import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.JavaRefactoringSettings; import com.intellij.refactoring.RefactoringBundle; @@ -118,7 +117,7 @@ public class PullUpDialog extends RefactoringDialog { protected JComponent createNorthPanel() { JPanel panel = new JPanel(); - panel.setBorder(IdeBorderFactory.createBorder()); + panel.setBorder(IdeBorderFactory.createRoundedBorder()); panel.setLayout(new GridBagLayout()); GridBagConstraints gbConstraints = new GridBagConstraints(); diff --git a/java/java-impl/src/com/intellij/refactoring/migration/EditMigrationDialog.java b/java/java-impl/src/com/intellij/refactoring/migration/EditMigrationDialog.java index f2c73b1ad763..9ddd5b37e928 100644 --- a/java/java-impl/src/com/intellij/refactoring/migration/EditMigrationDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/migration/EditMigrationDialog.java @@ -130,7 +130,7 @@ public class EditMigrationDialog extends DialogWrapper{ protected JComponent createCenterPanel() { JPanel tablePanel = new JPanel(new BorderLayout()); - tablePanel.setBorder(IdeBorderFactory.createBorder()); + tablePanel.setBorder(IdeBorderFactory.createRoundedBorder()); tablePanel.add(createTable(), BorderLayout.CENTER); JPanel tableButtonsPanel = new JPanel(); diff --git a/java/java-impl/src/com/intellij/refactoring/migration/EditMigrationEntryDialog.java b/java/java-impl/src/com/intellij/refactoring/migration/EditMigrationEntryDialog.java index 0b34aaaa600b..a02c348a28c8 100644 --- a/java/java-impl/src/com/intellij/refactoring/migration/EditMigrationEntryDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/migration/EditMigrationEntryDialog.java @@ -55,7 +55,7 @@ public class EditMigrationEntryDialog extends DialogWrapper{ protected JComponent createNorthPanel() { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbConstraints = new GridBagConstraints(); - panel.setBorder(IdeBorderFactory.createBorder()); + panel.setBorder(IdeBorderFactory.createRoundedBorder()); gbConstraints.insets = new Insets(4, 4, 4, 4); gbConstraints.weighty = 1; diff --git a/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperDialog.java b/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperDialog.java index 876d27fa3911..0c404004ea14 100644 --- a/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperDialog.java @@ -83,7 +83,7 @@ public class TurnRefsToSuperDialog extends RefactoringDialog { protected JComponent createNorthPanel() { JPanel panel = new JPanel(); - panel.setBorder(IdeBorderFactory.createBorder()); + panel.setBorder(IdeBorderFactory.createRoundedBorder()); panel.setLayout(new GridBagLayout()); GridBagConstraints gbConstraints = new GridBagConstraints(); diff --git a/java/java-impl/src/com/intellij/refactoring/typeCook/TypeCookDialog.java b/java/java-impl/src/com/intellij/refactoring/typeCook/TypeCookDialog.java index 29da46f6fa7e..4d2167c03234 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeCook/TypeCookDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/typeCook/TypeCookDialog.java @@ -86,7 +86,7 @@ public class TypeCookDialog extends RefactoringDialog { JPanel optionsPanel = new JPanel(new GridBagLayout()); GridBagConstraints gbConstraints = new GridBagConstraints(); - optionsPanel.setBorder(IdeBorderFactory.createBorder()); + optionsPanel.setBorder(IdeBorderFactory.createRoundedBorder()); if (myCbDropCasts.isEnabled()) { myCbDropCasts.setSelected(JavaRefactoringSettings.getInstance().TYPE_COOK_DROP_CASTS); diff --git a/java/java-impl/src/com/intellij/slicer/SlicePanel.java b/java/java-impl/src/com/intellij/slicer/SlicePanel.java index d0c5b62ac8ab..fea2f4fbcb25 100644 --- a/java/java-impl/src/com/intellij/slicer/SlicePanel.java +++ b/java/java-impl/src/com/intellij/slicer/SlicePanel.java @@ -135,17 +135,24 @@ public abstract class SlicePanel extends JPanel implements TypeSafeDataProvider, Disposer.dispose(myUsagePreviewPanel); } removeAll(); + JScrollPane pane = ScrollPaneFactory.createScrollPane(myTree); + if (isPreview()) { + pane.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT | SideBorder.RIGHT)); + boolean vertical = myToolWindow.getAnchor() == ToolWindowAnchor.LEFT || myToolWindow.getAnchor() == ToolWindowAnchor.RIGHT; Splitter splitter = new Splitter(vertical, UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS); - splitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myTree)); + splitter.setFirstComponent(pane); myUsagePreviewPanel = new UsagePreviewPanel(myProject); + myUsagePreviewPanel.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT)); + Disposer.register(this, myUsagePreviewPanel); splitter.setSecondComponent(myUsagePreviewPanel); add(splitter, BorderLayout.CENTER); } else { - add(ScrollPaneFactory.createScrollPane(myTree), BorderLayout.CENTER); + pane.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT)); + add(pane, BorderLayout.CENTER); } add(createToolbar().getComponent(), BorderLayout.WEST); diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java index 228a8844826a..ca3abf3010f9 100644 --- a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java +++ b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java @@ -271,7 +271,7 @@ public class CreateTestDialog extends DialogWrapper { protected JComponent createCenterPanel() { JPanel panel = new JPanel(new GridBagLayout()); - panel.setBorder(IdeBorderFactory.createBorder()); + panel.setBorder(IdeBorderFactory.createRoundedBorder()); GridBagConstraints constr = new GridBagConstraints(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/ImplementationViewComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/ImplementationViewComponent.java index 8d2503d63a00..6ff4c1f5eb98 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hint/ImplementationViewComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/ImplementationViewComponent.java @@ -202,7 +202,7 @@ public class ImplementationViewComponent extends JPanel { label.setIcon(file.getIcon()); label.setForeground(FileStatusManager.getInstance(project).getStatus(file).getColor()); label.setText(file.getPresentableName()); - label.setBorder(new CompoundBorder(IdeBorderFactory.createBorder(), IdeBorderFactory.createEmptyBorder(0, 0, 0, 5))); + label.setBorder(new CompoundBorder(IdeBorderFactory.createRoundedBorder(), IdeBorderFactory.createEmptyBorder(0, 0, 0, 5))); } toolbarPanel.add(label); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/LazyEditor.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/LazyEditor.java index bf949f547111..38502208ec69 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/LazyEditor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/LazyEditor.java @@ -19,6 +19,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.border.Border; import java.awt.*; import java.awt.event.MouseEvent; @@ -62,6 +63,11 @@ class LazyEditor extends UserDataHolderBase implements Editor { return getEditor().getContentComponent(); } + @Override + public void setBorder(@Nullable Border border) { + getEditor().setBorder(border); + } + @NotNull public SelectionModel getSelectionModel() { return getEditor().getSelectionModel(); diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index 7436f0969893..db2ab7263ce0 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -228,7 +228,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { editor.setHorizontalScrollbarVisible(false); editor.setVerticalScrollbarVisible(true); editor.getColorsScheme().setColor(EditorColors.CARET_ROW_COLOR, null); - editor.getScrollPane().setBorder(null); + editor.setBorder(null); editor.getContentComponent().setFocusCycleRoot(false); final EditorSettings editorSettings = editor.getSettings(); diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java index be11301b2b6a..e79942cdc428 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java +++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java @@ -53,6 +53,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiUtilBase; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.ListScrollingUtil; +import com.intellij.ui.SideBorder; import com.intellij.ui.SpeedSearchBase; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashSet; @@ -220,7 +221,7 @@ public class FileStructureDialog extends DialogWrapper { addFilterCheckbox(panel, filter); } - myCommanderPanel.setBorder(IdeBorderFactory.createSimpleBorder(1, 0, 0, 0)); + myCommanderPanel.setBorder(IdeBorderFactory.createBorder(SideBorder.TOP)); panel.add(myCommanderPanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); diff --git a/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java index aae8a0edaa25..0a7842682cd3 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java @@ -46,6 +46,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.border.Border; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; @@ -429,6 +430,11 @@ public class EditorWindow implements EditorEx, UserDataHolderEx { return myDelegate.getScrollPane(); } + @Override + public void setBorder(Border border) { + myDelegate.setBorder(border); + } + public int logicalPositionToOffset(@NotNull final LogicalPosition pos) { int lineStartOffset = myDocumentWindow.getLineStartOffset(pos.line); return calcOffset(pos.column, pos.line, lineStartOffset); diff --git a/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesDialog.java b/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesDialog.java index 7efcab47e49e..78d0ba6b1844 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesDialog.java +++ b/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesDialog.java @@ -130,7 +130,7 @@ class CopyFilesOrDirectoriesDialog extends DialogWrapper{ protected JComponent createNorthPanel() { JPanel panel = new JPanel(new GridBagLayout()); - panel.setBorder(IdeBorderFactory.createBorder()); + panel.setBorder(IdeBorderFactory.createRoundedBorder()); myInformationLabel = new JLabel(); diff --git a/platform/lang-impl/src/com/intellij/refactoring/lang/ExtractIncludeDialog.java b/platform/lang-impl/src/com/intellij/refactoring/lang/ExtractIncludeDialog.java index b7f52a6293e9..df21b8eba25c 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/lang/ExtractIncludeDialog.java +++ b/platform/lang-impl/src/com/intellij/refactoring/lang/ExtractIncludeDialog.java @@ -78,7 +78,7 @@ public class ExtractIncludeDialog extends DialogWrapper { protected JComponent createCenterPanel() { JPanel panel = new JPanel(new VerticalFlowLayout()); - panel.setBorder(IdeBorderFactory.createBorder()); + panel.setBorder(IdeBorderFactory.createRoundedBorder()); JLabel nameLabel = new JLabel(); panel.add(nameLabel); diff --git a/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFilesOrDirectoriesDialog.java b/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFilesOrDirectoriesDialog.java index ae554b56c053..e79749b8ecb0 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFilesOrDirectoriesDialog.java +++ b/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFilesOrDirectoriesDialog.java @@ -83,7 +83,7 @@ public class MoveFilesOrDirectoriesDialog extends DialogWrapper{ JPanel panel = new JPanel(); panel.setLayout(new GridBagLayout()); - panel.setBorder(IdeBorderFactory.createBorder()); + panel.setBorder(IdeBorderFactory.createRoundedBorder()); myNameLabel = new JLabel(); panel.add(myNameLabel, new GridBagConstraints(0,0,2,1,1,0,GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,new Insets(4,8,4,8),0,0)); diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameDialog.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameDialog.java index bfa5458b7066..9c32630b7933 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameDialog.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameDialog.java @@ -186,7 +186,7 @@ public class RenameDialog extends RefactoringDialog { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbConstraints = new GridBagConstraints(); - panel.setBorder(IdeBorderFactory.createBorder()); + panel.setBorder(IdeBorderFactory.createRoundedBorder()); gbConstraints.insets = new Insets(4, 8, 4, 8); gbConstraints.weighty = 0; diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/HistoryDialog.java b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/HistoryDialog.java index 5507f2a9cef2..d5560002573f 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/HistoryDialog.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/HistoryDialog.java @@ -46,10 +46,7 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.patch.CreatePatchConfigurationPanel; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.ExcludingTraversalPolicy; -import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.PopupHandler; -import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.*; import com.intellij.ui.awt.RelativePoint; import com.intellij.util.Consumer; import com.intellij.util.ImageLoader; @@ -165,10 +162,10 @@ public abstract class HistoryDialog extends FrameW restoreSplitterProportion(); root.add(mySplitter); - setDiffBorder(IdeBorderFactory.createSimpleBorder(1, 1, 0, 0)); + setDiffBorder(IdeBorderFactory.createBorder(SideBorder.TOP | SideBorder.LEFT)); } else { - setDiffBorder(IdeBorderFactory.createSimpleBorder(1, 0, 1, 0)); + setDiffBorder(IdeBorderFactory.createBorder(SideBorder.TOP | SideBorder.BOTTOM)); root.add(myDiffView); } @@ -209,7 +206,7 @@ public abstract class HistoryDialog extends FrameW } result.add(toolBarPanel, BorderLayout.NORTH); JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myRevisionsList.getComponent()); - scrollPane.setBorder(IdeBorderFactory.createSimpleBorder(1, 0, 0, 1)); + scrollPane.setBorder(IdeBorderFactory.createBorder(SideBorder.TOP | SideBorder.RIGHT)); result.add(scrollPane, BorderLayout.CENTER); return result; diff --git a/platform/platform-api/src/com/intellij/openapi/editor/Editor.java b/platform/platform-api/src/com/intellij/openapi/editor/Editor.java index dde1ec98456f..b06f8db2eeeb 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/Editor.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/Editor.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.border.Border; import java.awt.*; import java.awt.event.MouseEvent; @@ -69,6 +70,8 @@ public interface Editor extends UserDataHolder { */ @NotNull JComponent getContentComponent(); + void setBorder(@Nullable Border border); + /** * Returns the selection model for the editor, which can be used to select ranges of text in * the document and retrieve information about the selection. diff --git a/platform/platform-api/src/com/intellij/ui/GuiUtils.java b/platform/platform-api/src/com/intellij/ui/GuiUtils.java index 8a6a90c84908..96f767ef02a1 100644 --- a/platform/platform-api/src/com/intellij/ui/GuiUtils.java +++ b/platform/platform-api/src/com/intellij/ui/GuiUtils.java @@ -120,7 +120,7 @@ public class GuiUtils { public static JPanel makeDialogPanel(JPanel aPanel) { JPanel emptyBordered = makePaddedPanel(aPanel, paddingFromDialogBoundaries); - return wrapWithBorder(emptyBordered, IdeBorderFactory.createBorder()); + return wrapWithBorder(emptyBordered, IdeBorderFactory.createRoundedBorder()); } public static JPanel makeTitledPanel(JComponent aComponent, String aTitle) { diff --git a/platform/platform-api/src/com/intellij/ui/IdeBorderFactory.java b/platform/platform-api/src/com/intellij/ui/IdeBorderFactory.java index 2e702702e7b3..e17c6e5d1448 100644 --- a/platform/platform-api/src/com/intellij/ui/IdeBorderFactory.java +++ b/platform/platform-api/src/com/intellij/ui/IdeBorderFactory.java @@ -25,18 +25,18 @@ import javax.swing.border.TitledBorder; import java.awt.*; public class IdeBorderFactory { - public static TitledBorder createTitledBorder(String title) { - //return BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), title); - return BorderFactory.createTitledBorder(new RoundedLineBorder(Color.LIGHT_GRAY, 3), title); - } - - public static TitledBorder createTitledHeaderBorder(String title) { - //return BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), title); - return BorderFactory.createTitledBorder(new CompoundBorder(createEmptyBorder(0, 0, 5, 5), new SideBorder(Color.LIGHT_GRAY, SideBorder.TOP)), title); - } + public static final int BORDER_ROUNDNESS = 5; public static Border createBorder() { - return new RoundedLineBorder(Color.GRAY, 5); + return createBorder(SideBorder.ALL); + } + + public static Border createBorder(int borders) { + return new SideBorder(getBorderColor(), borders); + } + + public static Border createRoundedBorder() { + return new RoundedLineBorder(getBorderColor(), BORDER_ROUNDNESS); } public static Border createEmptyBorder(Insets insets) { @@ -47,11 +47,16 @@ public class IdeBorderFactory { return new EmptyBorder(top, left, bottom, right); } - public static Border createSimpleBorder() { - return createSimpleBorder(1, 1, 1, 1); + public static TitledBorder createTitledBorder(String title) { + return BorderFactory.createTitledBorder(new RoundedLineBorder(getBorderColor(), BORDER_ROUNDNESS), title); } - public static Border createSimpleBorder(int top, int left, int bottom, int right) { - return BorderFactory.createMatteBorder(top, left, bottom, right, UIUtil.getBorderSeparatorColor()); + public static TitledBorder createTitledHeaderBorder(String title) { + return BorderFactory.createTitledBorder(new CompoundBorder(createEmptyBorder(0, 0, BORDER_ROUNDNESS, BORDER_ROUNDNESS), + new SideBorder(getBorderColor(), SideBorder.TOP)), title); } -} + + private static Color getBorderColor() { + return UIUtil.getBorderColor(); + } +} \ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java index e5e24128b218..c49445d58eb8 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java @@ -20,7 +20,6 @@ import com.intellij.util.ui.ButtonlessScrollBarUI; import javax.swing.*; import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; import javax.swing.plaf.ScrollPaneUI; import java.awt.*; @@ -45,7 +44,7 @@ public class JBScrollPane extends JScrollPane { } private void init() { - setBorder(IdeBorderFactory.createSimpleBorder()); + setBorder(IdeBorderFactory.createBorder()); setCorner(UPPER_RIGHT_CORNER, new Corner(UPPER_RIGHT_CORNER)); setCorner(UPPER_LEFT_CORNER, new Corner(UPPER_LEFT_CORNER)); setCorner(LOWER_RIGHT_CORNER, new Corner(LOWER_RIGHT_CORNER)); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffStatusBar.java b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffStatusBar.java index b4cf41be8fc2..48e30c96b41b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffStatusBar.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffStatusBar.java @@ -117,7 +117,7 @@ public class DiffStatusBar extends JPanel { } }; setLayout(new BorderLayout()); - setBorder(BorderFactory.createCompoundBorder(IdeBorderFactory.createSimpleBorder(), + setBorder(BorderFactory.createCompoundBorder(IdeBorderFactory.createBorder(), BorderFactory.createEmptyBorder(3, 20, 3, 20))); add(myTextLabel, BorderLayout.WEST); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java index 7728292bd43e..0d71c6fb9cf3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java @@ -34,6 +34,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import javax.swing.*; +import javax.swing.border.Border; import java.awt.*; import java.awt.event.KeyEvent; import java.beans.PropertyChangeListener; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 4c4b38e1e7e1..40f6a10ee34d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -59,6 +59,7 @@ import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.GuiUtils; +import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.LightweightHint; import com.intellij.ui.components.JBScrollBar; import com.intellij.ui.components.JBScrollPane; @@ -78,6 +79,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.Timer; +import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.plaf.ScrollBarUI; import javax.swing.plaf.basic.BasicScrollBarUI; @@ -348,12 +350,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myEditorComponent = new EditorComponentImpl(this); myScrollPane = new MyScrollPane(); - myPanel = new JPanel() { - public void addNotify() { - super.addNotify(); - if (((JComponent)getParent()).getBorder() != null) myScrollPane.setBorder(null); - } - }; + myScrollPane.setBorder(null); + + myPanel = new JPanel(); myHeaderPanel = new MyHeaderPanel(); myVerticalScrollBar = new MyScrollBar(Adjustable.VERTICAL); @@ -2560,6 +2559,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi return myScrollPane; } + public void setBorder(Border border) { + myPanel.setBorder(border); + } + public int logicalPositionToOffset(@NotNull LogicalPosition pos) { assertReadAccess(); assertIsDispatchThread(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentEditor.java b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentEditor.java index b0e9465fa2af..cad02d93a98b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentEditor.java @@ -29,6 +29,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.border.Border; import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.event.MouseEvent; @@ -80,6 +81,10 @@ public class TextComponentEditor extends UserDataHolderBase implements Editor { return myTextComponent; } + @Override + public void setBorder(@Nullable Border border) { + } + @NotNull public SelectionModel getSelectionModel() { return mySelectionModel; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ActivatableLineBorder.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ActivatableLineBorder.java deleted file mode 100644 index 6838671fdfa2..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ActivatableLineBorder.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.wm.impl; - -import com.intellij.util.ui.UIUtil; - -import javax.swing.border.Border; -import java.awt.*; - -public class ActivatableLineBorder implements Border { - - private boolean active = false; - - public boolean isActive() { - return active; - } - - public void setActive(boolean active) { - this.active = active; - } - - public Insets getBorderInsets(Component c) { - return new Insets(1, 1, 1, 1); - } - - public boolean isBorderOpaque() { - return false; - } - - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - final Color lineColor = active ? UIUtil.getBorderActiveColor() : UIUtil.getBorderInactiveColor(); - g.setColor(lineColor); - - UIUtil.drawLine(g, x + 1, y, x + width - 2, y); - UIUtil.drawLine(g, x + 1, y + height - 1, x + width - 2, y + height - 1); - UIUtil.drawLine(g, x, y + 1, x, y + height - 2); - UIUtil.drawLine(g, x + width - 1, y + 1, x + width - 1, y + height - 2); - } -} diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java index 961cb2aff09a..3c15d553541e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java @@ -446,7 +446,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa } public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { - g.setColor(UIUtil.getBorderInactiveColor()); + g.setColor(UIUtil.getHeaderInactiveColor()); Insets insets = getBorderInsets(c); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/TitlePanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/TitlePanel.java index 2267ce00a4ae..b889514b3477 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/TitlePanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/TitlePanel.java @@ -88,7 +88,7 @@ public final class TitlePanel extends JPanel { final Rectangle sideRec = SwingUtilities.convertRectangle(mySideButtons.getParent(), mySideButtons.getBounds(), this); g2d.fillRect(0, STRUT, getWidth() - sideRec.width, getHeight()); - g2d.setColor(UIUtil.getBorderInactiveColor()); + g2d.setColor(UIUtil.getHeaderInactiveColor()); final Color buttonInnerColor = myActive ? ACTIVE_SIDE_BUTTON_BG : INACTIVE_SIDE_BUTTON_BG; g2d.setPaint(new GradientPaint(sideRec.x, sideRec.y, Color.white, sideRec.x, (int)sideRec.getMaxY() - 1, buttonInnerColor)); g2d.fillRect(sideRec.x + 2, sideRec.y, sideRec.width - 2, sideRec.height); diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java index 229b349a24c6..3bc345ff2a37 100644 --- a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java +++ b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java @@ -359,7 +359,7 @@ public class EditorTextField extends JPanel implements DocumentListener, TextCom editor.setOneLineMode(true); editor.getCaretModel().moveToOffset(myDocument.getTextLength()); if (!shouldHaveBorder()) { - editor.getScrollPane().setBorder(null); + editor.setBorder(null); } if (myIsViewer) { diff --git a/platform/platform-resources-en/src/messages/UsageView.properties b/platform/platform-resources-en/src/messages/UsageView.properties index deb21d119c73..026d288cc792 100644 --- a/platform/platform-resources-en/src/messages/UsageView.properties +++ b/platform/platform-resources-en/src/messages/UsageView.properties @@ -55,7 +55,6 @@ usage.type.new=New instance creation usage.type.annotation=Annotation usage.type.read=Value read usage.type.write=Value write -preview.title=\\ \\ \\ Preview\\ {0}:\\ 

preview.usages.action.text=Preview Usages select.the.usage.to.preview=Select the usage to preview usages.were.filtered.out={0,choice, 1#The usage was|2#{0,number} usages were} filtered out diff --git a/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java b/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java index 1500744b496d..cea1a024d4f4 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java @@ -29,6 +29,8 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.SideBorder; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewBundle; import com.intellij.util.ui.UIUtil; @@ -45,13 +47,12 @@ public class UsagePreviewPanel extends JPanel implements Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.usages.impl.UsagePreviewPanel"); private Editor myEditor; private final Project myProject; - private String myTitle; private volatile boolean isDisposed = false; public UsagePreviewPanel(final Project project) { myProject = project; - setLayout(new BorderLayout()); + setBorder(IdeBorderFactory.createBorder()); } private void resetEditor(@NotNull final List infos) { @@ -69,15 +70,11 @@ public class UsagePreviewPanel extends JPanel implements Disposable { final Document document = PsiDocumentManager.getInstance(psiFile.getProject()).getDocument(psiFile); if (document == null) return; - final String title = UsageViewBundle.message("preview.title", psiFile.getName()); - if (myEditor == null || document != myEditor.getDocument() || !Comparing.strEqual(title, myTitle)) { + if (myEditor == null || document != myEditor.getDocument()) { releaseEditor(); removeAll(); myEditor = createEditor(psiFile, document); if (myEditor == null) return; - myTitle = title; - JComponent titleComp = new JLabel(myTitle); - add(titleComp, BorderLayout.NORTH); add(myEditor.getComponent(), BorderLayout.CENTER); revalidate(); @@ -178,7 +175,6 @@ public class UsagePreviewPanel extends JPanel implements Disposable { if (myProject.isDisposed()) return; if (infos == null) { releaseEditor(); - myTitle = null; removeAll(); JComponent titleComp = new JLabel(UsageViewBundle.message("select.the.usage.to.preview")); add(titleComp, BorderLayout.CENTER); diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java index aa90f23f59f6..ea1d5ea571cb 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java @@ -37,9 +37,7 @@ import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.Navigatable; import com.intellij.psi.PsiDocumentManager; -import com.intellij.ui.PopupHandler; -import com.intellij.ui.ScrollPaneFactory; -import com.intellij.ui.SmartExpander; +import com.intellij.ui.*; import com.intellij.ui.content.Content; import com.intellij.ui.treeStructure.Tree; import com.intellij.usageView.UsageInfo; @@ -234,16 +232,21 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra Disposer.dispose(myUsagePreviewPanel); myUsagePreviewPanel = null; } + JScrollPane pane = ScrollPaneFactory.createScrollPane(myTree); + if (UsageViewSettings.getInstance().IS_PREVIEW_USAGES) { Splitter splitter = new Splitter(false, UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS); - splitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myTree)); + pane.putClientProperty(UIUtil.KEEP_BORDER_SIDES, SideBorder.RIGHT); + + splitter.setFirstComponent(pane); myUsagePreviewPanel = new UsagePreviewPanel(myProject); + myUsagePreviewPanel.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT)); Disposer.register(this, myUsagePreviewPanel); splitter.setSecondComponent(myUsagePreviewPanel); myCentralPanel.add(splitter, BorderLayout.CENTER); } else { - myCentralPanel.add(ScrollPaneFactory.createScrollPane(myTree), BorderLayout.CENTER); + myCentralPanel.add(pane, BorderLayout.CENTER); } myCentralPanel.add(myButtonPanel, BorderLayout.SOUTH); @@ -1212,6 +1215,8 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra } public void add(int index, final Runnable runnable, String text) { + if (getBorder() == null) setBorder(IdeBorderFactory.createBorder(SideBorder.TOP)); + final JButton button = new JButton(UIUtil.replaceMnemonicAmpersand(text)); DialogUtil.registerMnemonic(button); diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 57a7a6866bce..7dc2efb26f44 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -63,9 +63,11 @@ public class UIUtil { private static final Color UNFOCUSED_SELECTION_COLOR = new Color(212, 212, 212); - private static final Color ACTIVE_COLOR = new Color(160, 186, 213); - private static final Color INACTIVE_COLOR = new Color(128, 128, 128); - private static final Color SEPARATOR_COLOR = INACTIVE_COLOR.brighter(); + private static final Color ACTIVE_HEADER_COLOR = new Color(160, 186, 213); + private static final Color INACTIVE_HEADER_COLOR = new Color(128, 128, 128); + + private static final Color BORDER_COLOR = new Color(170, 170, 170); + public static final Pattern CLOSE_TAG_PATTERN = Pattern.compile("<\\s*([^<>/ ]+)([^<>]*)/\\s*>", Pattern.CASE_INSENSITIVE); @NonNls public static final String FOCUS_PROXY_KEY = "isFocusProxy"; @@ -97,7 +99,7 @@ public class UIUtil { final FontRenderContext frc = g.getFontRenderContext(); final Rectangle stringBounds = font.getStringBounds(string, frc).getBounds(); - return (int) (centerY - stringBounds.height / 2.0 - stringBounds.y); + return (int)(centerY - stringBounds.height / 2.0 - stringBounds.y); } public static void setEnabled(Component component, boolean enabled, boolean recursively) { @@ -118,12 +120,12 @@ public class UIUtil { g.drawLine(x1, y1, x2, y2); } - public static String[] splitText(String text, FontMetrics fontMetrics, int widthLimit, char separator){ + public static String[] splitText(String text, FontMetrics fontMetrics, int widthLimit, char separator) { ArrayList lines = new ArrayList(); String currentLine = ""; StringBuffer currentAtom = new StringBuffer(); - for (int i=0; i < text.length(); i++) { + for (int i = 0; i < text.length(); i++) { char ch = text.charAt(i); currentAtom.append(ch); @@ -679,13 +681,14 @@ public class UIUtil { /** * Should be invoked only in EDT. - * @param g Graphics surface - * @param startX Line start X coordinate - * @param endX Line end X coordinate - * @param lineY Line Y coordinate + * + * @param g Graphics surface + * @param startX Line start X coordinate + * @param endX Line end X coordinate + * @param lineY Line Y coordinate * @param bgColor Background color (optional) * @param fgColor Foreground color (optional) - * @param opaque If opaque the image will be dr + * @param opaque If opaque the image will be dr */ public static void drawBoldDottedLine(final Graphics2D g, final int startX, @@ -694,11 +697,12 @@ public class UIUtil { final Color bgColor, final Color fgColor, final boolean opaque) { - if (SystemInfo.isMac || SystemInfo.isLinux) { - drawAppleDottedLine(g, startX, endX, lineY, bgColor, fgColor, opaque); - } else { - drawBoringDottedLine(g, startX, endX, lineY, bgColor, fgColor, opaque); - } + if (SystemInfo.isMac || SystemInfo.isLinux) { + drawAppleDottedLine(g, startX, endX, lineY, bgColor, fgColor, opaque); + } + else { + drawBoringDottedLine(g, startX, endX, lineY, bgColor, fgColor, opaque); + } } private static void drawBoringDottedLine(final Graphics2D g, @@ -715,7 +719,7 @@ public class UIUtil { g.setColor(bgColor); drawLine(g, startX, lineY, endX, lineY); - drawLine(g, startX, lineY+1, endX, lineY+1); + drawLine(g, startX, lineY + 1, endX, lineY + 1); } // Draw dotted line: @@ -753,8 +757,8 @@ public class UIUtil { g.setColor(bgColor); drawLine(g, startX, lineY, endX, lineY); - drawLine(g, startX, lineY+1, endX, lineY+1); - drawLine(g, startX, lineY+2, endX, lineY+2); + drawLine(g, startX, lineY + 1, endX, lineY + 1); + drawLine(g, startX, lineY + 2, endX, lineY + 2); } // Draw apple like dotted line: @@ -781,7 +785,7 @@ public class UIUtil { final BufferedImage image = getAppleDotStamp(fgColor, oldColor); // Now copy our dot several times - final int dotX0 = (startX / step + startPosCorrection) * step; + final int dotX0 = (startX / step + startPosCorrection) * step; for (int dotXi = dotX0; dotXi < endX; dotXi += step) { g.drawImage(image, dotXi, lineY, null); } @@ -831,7 +835,7 @@ public class UIUtil { // dispose graphics g.dispose(); - + return image; } @@ -953,15 +957,13 @@ public class UIUtil { } @NotNull - public static - Color getBgFillColor(@NotNull JComponent c) { + public static Color getBgFillColor(@NotNull JComponent c) { final Component parent = findNearestOpaque(c); return parent == null ? c.getBackground() : parent.getBackground(); } @Nullable - public static - Component findNearestOpaque(JComponent c) { + public static Component findNearestOpaque(JComponent c) { Component eachParent = c; while (eachParent != null) { if (eachParent.isOpaque()) return eachParent; @@ -981,7 +983,9 @@ public class UIUtil { } public static boolean isStandardMenuLAF() { - return isWinLafOnVista() || "Nimbus".equals(UIManager.getLookAndFeel().getName()) || "GTK look and feel".equals(UIManager.getLookAndFeel().getName()); + return isWinLafOnVista() || + "Nimbus".equals(UIManager.getLookAndFeel().getName()) || + "GTK look and feel".equals(UIManager.getLookAndFeel().getName()); } public static Color getFocusedFillColor() { @@ -993,7 +997,7 @@ public class UIUtil { } public static Color getBoundsColor() { - return new Color(128, 128, 128); + return getBorderSeparatorColor(); } public static Color getBoundsColor(boolean focused) { @@ -1019,6 +1023,7 @@ public class UIUtil { } //todo maybe should do for all kind of listeners via the AWTEventMulticaster class + public static void dispose(final Component c) { if (c == null) return; @@ -1051,7 +1056,7 @@ public class UIUtil { }); } - private static boolean isToDispose(final JProgressBar progress) { + private static boolean isToDispose(final JProgressBar progress) { final ProgressBarUI ui = progress.getUI(); if (ui == null) return false; @@ -1115,16 +1120,37 @@ public class UIUtil { return true; } - public static Color getBorderActiveColor() { - return ACTIVE_COLOR; + public static Color getHeaderActiveColor() { + return ACTIVE_HEADER_COLOR; } + public static Color getHeaderInactiveColor() { + return INACTIVE_HEADER_COLOR; + } + + public static Color getBorderColor() { + return BORDER_COLOR; + } + + /** + * @deprecated use getBorderColor instead + */ public static Color getBorderInactiveColor() { - return INACTIVE_COLOR; + return getBorderColor(); } + /** + * @deprecated use getBorderColor instead + */ + public static Color getBorderActiveColor() { + return getBorderColor(); + } + + /** + * @deprecated use getBorderColor instead + */ public static Color getBorderSeparatorColor() { - return SEPARATOR_COLOR; + return getBorderColor(); } public static HTMLEditorKit getHTMLEditorKit() { @@ -1147,10 +1173,10 @@ public class UIUtil { if (component instanceof JScrollPane) { if (!hasNonPrimitiveParents(c, component)) { final JScrollPane scrollPane = (JScrollPane)component; - Integer keepBorderSides = (Integer) scrollPane.getClientProperty(KEEP_BORDER_SIDES); + Integer keepBorderSides = (Integer)scrollPane.getClientProperty(KEEP_BORDER_SIDES); if (keepBorderSides != null) { if (scrollPane.getBorder() instanceof LineBorder) { - Color color = ((LineBorder) scrollPane.getBorder()).getLineColor(); + Color color = ((LineBorder)scrollPane.getBorder()).getLineColor(); scrollPane.setBorder(new SideBorder(color, keepBorderSides.intValue())); } else { @@ -1219,7 +1245,8 @@ public class UIUtil { public static void invokeLaterIfNeeded(@NotNull Runnable runnable) { if (SwingUtilities.isEventDispatchThread()) { runnable.run(); - } else { + } + else { SwingUtilities.invokeLater(runnable); } } @@ -1234,7 +1261,8 @@ public class UIUtil { public static void invokeAndWaitIfNeeded(@NotNull Runnable runnable) { if (SwingUtilities.isEventDispatchThread()) { runnable.run(); - } else { + } + else { try { SwingUtilities.invokeAndWait(runnable); } @@ -1261,14 +1289,15 @@ public class UIUtil { public static class MacTreeUI extends BasicTreeUI { public static final String SOURCE_LIST_CLIENT_PROPERTY = "mac.ui.source.list"; - private static final Icon TREE_COLLAPSED_ICON = (Icon) UIManager.get("Tree.collapsedIcon"); - private static final Icon TREE_EXPANDED_ICON = (Icon) UIManager.get("Tree.expandedIcon"); + private static final Icon TREE_COLLAPSED_ICON = (Icon)UIManager.get("Tree.collapsedIcon"); + private static final Icon TREE_EXPANDED_ICON = (Icon)UIManager.get("Tree.expandedIcon"); private static final Icon TREE_SELECTED_COLLAPSED_ICON = IconLoader.getIcon("/mac/tree_white_right_arrow.png"); private static final Icon TREE_SELECTED_EXPANDED_ICON = IconLoader.getIcon("/mac/tree_white_down_arrow.png"); - private static final Border LIST_BACKGROUND_PAINTER = (Border) UIManager.get("List.sourceListBackgroundPainter"); - private static final Border LIST_SELECTION_BACKGROUND_PAINTER = (Border) UIManager.get("List.sourceListSelectionBackgroundPainter"); - private static final Border LIST_FOCUSED_SELECTION_BACKGROUND_PAINTER = (Border) UIManager.get("List.sourceListFocusedSelectionBackgroundPainter"); + private static final Border LIST_BACKGROUND_PAINTER = (Border)UIManager.get("List.sourceListBackgroundPainter"); + private static final Border LIST_SELECTION_BACKGROUND_PAINTER = (Border)UIManager.get("List.sourceListSelectionBackgroundPainter"); + private static final Border LIST_FOCUSED_SELECTION_BACKGROUND_PAINTER = + (Border)UIManager.get("List.sourceListFocusedSelectionBackgroundPainter"); private boolean myWideSelection; private boolean myOldRepaintAllRowValue; @@ -1285,22 +1314,22 @@ public class UIUtil { private MouseListener mySelectionListener = new MouseAdapter() { @Override public void mousePressed(@NotNull final MouseEvent e) { - final JTree tree = (JTree) e.getSource(); + final JTree tree = (JTree)e.getSource(); if (SwingUtilities.isLeftMouseButton(e) && !e.isPopupTrigger()) { // if we can't stop any ongoing editing, do nothing if (isEditing(tree) && tree.getInvokesStopCellEditing() - && !stopEditing(tree)) { - return; + && !stopEditing(tree)) { + return; } - + final TreePath pressedPath = getClosestPathForLocation(tree, e.getX(), e.getY()); if (tree.isPathSelected(pressedPath)) return; if (pressedPath != null) { Rectangle bounds = getPathBounds(tree, pressedPath); - if(e.getY() >= (bounds.y + bounds.height)) { - return; + if (e.getY() >= (bounds.y + bounds.height)) { + return; } if (isLocationInExpandControl(pressedPath, e.getX(), e.getY())) { @@ -1308,7 +1337,7 @@ public class UIUtil { } if (tree.getDragEnabled() || !startEditing(pressedPath, e)) { - selectPathForEvent(pressedPath, e); + selectPathForEvent(pressedPath, e); } } @@ -1425,11 +1454,13 @@ public class UIUtil { else { LIST_SELECTION_BACKGROUND_PAINTER.paintBorder(tree, rowGraphics, xOffset, bounds.y, containerWidth, bounds.height); } - } else { + } + else { rowGraphics.setColor(tree.getBackground()); rowGraphics.fillRect(xOffset, bounds.y, containerWidth, bounds.height); } - } else { + } + else { Color bg = tree.hasFocus() ? getTreeSelectionBackground() : getListUnfocusedSelectionBackground(); if (!selected) { bg = tree.getBackground(); @@ -1445,7 +1476,8 @@ public class UIUtil { super.paintRow(rowGraphics, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf); rowGraphics.dispose(); - } else { + } + else { super.paintRow(g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf); } } @@ -1497,9 +1529,9 @@ public class UIUtil { boolean isPathSelected = tree.getSelectionModel().isPathSelected(path); Icon expandIcon = isPathSelected && tree.hasFocus() ? TREE_SELECTED_EXPANDED_ICON - : TREE_EXPANDED_ICON; + : TREE_EXPANDED_ICON; Icon collapseIcon = isPathSelected && tree.hasFocus() ? TREE_SELECTED_COLLAPSED_ICON - : TREE_COLLAPSED_ICON; + : TREE_COLLAPSED_ICON; if (!isLeaf(row)) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesTreeBrowser.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesTreeBrowser.java index bca3f6f311c7..0d1e280aa977 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesTreeBrowser.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesTreeBrowser.java @@ -57,7 +57,7 @@ import java.util.List; * @author yole */ public class CommittedChangesTreeBrowser extends JPanel implements TypeSafeDataProvider, Disposable, DecoratorManager { - private static final Border RIGHT_BORDER = IdeBorderFactory.createSimpleBorder(1, 1, 0, 0); + private static final Border RIGHT_BORDER = IdeBorderFactory.createBorder(SideBorder.TOP | SideBorder.LEFT); private final Project myProject; private final Tree myChangesTree; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/WiseSplitter.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/WiseSplitter.java index c296bb04aad9..c7e57188bd49 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/WiseSplitter.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/WiseSplitter.java @@ -20,6 +20,7 @@ import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.ui.ThreeComponentsSplitter; import com.intellij.openapi.util.Disposer; import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.SideBorder; import javax.swing.*; import javax.swing.border.Border; @@ -28,8 +29,8 @@ import java.util.HashMap; import java.util.Map; public class WiseSplitter implements Disposable { - private static final Border LEFT_BORDER = IdeBorderFactory.createSimpleBorder(1, 0, 0, 1); - private static final Border MIDDLE_BORDER = IdeBorderFactory.createSimpleBorder(1, 1, 0, 1); + private static final Border LEFT_BORDER = IdeBorderFactory.createBorder(SideBorder.TOP | SideBorder.RIGHT); + private static final Border MIDDLE_BORDER = IdeBorderFactory.createBorder(SideBorder.TOP | SideBorder.LEFT | SideBorder.RIGHT); private final Runnable myRefresher; private final Splitter myParentSplitter; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java index 26409c7174a0..afe93acabff9 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java @@ -651,7 +651,7 @@ public class FileHistoryPanelImpl Date: Thu, 5 Aug 2010 12:53:45 +0400 Subject: [PATCH 14/18] UI: borders --- .../openapi/ui/SimpleToolWindowPanel.java | 28 +++++++-- .../intellij/ui/components/JBScrollPane.java | 60 ++++++++++--------- .../openapi/editor/impl/EditorImpl.java | 4 +- .../usages/impl/UsagePreviewPanel.java | 1 + .../util/src/com/intellij/util/ui/UIUtil.java | 2 +- 5 files changed, 58 insertions(+), 37 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java b/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java index bf45c5f64da1..5db53a0c3157 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java @@ -27,6 +27,7 @@ import org.jetbrains.annotations.NonNls; import javax.swing.*; import java.awt.*; +import java.awt.event.*; import java.util.*; import java.util.List; @@ -48,6 +49,29 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider myBorderless = borderless; myVertical = vertical; setProvideQuickActions(true); + + addContainerListener(new ContainerAdapter() { + @Override + public void componentAdded(ContainerEvent e) { + Component child = e.getChild(); + + if (child instanceof Container) { + ((Container)child).addContainerListener(this); + } + if (myBorderless) { + UIUtil.removeScrollBorder(SimpleToolWindowPanel.this); + } + } + + @Override + public void componentRemoved(ContainerEvent e) { + Component child = e.getChild(); + + if (child instanceof Container) { + ((Container)child).removeContainerListener(this); + } + } + }); } public void setToolbar(JComponent c) { @@ -59,10 +83,6 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider add(c, BorderLayout.WEST); } - if (myBorderless) { - UIUtil.removeScrollBorder(c); - } - revalidate(); repaint(); } diff --git a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java index c49445d58eb8..1ea304064a9e 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java @@ -53,35 +53,7 @@ public class JBScrollPane extends JScrollPane { public void setUI(ScrollPaneUI ui) { super.setUI(ui); - setViewportBorder(new Border() { - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - JViewport vp = getViewport(); - if (vp == null) return; - - Component view = vp.getView(); - if (view == null) return; - - Color bg = view.getBackground(); - if (bg == null) return; - - g.setColor(bg); - g.drawLine(0, 0, width - 1, 0); - g.drawLine(0, height - 1, width - 1, height - 1); - g.drawLine(0, 0, 0, height - 1); - g.drawLine(width - 1, 0, width - 1, height - 1); - } - - @Override - public Insets getBorderInsets(Component c) { - return new Insets(1, 1, 1, 1); - } - - @Override - public boolean isBorderOpaque() { - return true; - } - }); + setViewportBorder(new MyVewportBorder()); } @Override @@ -138,4 +110,34 @@ public class JBScrollPane extends JScrollPane { } } } + + private class MyVewportBorder implements Border { + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + JViewport vp = getViewport(); + if (vp == null) return; + + Component view = vp.getView(); + if (view == null) return; + + Color bg = view.getBackground(); + if (bg == null) return; + + g.setColor(bg); + g.drawLine(0, 0, width - 1, 0); + g.drawLine(0, height - 1, width - 1, height - 1); + g.drawLine(0, 0, 0, height - 1); + g.drawLine(width - 1, 0, width - 1, height - 1); + } + + @Override + public Insets getBorderInsets(Component c) { + return new Insets(1, 1, 1, 1); + } + + @Override + public boolean isBorderOpaque() { + return true; + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 40f6a10ee34d..ba8ad144f6ce 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -350,8 +350,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myEditorComponent = new EditorComponentImpl(this); myScrollPane = new MyScrollPane(); - myScrollPane.setBorder(null); - myPanel = new JPanel(); myHeaderPanel = new MyHeaderPanel(); @@ -2560,7 +2558,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } public void setBorder(Border border) { - myPanel.setBorder(border); + myScrollPane.setBorder(border); } public int logicalPositionToOffset(@NotNull LogicalPosition pos) { diff --git a/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java b/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java index cea1a024d4f4..2def25aa34e5 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java @@ -75,6 +75,7 @@ public class UsagePreviewPanel extends JPanel implements Disposable { removeAll(); myEditor = createEditor(psiFile, document); if (myEditor == null) return; + myEditor.setBorder(null); add(myEditor.getComponent(), BorderLayout.CENTER); revalidate(); diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 7dc2efb26f44..031921ed0172 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -997,7 +997,7 @@ public class UIUtil { } public static Color getBoundsColor() { - return getBorderSeparatorColor(); + return getBorderColor(); } public static Color getBoundsColor(boolean focused) { From 2fd465e3a73becbbffa8465a17dcbe80ed7f2105 Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Thu, 5 Aug 2010 13:27:41 +0400 Subject: [PATCH 15/18] IDEA-21675 Default and active buttons in the open project frame confirmation --- .../javaCompiler/BackendCompilerWrapper.java | 2 +- .../com/intellij/ide/impl/NewProjectUtil.java | 2 +- .../intellij/openapi/ui/DialogWrapper.java | 10 ++- .../src/com/intellij/openapi/ui/Messages.java | 72 ++++++++++++++----- .../com/intellij/ide/impl/ProjectUtil.java | 2 +- .../PlatformProjectOpenProcessor.java | 2 +- 6 files changed, 67 insertions(+), 23 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java index 3e41738c0d3e..ce39f72ccdea 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java @@ -176,7 +176,7 @@ public class BackendCompilerWrapper { } } finally { - if (fileToDelete != null) { + if (fileToDelete != null && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) { FileUtil.asyncDelete(fileToDelete); } } diff --git a/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java b/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java index 175e0865360f..3a55f74021bd 100644 --- a/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java +++ b/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java @@ -189,7 +189,7 @@ public class NewProjectUtil { Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); if (openProjects.length > 0) { int exitCode = Messages.showDialog(IdeBundle.message("prompt.open.project.in.new.frame"), IdeBundle.message("title.new.project"), - new String[]{IdeBundle.message("button.newframe"), IdeBundle.message("button.existingframe")}, 1, + new String[]{IdeBundle.message("button.newframe"), IdeBundle.message("button.existingframe")}, 1, 0, Messages.getQuestionIcon()); if (exitCode == 1) { // "No" option ProjectUtil.closeProject(projectToClose != null ? projectToClose : openProjects[openProjects.length - 1]); diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index bf1149306301..259fd4249c13 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -74,6 +74,8 @@ public abstract class DialogWrapper { */ @NonNls public static final String DEFAULT_ACTION = "DefaultAction"; + @NonNls public static final String FOCUSED_ACTION = "FocusedAction"; + private final DialogWrapperPeer myPeer; private int myExitCode = CANCEL_EXIT_CODE; @@ -107,6 +109,8 @@ public abstract class DialogWrapper { @Nullable private DoNotAskOption myDoNotAsk; + private JComponent myPreferredFocusedComponent; + protected String getDoNotShowMessage() { return CommonBundle.message("dialog.options.do.not.show"); } @@ -370,6 +374,10 @@ public abstract class DialogWrapper { button.setMnemonic(mnemonic); } + if (action.getValue(FOCUSED_ACTION) != null) { + myPreferredFocusedComponent = button; + } + buttons.add(button); buttonsPanel.add(button); } @@ -706,7 +714,7 @@ public abstract class DialogWrapper { */ @Nullable public JComponent getPreferredFocusedComponent() { - return null; + return SystemInfo.isMac ? myPreferredFocusedComponent : null; } /** diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java index 249abf64d253..35909e5e5c26 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java @@ -90,11 +90,15 @@ public class Messages { } public static int showDialog(Project project, String message, String title, String[] options, int defaultOptionIndex, Icon icon) { + return showDialog(project, message, title, options, defaultOptionIndex, -1, icon); + } + + public static int showDialog(Project project, String message, String title, String[] options, int defaultOptionIndex, int focusedOptionIndex, Icon icon) { if (isApplicationInUnitTestOrHeadless()) { return ourTestImplementation.show(message); } else { - MessageDialog dialog = new MessageDialog(project, message, title, options, defaultOptionIndex, icon); + MessageDialog dialog = new MessageDialog(project, message, title, options, defaultOptionIndex, focusedOptionIndex, icon); dialog.show(); return dialog.getExitCode(); } @@ -106,11 +110,27 @@ public class Messages { } public static int showDialog(Component parent, String message, String title, String[] options, int defaultOptionIndex, Icon icon) { + return showDialog(parent, message, title, options, defaultOptionIndex, icon); + } + + public static int showDialog(Component parent, String message, String title, String[] options, int defaultOptionIndex, int focusedOptionIndex, Icon icon) { if (isApplicationInUnitTestOrHeadless()) { return ourTestImplementation.show(message); } else { - MessageDialog dialog = new MessageDialog(parent, message, title, options, defaultOptionIndex, icon); + MessageDialog dialog = new MessageDialog(parent, message, title, options, defaultOptionIndex, focusedOptionIndex, icon); + dialog.show(); + return dialog.getExitCode(); + } + } + + public static int showDialog(String message, String title, String[] options, int defaultOptionIndex, int focusedOptionIndex, Icon icon, DialogWrapper.DoNotAskOption doNotAskOption) { + if (isApplicationInUnitTestOrHeadless()) { + return ourTestImplementation.show(message); + } + else { + //what's it? if (application.isUnitTestMode()) throw new RuntimeException(message); + MessageDialog dialog = new MessageDialog(message, title, options, defaultOptionIndex, focusedOptionIndex, icon, doNotAskOption); dialog.show(); return dialog.getExitCode(); } @@ -123,19 +143,15 @@ public class Messages { * @see #showDialog(Component, String, String, String[], int, Icon) */ public static int showDialog(String message, String title, String[] options, int defaultOptionIndex, Icon icon, DialogWrapper.DoNotAskOption doNotAskOption) { - if (isApplicationInUnitTestOrHeadless()) { - return ourTestImplementation.show(message); - } - else { - //what's it? if (application.isUnitTestMode()) throw new RuntimeException(message); - MessageDialog dialog = new MessageDialog(message, title, options, defaultOptionIndex, icon, doNotAskOption); - dialog.show(); - return dialog.getExitCode(); - } + return showDialog(message, title, options, defaultOptionIndex, -1, icon, doNotAskOption); } public static int showDialog(String message, String title, String[] options, int defaultOptionIndex, Icon icon) { - return showDialog(message, title, options, defaultOptionIndex, icon, null); + return showDialog(message, title, options, defaultOptionIndex, -1, icon); + } + + public static int showDialog(String message, String title, String[] options, int defaultOptionIndex, int focusedOptionIndex, Icon icon) { + return showDialog(message, title, options, defaultOptionIndex, focusedOptionIndex, icon, null); } /** @@ -486,33 +502,47 @@ public class Messages { protected String myMessage; protected String[] myOptions; protected int myDefaultOptionIndex; + protected int myFocusedOptionIndex; protected Icon myIcon; public MessageDialog(Project project, String message, String title, String[] options, int defaultOptionIndex, Icon icon) { + this(project, message, title, options, defaultOptionIndex, -1, icon); + } + + public MessageDialog(Project project, String message, String title, String[] options, int defaultOptionIndex, int focusedOptionIndex, Icon icon) { super(project, false); - _init(title, message, options, defaultOptionIndex, icon, null); + _init(title, message, options, defaultOptionIndex, focusedOptionIndex, icon, null); } public MessageDialog(Component parent, String message, String title, String[] options, int defaultOptionIndex, Icon icon) { + this(parent, message, title, options, defaultOptionIndex, -1, icon); + } + + public MessageDialog(Component parent, String message, String title, String[] options, int defaultOptionIndex, int focusedOptionIndex, Icon icon) { super(parent, false); - _init(title, message, options, defaultOptionIndex, icon, null); + _init(title, message, options, defaultOptionIndex, focusedOptionIndex, icon, null); } public MessageDialog(String message, String title, String[] options, int defaultOptionIndex, Icon icon) { super(false); - _init(title, message, options, defaultOptionIndex, icon, null); + _init(title, message, options, defaultOptionIndex, -1, icon, null); + } + + public MessageDialog(String message, String title, String[] options, int defaultOptionIndex, int focusedOptionIndex, Icon icon, DoNotAskOption doNotAskOption) { + super(false); + _init(title, message, options, defaultOptionIndex, focusedOptionIndex, icon, doNotAskOption); } public MessageDialog(String message, String title, String[] options, int defaultOptionIndex, Icon icon, DoNotAskOption doNotAskOption) { - super(false); - _init(title, message, options, defaultOptionIndex, icon, doNotAskOption); + this(message, title, options, defaultOptionIndex, -1, icon, doNotAskOption); } - private void _init(String title, String message, String[] options, int defaultOptionIndex, Icon icon, DoNotAskOption doNotAskOption) { + private void _init(String title, String message, String[] options, int defaultOptionIndex, int focusedOptionIndex, Icon icon, DoNotAskOption doNotAskOption) { setTitle(title); myMessage = message; myOptions = options; myDefaultOptionIndex = defaultOptionIndex; + myFocusedOptionIndex = focusedOptionIndex; myIcon = icon; setButtonsAlignment(SwingUtilities.CENTER); setDoNotAskOption(doNotAskOption); @@ -529,9 +559,15 @@ public class Messages { close(exitCode, true); } }; + if (i == myDefaultOptionIndex) { actions[i].putValue(DEFAULT_ACTION, Boolean.TRUE); } + + if (i == myFocusedOptionIndex) { + actions[i].putValue(FOCUSED_ACTION, Boolean.TRUE); + } + assignMnemonic(option, actions[i]); } diff --git a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java index d164f33a7464..c7c32794d651 100644 --- a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java @@ -156,7 +156,7 @@ public class ProjectUtil { if (settings.getConfirmOpenNewProject() < 0) { exitCode = Messages.showDialog(IdeBundle.message("prompt.open.project.in.new.frame"), IdeBundle.message("title.open.project"), new String[]{IdeBundle.message("button.newframe"), IdeBundle.message("button.existingframe"), - CommonBundle.getCancelButtonText()}, 1, Messages.getQuestionIcon(), new DialogWrapper.DoNotAskOption() { + CommonBundle.getCancelButtonText()}, 1, 0, Messages.getQuestionIcon(), new DialogWrapper.DoNotAskOption() { public boolean isToBeShown() { return true; } diff --git a/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java b/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java index 1834a3813a0b..e8aa291a72ff 100644 --- a/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java +++ b/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java @@ -75,7 +75,7 @@ public class PlatformProjectOpenProcessor extends ProjectOpenProcessor { if (!forceOpenInNewFrame && openProjects.length > 0) { int exitCode = Messages.showDialog(IdeBundle.message("prompt.open.project.in.new.frame"), IdeBundle.message("title.open.project"), new String[]{IdeBundle.message("button.newframe"), IdeBundle.message("button.existingframe"), - CommonBundle.getCancelButtonText()}, 1, Messages.getQuestionIcon()); + CommonBundle.getCancelButtonText()}, 1, 0, Messages.getQuestionIcon()); if (exitCode == 1) { // "No" option if (!ProjectUtil.closeProject(projectToClose != null ? projectToClose : openProjects[openProjects.length - 1])) return null; } From b46c1f58a47137b502aebb945dcedfe5d557c487 Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 5 Aug 2010 11:42:52 +0400 Subject: [PATCH 16/18] added method to ModuleRootModel to get source roots without tests --- .../ArtifactBySourceFileFinderImpl.java | 11 ++------ .../impl/artifacts/ArtifactUtil.java | 26 ++++++------------ .../com/intellij/analysis/AnalysisScope.java | 8 +----- .../openapi/roots/ModuleRootModel.java | 26 +++++++++++++++++- .../openapi/roots/ProjectRootsTraversing.java | 15 +---------- .../roots/impl/ModuleRootManagerImpl.java | 15 +++++++++-- .../roots/impl/OrderRootsEnumeratorImpl.java | 27 ++----------------- .../openapi/roots/impl/RootModelImpl.java | 17 +++++++++--- 8 files changed, 66 insertions(+), 79 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactBySourceFileFinderImpl.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactBySourceFileFinderImpl.java index aad584cacd02..cbff9ef68971 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactBySourceFileFinderImpl.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactBySourceFileFinderImpl.java @@ -17,9 +17,7 @@ package com.intellij.packaging.impl.artifacts; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModuleRootModel; -import com.intellij.openapi.roots.SourceFolder; import com.intellij.openapi.util.ModificationTracker; import com.intellij.openapi.util.MultiValuesMap; import com.intellij.openapi.vfs.VirtualFile; @@ -90,13 +88,8 @@ public class ArtifactBySourceFileFinderImpl extends ArtifactBySourceFileFinder { final Module module = ((ModuleOutputPackagingElement)element).findModule(context); if (module != null) { final ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module); - for (ContentEntry contentEntry : rootModel.getContentEntries()) { - for (SourceFolder sourceFolder : contentEntry.getSourceFolders()) { - final VirtualFile sourceRoot = sourceFolder.getFile(); - if (sourceRoot != null && !sourceFolder.isTestSource()) { - result.put(sourceRoot, artifact); - } - } + for (VirtualFile sourceRoot : rootModel.getSourceRoots(false)) { + result.put(sourceRoot, artifact); } } } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java index da39774c3698..f9a512ffbb73 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java @@ -19,9 +19,7 @@ import com.intellij.compiler.CompilerConfiguration; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.CompilerProjectExtension; -import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModuleRootModel; -import com.intellij.openapi.roots.SourceFolder; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Trinity; @@ -365,12 +363,9 @@ public class ArtifactUtil { final Module module = moduleElement.findModule(context); if (module != null) { final ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module); - for (ContentEntry entry : rootModel.getContentEntries()) { - for (SourceFolder folder : entry.getSourceFolders()) { - final VirtualFile sourceRoot = folder.getFile(); - if (!folder.isTestSource() && sourceRoot != null && VfsUtil.isAncestor(sourceRoot, file, true)) { - return VfsUtil.getRelativePath(file, sourceRoot, '/'); - } + for (VirtualFile sourceRoot : rootModel.getSourceRoots(false)) { + if (VfsUtil.isAncestor(sourceRoot, file, true)) { + return VfsUtil.getRelativePath(file, sourceRoot, '/'); } } } @@ -428,16 +423,11 @@ public class ArtifactUtil { final Module module = ((ModuleOutputPackagingElement)element).findModule(context); if (module != null) { final CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(context.getProject()); - final ContentEntry[] contentEntries = context.getModulesProvider().getRootModel(module).getContentEntries(); - for (ContentEntry contentEntry : contentEntries) { - for (SourceFolder sourceFolder : contentEntry.getSourceFolders()) { - final VirtualFile sourceRoot = sourceFolder.getFile(); - if (!sourceFolder.isTestSource() && sourceRoot != null) { - final VirtualFile sourceFile = sourceRoot.findFileByRelativePath(path); - if (sourceFile != null && compilerConfiguration.isResourceFile(sourceFile)) { - result.add(sourceFile); - } - } + final ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module); + for (VirtualFile sourceRoot : rootModel.getSourceRoots(false)) { + final VirtualFile sourceFile = sourceRoot.findFileByRelativePath(path); + if (sourceFile != null && compilerConfiguration.isResourceFile(sourceFile)) { + result.add(sourceFile); } } } diff --git a/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java b/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java index 69e9a5b7213b..1377642f7947 100644 --- a/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java +++ b/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java @@ -677,13 +677,7 @@ public class AnalysisScope { } private static boolean isTestOnly(Module module) { - final ContentEntry[] contentEntries = ModuleRootManager.getInstance(module).getContentEntries(); - for (ContentEntry contentEntry : contentEntries) { - for (SourceFolder folder : contentEntry.getSourceFolders()) { - if (!folder.isTestSource()) return false; - } - } - return true; + return ModuleRootManager.getInstance(module).getSourceRootUrls(false).length == 0; } public boolean isIncludeTestSource() { diff --git a/platform/lang-api/src/com/intellij/openapi/roots/ModuleRootModel.java b/platform/lang-api/src/com/intellij/openapi/roots/ModuleRootModel.java index e10c020bc459..956330b4a056 100644 --- a/platform/lang-api/src/com/intellij/openapi/roots/ModuleRootModel.java +++ b/platform/lang-api/src/com/intellij/openapi/roots/ModuleRootModel.java @@ -110,17 +110,41 @@ public interface ModuleRootModel { * * @return the array of source roots. * @see #getContentEntries() + * @see #getSourceRoots(boolean) */ - @NotNull VirtualFile[] getSourceRoots(); + @NotNull + VirtualFile[] getSourceRoots(); + + /** + * Returns an array of source roots from all content entries. A helper method. + * + * @param includingTests determines whether test source roots should be included in the result + * @return the array of source roots. + * @see #getContentEntries() + * @since 10.0 + */ + @NotNull + VirtualFile[] getSourceRoots(boolean includingTests); /** * Returns an array of source root urls from all content entries. A helper method. * * @return the array of source root URLs. * @see #getContentEntries() + * @see #getSourceRootUrls(boolean) */ @NotNull String[] getSourceRootUrls(); + /** + * Returns an array of source root urls from all content entries. A helper method. + * + * @param includingTests determines whether test source root urls should be included in the result + * @return the array of source root URLs. + * @see #getContentEntries() + * @since 10.0 + */ + @NotNull String[] getSourceRootUrls(boolean includingTests); + /** * Returns an exploded directory path of the module, if it is valid. * diff --git a/platform/lang-api/src/com/intellij/openapi/roots/ProjectRootsTraversing.java b/platform/lang-api/src/com/intellij/openapi/roots/ProjectRootsTraversing.java index 907ba77b35a0..b748e0c63d61 100644 --- a/platform/lang-api/src/com/intellij/openapi/roots/ProjectRootsTraversing.java +++ b/platform/lang-api/src/com/intellij/openapi/roots/ProjectRootsTraversing.java @@ -252,20 +252,7 @@ public class ProjectRootsTraversing { } public void visit(ModuleSourceOrderEntry orderEntry, TraverseState state, RootPolicy policy) { - if (myExcludeTests) { - ContentEntry[] contentEntries = ModuleRootManager.getInstance(orderEntry.getOwnerModule()).getContentEntries(); - for (ContentEntry contentEntry : contentEntries) { - for (SourceFolder folder : contentEntry.getSourceFolders()) { - VirtualFile root = folder.getFile(); - if (root != null && !folder.isTestSource()) { - state.add(root); - } - } - } - } - else { - state.addAll(orderEntry.getFiles(OrderRootType.SOURCES)); - } + state.addAll(ModuleRootManager.getInstance(orderEntry.getOwnerModule()).getSourceRoots(!myExcludeTests)); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java index 159476375ec6..a14ae6dc9be5 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java @@ -359,14 +359,25 @@ public class ModuleRootManagerImpl extends ModuleRootManager implements ModuleCo @NotNull public String[] getSourceRootUrls() { + return getSourceRootUrls(true); + } + + @NotNull + @Override + public String[] getSourceRootUrls(boolean includingTests) { LOG.assertTrue(!myIsDisposed); - return myRootModel.getSourceRootUrls(); + return myRootModel.getSourceRootUrls(includingTests); } @NotNull public VirtualFile[] getSourceRoots() { + return getSourceRoots(true); + } + + @NotNull + public VirtualFile[] getSourceRoots(final boolean includingTests) { LOG.assertTrue(!myIsDisposed); - return myRootModel.getSourceRoots(); + return myRootModel.getSourceRoots(includingTests); } public void projectOpened() { diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java index fc43f4517a50..816e7127a3a2 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java @@ -171,19 +171,7 @@ public class OrderRootsEnumeratorImpl implements OrderRootsEnumerator { private void collectModuleRoots(ModuleRootModel rootModel, Collection result) { if (myRootType.equals(OrderRootType.SOURCES)) { - if (myOrderEnumerator.isProductionOnly()) { - for (ContentEntry contentEntry : rootModel.getContentEntries()) { - for (SourceFolder folder : contentEntry.getSourceFolders()) { - VirtualFile root = folder.getFile(); - if (root != null && !folder.isTestSource()) { - result.add(root); - } - } - } - } - else { - Collections.addAll(result, rootModel.getSourceRoots()); - } + Collections.addAll(result, rootModel.getSourceRoots(!myOrderEnumerator.isProductionOnly())); } else if (myRootType.equals(OrderRootType.CLASSES)) { final CompilerModuleExtension extension = rootModel.getModuleExtension(CompilerModuleExtension.class); @@ -195,18 +183,7 @@ public class OrderRootsEnumeratorImpl implements OrderRootsEnumerator { private void collectModuleRootsUrls(ModuleRootModel rootModel, Collection result) { if (myRootType.equals(OrderRootType.SOURCES)) { - if (myOrderEnumerator.isProductionOnly()) { - for (ContentEntry contentEntry : rootModel.getContentEntries()) { - for (SourceFolder folder : contentEntry.getSourceFolders()) { - if (!folder.isTestSource()) { - result.add(folder.getUrl()); - } - } - } - } - else { - Collections.addAll(result, rootModel.getSourceRootUrls()); - } + Collections.addAll(result, rootModel.getSourceRootUrls(!myOrderEnumerator.isProductionOnly())); } else if (myRootType.equals(OrderRootType.CLASSES)) { final CompilerModuleExtension extension = rootModel.getModuleExtension(CompilerModuleExtension.class); diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java index 7f7fe69047d7..46d535eba037 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java @@ -325,11 +325,18 @@ public class RootModelImpl implements ModifiableRootModel { @NotNull public String[] getSourceRootUrls() { + return getSourceRootUrls(true); + } + + @NotNull + public String[] getSourceRootUrls(boolean includingTests) { List result = new SmartList(); for (ContentEntry contentEntry : myContent) { final SourceFolder[] sourceFolders = contentEntry.getSourceFolders(); for (SourceFolder sourceFolder : sourceFolders) { - result.add(sourceFolder.getUrl()); + if (includingTests || !sourceFolder.isTestSource()) { + result.add(sourceFolder.getUrl()); + } } } return ContainerUtil.toArray(result, new String[result.size()]); @@ -337,12 +344,17 @@ public class RootModelImpl implements ModifiableRootModel { @NotNull public VirtualFile[] getSourceRoots() { + return getSourceRoots(true); + } + + @NotNull + public VirtualFile[] getSourceRoots(final boolean includingTests) { List result = new SmartList(); for (ContentEntry contentEntry : myContent) { final SourceFolder[] sourceFolders = contentEntry.getSourceFolders(); for (SourceFolder sourceFolder : sourceFolders) { final VirtualFile file = sourceFolder.getFile(); - if (file != null) { + if (file != null && (includingTests || !sourceFolder.isTestSource())) { result.add(file); } } @@ -1061,4 +1073,3 @@ public class RootModelImpl implements ModifiableRootModel { Disposer.register(myDisposable, disposable); } } - From 6a8fa26b865037257e879120f80bbe3734b1bd00 Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 5 Aug 2010 13:37:36 +0400 Subject: [PATCH 17/18] not-null instrumentation fixed for static inner classes --- .../NotNullVerifyingInstrumenter.java | 24 +------ .../NonStaticInnerClass.java | 12 ++++ .../notNullVerification/StaticInnerClass.java | 12 ++++ .../NotNullVerifyingInstrumenterTest.java | 62 ++++++++++++++----- 4 files changed, 72 insertions(+), 38 deletions(-) create mode 100644 java/java-tests/testData/compiler/notNullVerification/NonStaticInnerClass.java create mode 100644 java/java-tests/testData/compiler/notNullVerification/StaticInnerClass.java diff --git a/java/compiler/notNull/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java b/java/compiler/notNull/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java index 62cf1608aa7d..02abbc67e238 100644 --- a/java/compiler/notNull/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java +++ b/java/compiler/notNull/src/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenter.java @@ -25,12 +25,9 @@ import java.util.ArrayList; */ public class NotNullVerifyingInstrumenter extends ClassAdapter implements Opcodes { private boolean myIsModification = false; - private boolean myIsNotStaticInner = false; private String myClassName; - private String mySuperName; public static final String NOT_NULL = "org/jetbrains/annotations/NotNull"; public static final String NOT_NULL_ANNO = "L"+ NOT_NULL + ";"; - private static final String ENUM_CLASS_NAME = "java/lang/Enum"; public static final String IAE_CLASS_NAME = "java/lang/IllegalArgumentException"; public static final String ISE_CLASS_NAME = "java/lang/IllegalStateException"; private static final String CONSTRUCTOR_NAME = ""; @@ -51,14 +48,6 @@ public class NotNullVerifyingInstrumenter extends ClassAdapter implements Opcode final String[] interfaces) { super.visit(version, access, name, signature, superName, interfaces); myClassName = name; - mySuperName = superName; - } - - public void visitInnerClass(final String name, final String outerName, final String innerName, final int access) { - super.visitInnerClass(name, outerName, innerName, access); - if (myClassName.equals(name)) { - myIsNotStaticInner = (access & ACC_STATIC) == 0; - } } public MethodVisitor visitMethod( @@ -69,7 +58,6 @@ public class NotNullVerifyingInstrumenter extends ClassAdapter implements Opcode final String[] exceptions) { final Type[] args = Type.getArgumentTypes(desc); final Type returnType = Type.getReturnType(desc); - final int startParameter = getStartParameterIndex(name); MethodVisitor v = cv.visitMethod(access, name, desc, @@ -123,7 +111,7 @@ public class NotNullVerifyingInstrumenter extends ClassAdapter implements Opcode for (int p = 0; p < myNotNullParams.size(); ++p) { int var = ((access & ACC_STATIC) == 0) ? 1 : 0; int param = ((Integer)myNotNullParams.get(p)).intValue(); - for (int i = 0; i < startParameter + param; ++i) { + for (int i = 0; i < param; ++i) { var += args[i].getSize(); } mv.visitVarInsn(ALOAD, var); @@ -192,16 +180,6 @@ public class NotNullVerifyingInstrumenter extends ClassAdapter implements Opcode }; } - private int getStartParameterIndex(final String name) { - int result = 0; - if (CONSTRUCTOR_NAME.equals(name)) { - if (myIsNotStaticInner) { - result += 1; - } - } - return result; - } - private static boolean isReferenceType(final Type type) { return type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY; } diff --git a/java/java-tests/testData/compiler/notNullVerification/NonStaticInnerClass.java b/java/java-tests/testData/compiler/notNullVerification/NonStaticInnerClass.java new file mode 100644 index 000000000000..c3613fad6df9 --- /dev/null +++ b/java/java-tests/testData/compiler/notNullVerification/NonStaticInnerClass.java @@ -0,0 +1,12 @@ +import org.jetbrains.annotations.NotNull; + +public class NonStaticInnerClass { + public NonStaticInnerClass() { + new Inner(""); + } + + public class Inner { + public Inner(@NotNull String s) { + } + } +} diff --git a/java/java-tests/testData/compiler/notNullVerification/StaticInnerClass.java b/java/java-tests/testData/compiler/notNullVerification/StaticInnerClass.java new file mode 100644 index 000000000000..a08109042af9 --- /dev/null +++ b/java/java-tests/testData/compiler/notNullVerification/StaticInnerClass.java @@ -0,0 +1,12 @@ +import org.jetbrains.annotations.NotNull; + +public class StaticInnerClass { + public StaticInnerClass() { + new Inner(""); + } + + public static class Inner { + public Inner(@NotNull String s) { + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java b/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java index e8d6dd9d56cf..b512920c983e 100644 --- a/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java +++ b/java/java-tests/testSrc/com/intellij/compiler/notNullVerification/NotNullVerifyingInstrumenterTest.java @@ -69,6 +69,16 @@ public class NotNullVerifyingInstrumenterTest extends UsefulTestCase { assertNotNull(field); } + public void testStaticInnerClass() throws Exception { + final Class aClass = prepareTest(); + assertNotNull(aClass.newInstance()); + } + + public void testNonStaticInnerClass() throws Exception { + final Class aClass = prepareTest(); + assertNotNull(aClass.newInstance()); + } + private static void verifyCallThrowsException(final String expectedError, final Object instance, final Method method, final Object... args) throws IllegalAccessException { String exceptionText = null; try { @@ -85,27 +95,48 @@ public class NotNullVerifyingInstrumenterTest extends UsefulTestCase { private Class prepareTest() throws IOException { String base = JavaTestUtil.getJavaTestDataPath() + "/compiler/notNullVerification/"; - String path = base + getTestName(false); + final String baseClassName = getTestName(false); + String path = base + baseClassName; String javaPath = path + ".java"; - String classPath = path + ".class"; + File classesDir = FileUtil.createTempDirectory(baseClassName, "output"); + try { - com.sun.tools.javac.Main.compile(new String[] { "-classpath", base+"annotations.jar", javaPath } ); - FileInputStream stream = new FileInputStream(classPath); - byte[] content = FileUtil.adaptiveLoadBytes(stream); - stream.close(); - - ClassReader reader = new ClassReader(content, 0, content.length); - ClassWriter writer = new PsiClassWriter(myFixture.getProject(), false); - final NotNullVerifyingInstrumenter instrumenter = new NotNullVerifyingInstrumenter(writer); - reader.accept(instrumenter, 0); - assertTrue(instrumenter.isModification()); + com.sun.tools.javac.Main.compile(new String[] { "-classpath", base+"annotations.jar", "-d", classesDir.getAbsolutePath(), javaPath } ); + Class mainClass = null; + final File[] files = classesDir.listFiles(); + boolean modified = false; MyClassLoader classLoader = new MyClassLoader(getClass().getClassLoader()); - byte[] instrumented = writer.toByteArray(); - return classLoader.doDefineClass(getTestName(false), instrumented); + for (File file : files) { + final String fileName = file.getName(); + FileInputStream stream = new FileInputStream(file); + byte[] content; + try { + content = FileUtil.adaptiveLoadBytes(stream); + } + finally { + stream.close(); + } + + ClassReader reader = new ClassReader(content, 0, content.length); + ClassWriter writer = new PsiClassWriter(myFixture.getProject(), false); + final NotNullVerifyingInstrumenter instrumenter = new NotNullVerifyingInstrumenter(writer); + reader.accept(instrumenter, 0); + modified |= instrumenter.isModification(); + + byte[] instrumented = writer.toByteArray(); + final String className = FileUtil.getNameWithoutExtension(fileName); + final Class aClass = classLoader.doDefineClass(className, instrumented); + if (className.equals(baseClassName)) { + mainClass = aClass; + } + } + assertTrue(modified); + assertNotNull("Class " + baseClassName + " not found!", mainClass); + return mainClass; } finally { - FileUtil.delete(new File(classPath)); + FileUtil.delete(classesDir); } } @@ -114,6 +145,7 @@ public class NotNullVerifyingInstrumenterTest extends UsefulTestCase { super(parent); } + public Class doDefineClass(String name, byte[] data) { return defineClass(name, data, 0, data.length); } From d103458aefc45e3850b6323188840517ac20da34 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 5 Aug 2010 14:04:08 +0400 Subject: [PATCH 18/18] exception --- java/java-impl/src/com/intellij/slicer/SlicePanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/slicer/SlicePanel.java b/java/java-impl/src/com/intellij/slicer/SlicePanel.java index fea2f4fbcb25..ebbcc76b799f 100644 --- a/java/java-impl/src/com/intellij/slicer/SlicePanel.java +++ b/java/java-impl/src/com/intellij/slicer/SlicePanel.java @@ -90,7 +90,7 @@ public abstract class SlicePanel extends JPanel implements TypeSafeDataProvider, } public void stateChanged() { - if (project.isDisposed()) return; + if (!project.isOpen()) return; if (toolWindow.getAnchor() != myAnchor) { myAnchor = myToolWindow.getAnchor(); layoutPanel();