From 4c7e3a9fb01bf2a29b2824d8eb43fcbb2dd14d77 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 7 Feb 2012 17:44:12 +0100 Subject: [PATCH 01/18] minor --- ...erenceExpressionCompletionContributor.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java index 277188306be0..8e5749cc746e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java @@ -419,13 +419,24 @@ public class ReferenceExpressionCompletionContributor { final Consumer result, PsiType qualifierType, final PsiType expectedType, JavaSmartCompletionParameters parameters) throws IncorrectOperationException { + final PsiReferenceExpression mockRef = createMockReference(place, qualifierType); + + final ElementFilter filter = getReferenceFilter(place, true); + for (final LookupElement item : completeFinalReference(place, mockRef, filter, parameters)) { + if (shoudChain(place, qualifierType, expectedType, item)) { + result.consume(new JavaChainLookupElement(qualifierItem, item)); + } + } + } + + private static PsiReferenceExpression createMockReference(PsiElement place, PsiType qualifierType) { final JavaCodeFragmentFactory factory = JavaCodeFragmentFactory.getInstance(place.getProject()); PsiType varType = qualifierType; if (varType instanceof PsiEllipsisType) { varType = ((PsiEllipsisType)varType).getComponentType(); } if (varType instanceof PsiWildcardType || varType instanceof PsiCapturedWildcardType) { - varType = TypeConversionUtil.erasure(expectedType); + varType = TypeConversionUtil.erasure(varType); } final String typeText = varType.getCanonicalText(); @@ -435,14 +446,7 @@ public class ReferenceExpressionCompletionContributor { LOG.error(typeText + " of " + varType.getClass()); } final PsiExpressionStatement expressionStatement = (PsiExpressionStatement)secondChild; - final PsiReferenceExpression mockRef = (PsiReferenceExpression) expressionStatement.getExpression(); - - final ElementFilter filter = getReferenceFilter(place, true); - for (final LookupElement item : completeFinalReference(place, mockRef, filter, parameters)) { - if (shoudChain(place, varType, expectedType, item)) { - result.consume(new JavaChainLookupElement(qualifierItem, item)); - } - } + return (PsiReferenceExpression) expressionStatement.getExpression(); } private static boolean shoudChain(PsiElement element, PsiType qualifierType, PsiType expectedType, LookupElement item) { From 979191114eafde2eab7b21ce732ec9f6e97fdfc1 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 7 Feb 2012 18:38:51 +0100 Subject: [PATCH 02/18] IDEA-58766 Recognize dot as completion prefix part for chained call suggestions --- .../JavaClassNameCompletionContributor.java | 7 +- .../completion/JavaCompletionContributor.java | 4 +- .../completion/JavaNoVariantsDelegator.java | 98 +++++++++++++++---- .../JavaSmartCompletionContributor.java | 29 ++++-- ...erenceExpressionCompletionContributor.java | 14 ++- .../completion/JavaAutoPopupTest.groovy | 12 +++ .../completion/CompletionParameters.java | 4 + 7 files changed, 131 insertions(+), 37 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java index 18ef89056b04..9015b4cb13c6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java @@ -57,7 +57,8 @@ public class JavaClassNameCompletionContributor extends CompletionContributor { } CompletionResultSet result = _result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters)); - addAllClasses(parameters, JavaCompletionSorting.addJavaSorting(parameters, result), parameters.getInvocationCount() <= 1, new Consumer() { + addAllClasses(parameters, parameters.getInvocationCount() <= 1, + JavaCompletionSorting.addJavaSorting(parameters, result).getPrefixMatcher(), new Consumer() { @Override public void consume(LookupElement element) { _result.addElement(element); @@ -68,8 +69,8 @@ public class JavaClassNameCompletionContributor extends CompletionContributor { } public static void addAllClasses(CompletionParameters parameters, - final CompletionResultSet result, final boolean filterByScope, + @NotNull final PrefixMatcher matcher, @NotNull final Consumer consumer) { final PsiElement insertedElement = parameters.getPosition(); @@ -110,7 +111,7 @@ public class JavaClassNameCompletionContributor extends CompletionContributor { } final boolean lookingForAnnotations = PsiJavaPatterns.psiElement().afterLeaf("@").accepts(insertedElement); - AllClassesGetter.processJavaClasses(parameters, result.getPrefixMatcher(), filterByScope, new Consumer() { + AllClassesGetter.processJavaClasses(parameters, matcher, filterByScope, new Consumer() { @Override public void consume(PsiClass psiClass) { if (lookingForAnnotations && !psiClass.isAnnotationType()) return; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index 30f5c20fbef8..499040da4f31 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -106,7 +106,7 @@ public class JavaCompletionContributor extends CompletionContributor { withParent(or(psiElement(PsiResourceVariable.class), psiElement(PsiResourceList.class))))); @Nullable - private static ElementFilter getReferenceFilter(PsiElement position) { + public static ElementFilter getReferenceFilter(PsiElement position) { // Completion after extends in interface, type parameter and implements in class final PsiClass containingClass = PsiTreeUtil.getParentOfType(position, PsiClass.class, false, PsiCodeBlock.class, PsiMethod.class, PsiExpressionList.class, PsiVariable.class); if (containingClass != null && psiElement().afterLeaf(PsiKeyword.EXTENDS, PsiKeyword.IMPLEMENTS, ",", "&").accepts(position)) { @@ -239,7 +239,7 @@ public class JavaCompletionContributor extends CompletionContributor { if (!isClassNamePossible(parameters.getPosition()) || !mayStartClassName(result, parameters.isRelaxedMatching())) return; if (mayShowAllClasses(parameters)) { - JavaClassNameCompletionContributor.addAllClasses(parameters, result, parameters.getInvocationCount() <= 2, new Consumer() { + JavaClassNameCompletionContributor.addAllClasses(parameters, parameters.getInvocationCount() <= 2, result.getPrefixMatcher(), new Consumer() { @Override public void consume(LookupElement element) { if (!inheritors.alreadyProcessed(element)) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java index 9dcfb4a9f016..bdba7750740f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java @@ -15,10 +15,21 @@ */ package com.intellij.codeInsight.completion; +import com.intellij.codeInsight.completion.impl.CamelHumpMatcher; import com.intellij.codeInsight.lookup.AutoCompletionPolicy; import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiJavaCodeReferenceElement; +import com.intellij.psi.PsiReferenceExpression; +import com.intellij.psi.PsiType; +import com.intellij.psi.filters.ElementFilter; +import com.intellij.util.CollectConsumer; import com.intellij.util.Consumer; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + /** * @author peter */ @@ -26,29 +37,80 @@ public class JavaNoVariantsDelegator extends NoVariantsDelegator { @Override protected void delegate(CompletionParameters parameters, CompletionResultSet result, Consumer passResult) { - if (parameters.getCompletionType() == CompletionType.BASIC && - parameters.getInvocationCount() <= 1 && - JavaCompletionContributor.mayStartClassName(result, false) && - JavaCompletionContributor.isClassNamePossible(parameters.getPosition())) { - final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result); + if (parameters.getCompletionType() == CompletionType.BASIC) { + PsiElement position = parameters.getPosition(); + if (parameters.getInvocationCount() <= 1 && + JavaCompletionContributor.mayStartClassName(result, false) && + JavaCompletionContributor.isClassNamePossible(position)) { + suggestNonImportedClasses(parameters, result); + return; + } - JavaClassNameCompletionContributor.addAllClasses(parameters, JavaCompletionSorting.addJavaSorting(parameters, result), - true, new Consumer() { - @Override - public void consume(LookupElement element) { - JavaPsiClassReferenceElement classElement = element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY); - if (classElement != null) { - classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); + PsiElement parent = position.getParent(); + if (parent instanceof PsiJavaCodeReferenceElement) { + PsiElement qualifier = ((PsiJavaCodeReferenceElement)parent).getQualifier(); + if (qualifier instanceof PsiJavaCodeReferenceElement && + !((PsiJavaCodeReferenceElement)qualifier).isQualified() && + ((PsiJavaCodeReferenceElement)qualifier).resolve() == null) { + CompletionResultSet qualifiedCollector = result.withPrefixMatcher(position.getContainingFile().getText().substring(parent.getTextRange().getStartOffset(), parameters.getOffset())); + ElementFilter filter = JavaCompletionContributor.getReferenceFilter(position); + for (LookupElement base : suggestQualifierItems(parameters, result, (PsiJavaCodeReferenceElement)qualifier, filter)) { + PsiType type = JavaCompletionUtil.getLookupElementType(base); + if (type != null) { + PsiReferenceExpression ref = ReferenceExpressionCompletionContributor.createMockReference(position, type, base); + for (final LookupElement item : JavaSmartCompletionContributor.completeReference(position, ref, filter, true, true, parameters, + result.getPrefixMatcher())) { + qualifiedCollector.addElement(new JavaChainLookupElement(base, item)); + } + } } - - merger.consume(classElement); } - }); + } + } - merger.finishedClassProcessing(); - - } else if (parameters.getCompletionType() == CompletionType.SMART && parameters.getInvocationCount() == 2) { + if (parameters.getCompletionType() == CompletionType.SMART && parameters.getInvocationCount() == 2) { result.runRemainingContributors(parameters.withInvocationCount(3), passResult); } } + + private static Set suggestQualifierItems(CompletionParameters parameters, + CompletionResultSet result, + PsiJavaCodeReferenceElement qualifier, + ElementFilter filter) { + String referenceName = qualifier.getReferenceName(); + if (referenceName == null) { + return Collections.emptySet(); + } + + PrefixMatcher qMatcher = new CamelHumpMatcher(referenceName); + Set plainVariants = + JavaSmartCompletionContributor.completeReference(qualifier, qualifier, filter, true, true, parameters, qMatcher); + if (!plainVariants.isEmpty()) { + return plainVariants; + } + + final Set allClasses = new LinkedHashSet(); + JavaClassNameCompletionContributor.addAllClasses(parameters.withPosition(qualifier.getReferenceNameElement(), qualifier.getTextRange().getEndOffset()), + true, qMatcher, new CollectConsumer(allClasses)); + return allClasses; + } + + private static void suggestNonImportedClasses(CompletionParameters parameters, CompletionResultSet result) { + final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result); + + JavaClassNameCompletionContributor.addAllClasses(parameters, + true, JavaCompletionSorting.addJavaSorting(parameters, result).getPrefixMatcher(), new Consumer() { + @Override + public void consume(LookupElement element) { + JavaPsiClassReferenceElement classElement = element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY); + if (classElement != null) { + classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); + } + + merger.consume(classElement); + } + }); + + merger.finishedClassProcessing(); + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java index 649a4ed6e7ff..e4825f5781f2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java @@ -155,14 +155,15 @@ public class JavaSmartCompletionContributor extends CompletionContributor { final ElementFilter filter = getReferenceFilter(element); if (filter != null) { final List infos = Arrays.asList(getExpectedTypes(parameters)); - for (final LookupElement item : completeReference(element, reference, filter, true, parameters)) { + for (final LookupElement item : completeReference(element, reference, filter, true, false, parameters, result.getPrefixMatcher())) { if (item.getObject() instanceof PsiClass) { result.addElement(decorate(LookupElementDecorator.withInsertHandler((LookupItem)item, ConstructorInsertHandler.SMART_INSTANCE), infos)); } } } else if (INSIDE_TYPECAST_EXPRESSION.accepts(element)) { - for (final LookupElement item : completeReference(element, reference, new GeneratorFilter(AssignableToFilter.class, new CastTypeGetter()), false, parameters)) { + for (final LookupElement item : completeReference(element, reference, new GeneratorFilter(AssignableToFilter.class, new CastTypeGetter()), false, true, parameters, + result.getPrefixMatcher())) { result.addElement(item); } } @@ -182,7 +183,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor { final PsiElement element = parameters.getPosition(); final PsiReference reference = element.getContainingFile().findReferenceAt(parameters.getOffset()); assert reference != null; - for (final LookupElement item : completeReference(element, reference, THROWABLES_FILTER, true, parameters)) { + for (final LookupElement item : completeReference(element, reference, THROWABLES_FILTER, true, false, parameters, result.getPrefixMatcher())) { result.addElement(item); } } @@ -456,7 +457,12 @@ public class JavaSmartCompletionContributor extends CompletionContributor { return ExpectedTypesProvider.getExpectedTypes(expression, true, parameters.getCompletionType() == CompletionType.SMART, false); } - static Set completeReference(final PsiElement element, PsiReference reference, final ElementFilter filter, final boolean acceptClasses, CompletionParameters parameters) { + static Set completeReference(final PsiElement element, + PsiReference reference, + final ElementFilter filter, + final boolean acceptClasses, + final boolean acceptMembers, + CompletionParameters parameters, @Nullable final PrefixMatcher matcher) { if (reference instanceof PsiMultiReference) { reference = ContainerUtil.findInstance(((PsiMultiReference) reference).getReferences(), PsiJavaReference.class); } @@ -470,15 +476,18 @@ public class JavaSmartCompletionContributor extends CompletionContributor { } public boolean isClassAcceptable(Class hintClass) { - if (acceptClasses) { - return ReflectionCache.isAssignable(PsiClass.class, hintClass); + if (ReflectionCache.isAssignable(PsiClass.class, hintClass)) { + return acceptClasses; } - return ReflectionCache.isAssignable(PsiVariable.class, hintClass) || - ReflectionCache.isAssignable(PsiMethod.class, hintClass) || - ReflectionCache.isAssignable(CandidateInfo.class, hintClass); + if (ReflectionCache.isAssignable(PsiVariable.class, hintClass) || + ReflectionCache.isAssignable(PsiMethod.class, hintClass) || + ReflectionCache.isAssignable(CandidateInfo.class, hintClass)) { + return acceptMembers; + } + return false; } - }, true, parameters.getInvocationCount() <= 1, null, parameters); + }, true, parameters.getInvocationCount() <= 1, matcher, parameters); } return Collections.emptySet(); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java index 8e5749cc746e..e9559a88292f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java @@ -122,7 +122,7 @@ public class ReferenceExpressionCompletionContributor { final boolean secondTime = parameters.getParameters().getInvocationCount() >= 2; final Set base = - JavaSmartCompletionContributor.completeReference(element, reference, filter, false, parameters.getParameters()); + JavaSmartCompletionContributor.completeReference(element, reference, filter, false, true, parameters.getParameters(), null); for (final LookupElement item : base) { addSingleArrayElementAccess(element, item, parameters, result); } @@ -177,7 +177,7 @@ public class ReferenceExpressionCompletionContributor { public boolean isClassAcceptable(Class hintClass) { return true; } - }), false, parameters.getParameters()); + }), false, true, parameters.getParameters(), null); for (LookupElement lookupElement : elements) { if (lookupElement.getObject() instanceof PsiMethod) { final JavaMethodCallElement item = lookupElement.as(JavaMethodCallElement.CLASS_CONDITION_KEY); @@ -419,7 +419,7 @@ public class ReferenceExpressionCompletionContributor { final Consumer result, PsiType qualifierType, final PsiType expectedType, JavaSmartCompletionParameters parameters) throws IncorrectOperationException { - final PsiReferenceExpression mockRef = createMockReference(place, qualifierType); + final PsiReferenceExpression mockRef = createMockReference(place, qualifierType, qualifierItem); final ElementFilter filter = getReferenceFilter(place, true); for (final LookupElement item : completeFinalReference(place, mockRef, filter, parameters)) { @@ -429,7 +429,13 @@ public class ReferenceExpressionCompletionContributor { } } - private static PsiReferenceExpression createMockReference(PsiElement place, PsiType qualifierType) { + public static PsiReferenceExpression createMockReference(PsiElement place, @NotNull PsiType qualifierType, LookupElement qualifierItem) { + if (qualifierItem.getObject() instanceof PsiClass) { + return (PsiReferenceExpression)JavaPsiFacade.getElementFactory(place.getProject()) + .createExpressionFromText(((PsiClass)qualifierItem.getObject()).getQualifiedName() + ".xxx", place); + + } + final JavaCodeFragmentFactory factory = JavaCodeFragmentFactory.getInstance(place.getProject()); PsiType varType = qualifierType; if (varType instanceof PsiEllipsisType) { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy index 6d46ad532c64..47542b0b1266 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -1221,4 +1221,16 @@ class Foo {{ myFixture.checkResult 'class Foo { int foo() { re() }}' } + public void testAmbiguousClassQualifier() { + myFixture.addClass("package foo; public class Util { public static void foo() {} }") + myFixture.addClass("package bar; public class Util { public static void bar() {} }") + myFixture.configureByText 'a.java', 'class Foo {{ }}' + type 'Util.' + assert myFixture.lookupElementStrings == ['Util.bar', 'Util.foo'] + type 'fo\n' + myFixture.checkResult '''import foo.Util; + +class Foo {{ Util.foo(); }}''' + } + } diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java index b7ac712d6767..56eb0c10af62 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java @@ -100,4 +100,8 @@ public class CompletionParameters { public boolean isRelaxedMatching() { return myRelaxedMatching; } + + public CompletionParameters withPosition(PsiElement element, int offset) { + return new CompletionParameters(element, myOriginalFile, myCompletionType, offset, myInvocationCount, myLookup, myRelaxedMatching); + } } From 3ac3fb5e95eef3f6fcc1f3e3e830f91d32ab60b6 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 7 Feb 2012 19:11:09 +0100 Subject: [PATCH 03/18] don't filter out DefaultGroovyMethods, move them to the bottom instead --- .../GroovyCompletionContributor.java | 82 +++++++------------ .../GrCompletionWithLibraryTest.groovy | 62 +++++++++++++- .../completion/GroovyCompletionTest.groovy | 12 +-- .../dsl/GroovyTransformationsTest.groovy | 2 +- 4 files changed, 92 insertions(+), 66 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java index 0b133fffb90b..45ecbc716a4f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java @@ -45,7 +45,6 @@ import com.intellij.util.PairConsumer; import com.intellij.util.ProcessingContext; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.GroovyBundle; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; @@ -417,15 +416,6 @@ public class GroovyCompletionContributor extends CompletionContributor { GroovySmartCompletionContributor.generateInheritorVariants(parameters, result.getPrefixMatcher(), inheritorsHolder); } - final int invocationCount = parameters.getInvocationCount(); - final boolean firstCompletionInvoked = invocationCount < 2; - - final String prefix = result.getPrefixMatcher().getPrefix(); - final boolean skipAccessors = firstCompletionInvoked && !prefix.startsWith("g") && !prefix.startsWith("s") && !prefix.startsWith("i"); - result.restartCompletionOnPrefixChange("g"); - result.restartCompletionOnPrefixChange("i"); - result.restartCompletionOnPrefixChange("s"); - final Map staticMembers = hashMap(); final PsiElement qualifier = reference.getQualifier(); final PsiType qualifierType = qualifier instanceof GrExpression ? ((GrExpression)qualifier).getType() : null; @@ -445,7 +435,7 @@ public class GroovyCompletionContributor extends CompletionContributor { element = ((LookupElement)element).getObject(); } - final LookupElement lookupElement = element instanceof PsiClass + LookupElement lookupElement = element instanceof PsiClass ? GroovyCompletionUtil.createClassLookupItem(CompletionUtil.getOriginalOrSelf((PsiClass)element)) : GroovyCompletionUtil.getLookupElement(element); Object object = lookupElement.getObject(); @@ -460,45 +450,8 @@ public class GroovyCompletionContributor extends CompletionContributor { if (object instanceof PsiMember && JavaCompletionUtil.isInExcludedPackage((PsiMember)object, true)) { return; } + lookupElement = tweakPriority(lookupElement, object, substitutor, resolveResult, qualifierType); - final boolean autopopup = parameters.getInvocationCount() == 0; - //skip default groovy methods - if (firstCompletionInvoked && - object instanceof GrGdkMethod && - GroovyCompletionUtil.skipDefGroovyMethod((GrGdkMethod)object, substitutor, qualifierType)) { - if (!autopopup) { - showInfo(); - } - return; - } - - //skip operator methods - if (firstCompletionInvoked && - object instanceof PsiMethod && - GroovyCompletionUtil.OPERATOR_METHOD_NAMES.contains(((PsiMethod)object).getName())) { - if (!checkForIterator((PsiMethod)object)) { - if (!autopopup) { - showInfo(); - } - return; - } - } - - //skip accessors if there is no get, set, is prefix - if (skipAccessors && object instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)object)) { - if (!autopopup) { - showInfo(); - } - return; - } - - //skip inaccessible elements - if (firstCompletionInvoked && resolveResult != null && !resolveResult.isAccessible()) { - if (!autopopup) { - showInfo(); - } - return; - } if ((object instanceof PsiMethod || object instanceof PsiField) && ((PsiModifierListOwner)object).hasModifierProperty(PsiModifier.STATIC)) { @@ -545,11 +498,34 @@ public class GroovyCompletionContributor extends CompletionContributor { return InheritanceUtil.isInheritorOrSelf(containingClass, iterator, true); } - private static void showInfo() { - if (StringUtil.isEmpty(CompletionService.getCompletionService().getAdvertisementText())) { - CompletionService.getCompletionService() - .setAdvertisementText(GroovyBundle.message("invoke.completion.second.time.to.show.skipped.methods")); + + private static LookupElement tweakPriority(LookupElement lookupElement, + Object object, + PsiSubstitutor substitutor, + GroovyResolveResult resolveResult, + PsiType qualifierType) { + // default groovy methods + if (object instanceof GrGdkMethod && + GroovyCompletionUtil.skipDefGroovyMethod((GrGdkMethod)object, substitutor, qualifierType)) { + return PrioritizedLookupElement.withPriority(lookupElement, -1); } + + // operator methods + if (object instanceof PsiMethod && + GroovyCompletionUtil.OPERATOR_METHOD_NAMES.contains(((PsiMethod)object).getName()) && !checkForIterator((PsiMethod)object)) { + return PrioritizedLookupElement.withPriority(lookupElement, -3); + } + + // accessors if there is no get, set, is prefix + if (object instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)object)) { + return PrioritizedLookupElement.withPriority(lookupElement, -1); + } + + // inaccessible elements + if (resolveResult != null && !resolveResult.isAccessible()) { + return PrioritizedLookupElement.withPriority(lookupElement, -2); + } + return lookupElement; } static StaticMemberProcessor completeStaticMembers(CompletionParameters parameters) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GrCompletionWithLibraryTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GrCompletionWithLibraryTest.groovy index fbdb4e312da7..1c6f897345d6 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GrCompletionWithLibraryTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GrCompletionWithLibraryTest.groovy @@ -170,7 +170,67 @@ toString wait wait wait -with\ +with +getThisProp +setThisProp +getSuperProp +setSuperProp +addShutdownHook +any +any +asBoolean +asType +collect +collect +dump +each +eachWithIndex +every +every +find +findAll +findIndexOf +findIndexOf +findIndexValues +findIndexValues +findLastIndexOf +findLastIndexOf +getAt +getClass +getMetaClass +getMetaPropertyValues +getProperties +grep +hasPerInstanceMetaClass +hasProperty +identity +inject +inspect +is +isCase +iterator +metaClass +primitiveArrayGet +primitiveArrayGet +primitiveArrayGet +primitiveArrayPut +print +print +printf +printf +println +println +println +putAt +respondsTo +respondsTo +setMetaClass +split +sprintf +sprintf +use +use +use\ """.split('\n') } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index 94794bebd83b..c8ac6a4b037c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -891,16 +891,6 @@ class B extends A { checkCompletion "assex", ' ', 'assert x' } - public void testDontShowAccessors() { - assertNull doContainsTest("getFoo", """ -class MyClass { - def foo -} - -def a = new MyClass() -a.""") - } - public void testPreferInstanceof() { caseSensitiveNone() @@ -1072,7 +1062,7 @@ class X { } public void testSortOrder0() { - doVariantableTest 'se', 'setMetaClass', 'setProperty', 'setSe' + doVariantableTest 'se', 'setProperty', 'setMetaClass', 'setSe' } public void testPrimitiveCastOverwrite() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyTransformationsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyTransformationsTest.groovy index a46a38e51faa..0228220fa5ea 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyTransformationsTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyTransformationsTest.groovy @@ -50,7 +50,7 @@ class GroovyTransformationsTest extends LightCodeInsightFixtureTestCase { public void testVetoableTransform() throws Throwable { doPlainTest() } - public void testNewifyTransform1() throws Throwable { doVariantsTest('newInstance', 'new', 'new', 'newInstance') } + public void testNewifyTransform1() throws Throwable { doVariantsTest('newInstance', 'new', 'new', 'newInstance', 'negative', 'next') } public void testNewifyTransform2() throws Throwable { doVariantsTest('Leaf', 'Leaf', 'Leaf') } From 55ebfba51f6a1e31701b6d6b6e3bef1fce683e9b Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 7 Feb 2012 19:18:23 +0100 Subject: [PATCH 04/18] minor --- .../completion/JavaNoVariantsDelegator.java | 49 +++++++++++-------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java index bdba7750740f..a70318059c7c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java @@ -46,26 +46,7 @@ public class JavaNoVariantsDelegator extends NoVariantsDelegator { return; } - PsiElement parent = position.getParent(); - if (parent instanceof PsiJavaCodeReferenceElement) { - PsiElement qualifier = ((PsiJavaCodeReferenceElement)parent).getQualifier(); - if (qualifier instanceof PsiJavaCodeReferenceElement && - !((PsiJavaCodeReferenceElement)qualifier).isQualified() && - ((PsiJavaCodeReferenceElement)qualifier).resolve() == null) { - CompletionResultSet qualifiedCollector = result.withPrefixMatcher(position.getContainingFile().getText().substring(parent.getTextRange().getStartOffset(), parameters.getOffset())); - ElementFilter filter = JavaCompletionContributor.getReferenceFilter(position); - for (LookupElement base : suggestQualifierItems(parameters, result, (PsiJavaCodeReferenceElement)qualifier, filter)) { - PsiType type = JavaCompletionUtil.getLookupElementType(base); - if (type != null) { - PsiReferenceExpression ref = ReferenceExpressionCompletionContributor.createMockReference(position, type, base); - for (final LookupElement item : JavaSmartCompletionContributor.completeReference(position, ref, filter, true, true, parameters, - result.getPrefixMatcher())) { - qualifiedCollector.addElement(new JavaChainLookupElement(base, item)); - } - } - } - } - } + suggestChainedCalls(parameters, result, position); } if (parameters.getCompletionType() == CompletionType.SMART && parameters.getInvocationCount() == 2) { @@ -73,8 +54,34 @@ public class JavaNoVariantsDelegator extends NoVariantsDelegator { } } + private static void suggestChainedCalls(CompletionParameters parameters, CompletionResultSet result, PsiElement position) { + PsiElement parent = position.getParent(); + if (!(parent instanceof PsiJavaCodeReferenceElement)) { + return; + } + PsiElement qualifier = ((PsiJavaCodeReferenceElement)parent).getQualifier(); + if (!(qualifier instanceof PsiJavaCodeReferenceElement) || + ((PsiJavaCodeReferenceElement)qualifier).isQualified() || + ((PsiJavaCodeReferenceElement)qualifier).resolve() != null) { + return; + } + + String fullPrefix = position.getContainingFile().getText().substring(parent.getTextRange().getStartOffset(), parameters.getOffset()); + CompletionResultSet qualifiedCollector = result.withPrefixMatcher(fullPrefix); + ElementFilter filter = JavaCompletionContributor.getReferenceFilter(position); + for (LookupElement base : suggestQualifierItems(parameters, (PsiJavaCodeReferenceElement)qualifier, filter)) { + PsiType type = JavaCompletionUtil.getLookupElementType(base); + if (type != null && !PsiType.VOID.equals(type)) { + PsiReferenceExpression ref = ReferenceExpressionCompletionContributor.createMockReference(position, type, base); + for (final LookupElement item : JavaSmartCompletionContributor.completeReference(position, ref, filter, true, true, parameters, + result.getPrefixMatcher())) { + qualifiedCollector.addElement(new JavaChainLookupElement(base, item)); + } + } + } + } + private static Set suggestQualifierItems(CompletionParameters parameters, - CompletionResultSet result, PsiJavaCodeReferenceElement qualifier, ElementFilter filter) { String referenceName = qualifier.getReferenceName(); From 19593a00497f01cf77edd431267d9861b9256725 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 7 Feb 2012 19:46:43 +0100 Subject: [PATCH 05/18] minor refactoring --- .../GroovyCompletionContributor.java | 56 ++++++++++++------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java index 45ecbc716a4f..ddf92e0f0aeb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java @@ -45,6 +45,7 @@ import com.intellij.util.PairConsumer; import com.intellij.util.ProcessingContext; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; @@ -309,21 +310,26 @@ public class GroovyCompletionContributor extends CompletionContributor { addUnfinishedMethodTypeParameters(position, result); - final PsiElement parent = position.getParent(); - GrReferenceElement reference; - if (parent instanceof GrReferenceElement) { - reference = (GrReferenceElement)parent; - if (reference.getParent() instanceof GrImportStatement && reference.getQualifier() != null) { - result.addElement(LookupElementBuilder.create("*")); - } - } else if (couldContainReference(position)) { - reference = GroovyPsiElementFactory.getInstance(position.getProject()).createReferenceElementFromText("Foo", position); - } else { + GrReferenceElement reference = findGroovyReference(position); + if (reference == null) { return; } + if (reference.getParent() instanceof GrImportStatement && reference.getQualifier() != null) { + result.addElement(LookupElementBuilder.create("*")); + } + InheritorsHolder inheritors = new InheritorsHolder(position, result); - completeReference(parameters, result, reference, inheritors); + if (GroovySmartCompletionContributor.AFTER_NEW.accepts(position)) { + GroovySmartCompletionContributor.generateInheritorVariants(parameters, result.getPrefixMatcher(), inheritors); + } + + completeReference(parameters, reference, inheritors, result.getPrefixMatcher(), new Consumer() { + @Override + public void consume(LookupElement element) { + result.addElement(element); + } + }); if (reference.getQualifier() == null) { GroovySmartCompletionContributor.addExpectedClassMembers(parameters, result); @@ -360,6 +366,17 @@ public class GroovyCompletionContributor extends CompletionContributor { } + @Nullable private static GrReferenceElement findGroovyReference(PsiElement position) { + final PsiElement parent = position.getParent(); + if (parent instanceof GrReferenceElement) { + return (GrReferenceElement)parent; + } + if (couldContainReference(position)) { + return GroovyPsiElementFactory.getInstance(position.getProject()).createReferenceElementFromText("Foo", position); + } + return null; + } + private static boolean couldContainReference(PsiElement position) { return IN_CATCH_TYPE.accepts(position) || AFTER_AT.accepts(position) || @@ -408,21 +425,16 @@ public class GroovyCompletionContributor extends CompletionContributor { } private static void completeReference(final CompletionParameters parameters, - final CompletionResultSet result, - GrReferenceElement reference, final InheritorsHolder inheritorsHolder) { + GrReferenceElement reference, final InheritorsHolder inheritorsHolder, final PrefixMatcher matcher, final Consumer result) { final PsiElement position = parameters.getPosition(); - if (GroovySmartCompletionContributor.AFTER_NEW.accepts(position)) { - GroovySmartCompletionContributor.generateInheritorVariants(parameters, result.getPrefixMatcher(), inheritorsHolder); - } - final Map staticMembers = hashMap(); final PsiElement qualifier = reference.getQualifier(); final PsiType qualifierType = qualifier instanceof GrExpression ? ((GrExpression)qualifier).getType() : null; final ElementFilter classFilter = getClassFilter(position); - reference.processVariants(result.getPrefixMatcher(), parameters, new Consumer() { + reference.processVariants(matcher, parameters, new Consumer() { public void consume(Object element) { if (element instanceof PsiClass && inheritorsHolder.alreadyProcessed((PsiClass)element)) { return; @@ -463,7 +475,7 @@ public class GroovyCompletionContributor extends CompletionContributor { if (object instanceof PsiClass && !classFilter.isAcceptable(object, position)) { return; } - result.addElement(JavaCompletionUtil.highlightIfNeeded(qualifierType, lookupElement, object)); + result.consume(JavaCompletionUtil.highlightIfNeeded(qualifierType, lookupElement, object)); } }); @@ -475,7 +487,7 @@ public class GroovyCompletionContributor extends CompletionContributor { member = ((GrAccessorMethod)member).getProperty(); } final String name = member.getName(); - if (name == null || !result.getPrefixMatcher().prefixMatches(name)) { + if (name == null || !matcher.prefixMatches(name)) { staticMembers.remove(member); return; } @@ -485,7 +497,9 @@ public class GroovyCompletionContributor extends CompletionContributor { }); } - result.addAllElements(staticMembers.values()); + for (LookupElement element : staticMembers.values()) { + result.consume(element); + } } private static boolean checkForIterator(PsiMethod method) { From 3ea29bdefbed11d30e848b51050beb5ab0c87d50 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 7 Feb 2012 20:16:45 +0100 Subject: [PATCH 06/18] not all types can be transformed to text and parsed back (EA-33366) --- ...erenceExpressionCompletionContributor.java | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java index e9559a88292f..24aa41aafa2e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java @@ -33,8 +33,11 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.filters.*; import com.intellij.psi.filters.element.ModifierFilter; import com.intellij.psi.filters.types.AssignableFromFilter; +import com.intellij.psi.impl.FakePsiElement; +import com.intellij.psi.impl.light.LightVariableBuilder; import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.psi.infos.CandidateInfo; +import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; @@ -429,30 +432,31 @@ public class ReferenceExpressionCompletionContributor { } } - public static PsiReferenceExpression createMockReference(PsiElement place, @NotNull PsiType qualifierType, LookupElement qualifierItem) { + public static PsiReferenceExpression createMockReference(final PsiElement place, @NotNull PsiType qualifierType, LookupElement qualifierItem) { + PsiElementFactory factory = JavaPsiFacade.getElementFactory(place.getProject()); if (qualifierItem.getObject() instanceof PsiClass) { - return (PsiReferenceExpression)JavaPsiFacade.getElementFactory(place.getProject()) + return (PsiReferenceExpression)factory .createExpressionFromText(((PsiClass)qualifierItem.getObject()).getQualifiedName() + ".xxx", place); - } - final JavaCodeFragmentFactory factory = JavaCodeFragmentFactory.getInstance(place.getProject()); - PsiType varType = qualifierType; - if (varType instanceof PsiEllipsisType) { - varType = ((PsiEllipsisType)varType).getComponentType(); - } - if (varType instanceof PsiWildcardType || varType instanceof PsiCapturedWildcardType) { - varType = TypeConversionUtil.erasure(varType); - } + return (PsiReferenceExpression) factory.createExpressionFromText("xxx.xxx", createContextWithXxxVariable(place, qualifierType)); + } - final String typeText = varType.getCanonicalText(); - final JavaCodeFragment block = factory.createCodeBlockCodeFragment(typeText + " xxx;xxx.xxx;", place, false); - final PsiElement secondChild = block.getChildren()[1]; - if (!(secondChild instanceof PsiExpressionStatement)) { - LOG.error(typeText + " of " + varType.getClass()); - } - final PsiExpressionStatement expressionStatement = (PsiExpressionStatement)secondChild; - return (PsiReferenceExpression) expressionStatement.getExpression(); + public static FakePsiElement createContextWithXxxVariable(final PsiElement place, final PsiType varType) { + return new FakePsiElement() { + @Override + public boolean processDeclarations(@NotNull PsiScopeProcessor processor, + @NotNull ResolveState state, + PsiElement lastParent, + @NotNull PsiElement place) { + return processor.execute(new LightVariableBuilder("xxx", varType, place), ResolveState.initial()); + } + + @Override + public PsiElement getParent() { + return place; + } + }; } private static boolean shoudChain(PsiElement element, PsiType qualifierType, PsiType expectedType, LookupElement item) { From 846ca5cf0afeab5fd2cedb31e66537007e9b33ab Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 8 Feb 2012 12:58:25 +0100 Subject: [PATCH 07/18] non-first java completion contributors --- .../platform-resources/src/META-INF/LangExtensions.xml | 4 +--- resources/src/META-INF/IdeaPlugin.xml | 8 ++++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 2d36ef88f549..0b87b66a01b1 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -443,7 +443,6 @@ - @@ -653,7 +652,7 @@ - + @@ -698,7 +697,6 @@ serviceImplementation="com.intellij.openapi.vcs.impl.CodeSmellDetectorImpl"/> - diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 472fdda42908..bdef3c17b07e 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -213,10 +213,12 @@ + + order="before javaMemberName, before javaLegacy, after liveTemplates"/> + order="after xml"/> + + From 3bf3a8f187133b18ae96efa310f759a1d5ef657f Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 8 Feb 2012 13:59:20 +0100 Subject: [PATCH 08/18] IDEA-58766 Recognize dot as completion prefix part for chained call suggestions, groovy --- .../completion/JavaChainLookupElement.java | 8 +- .../completion/JavaCompletionUtil.java | 3 + .../GroovyCompletionContributor.java | 103 ++++++++----- .../completion/GroovyNoVariantsDelegator.java | 139 +++++++++++++++--- .../CompleteReferenceExpression.java | 21 +-- .../completion/GroovyAutoPopupTest.groovy | 4 +- .../completion/GroovyCompletionTest.groovy | 12 ++ .../reference/tupleObjCompl.test | 3 +- .../oldCompletion/reference/untyped.test | 3 +- 9 files changed, 220 insertions(+), 76 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java index df36e2769cbf..6a8595751701 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java @@ -65,7 +65,11 @@ public class JavaChainLookupElement extends LookupElementDecorator() { + addAllClasses(parameters, new Consumer() { @Override public void consume(LookupElement element) { result.addElement(element); } - }, inheritors); + }, inheritors, result.getPrefixMatcher()); } - public static void addAllClasses(CompletionParameters parameters, CompletionResultSet result, final Consumer consumer, final InheritorsHolder inheritors) { + public static void addAllClasses(CompletionParameters parameters, + final Consumer consumer, + final InheritorsHolder inheritors, final PrefixMatcher matcher) { final PsiElement position = parameters.getPosition(); final ElementFilter filter = getClassFilter(position); - AllClassesGetter.processJavaClasses(parameters, result.getPrefixMatcher(), parameters.getInvocationCount() <= 1, + AllClassesGetter.processJavaClasses(parameters, matcher, parameters.getInvocationCount() <= 1, new Consumer() { @Override public void consume(PsiClass psiClass) { @@ -324,12 +327,7 @@ public class GroovyCompletionContributor extends CompletionContributor { GroovySmartCompletionContributor.generateInheritorVariants(parameters, result.getPrefixMatcher(), inheritors); } - completeReference(parameters, reference, inheritors, result.getPrefixMatcher(), new Consumer() { - @Override - public void consume(LookupElement element) { - result.addElement(element); - } - }); + result.addAllElements(completeReference(parameters, reference, inheritors, result.getPrefixMatcher())); if (reference.getQualifier() == null) { GroovySmartCompletionContributor.addExpectedClassMembers(parameters, result); @@ -424,16 +422,30 @@ public class GroovyCompletionContributor extends CompletionContributor { super.fillCompletionVariants(parameters, result); } - private static void completeReference(final CompletionParameters parameters, - GrReferenceElement reference, final InheritorsHolder inheritorsHolder, final PrefixMatcher matcher, final Consumer result) { + static LinkedHashSet completeReference(final CompletionParameters parameters, + GrReferenceElement reference, final InheritorsHolder inheritorsHolder, final PrefixMatcher matcher) { final PsiElement position = parameters.getPosition(); final Map staticMembers = hashMap(); final PsiElement qualifier = reference.getQualifier(); final PsiType qualifierType = qualifier instanceof GrExpression ? ((GrExpression)qualifier).getType() : null; + LinkedHashSet result = new LinkedHashSet(); + if (reference instanceof GrReferenceExpression && (qualifier instanceof GrExpression || qualifier == null)) { + for (String string : CompleteReferenceExpression.getVariantsWithSameQualifier(matcher, (GrExpression)qualifier, (GrReferenceExpression)reference)) { + result.add(GroovyCompletionUtil.getLookupElement(string)); + } + if (parameters.getInvocationCount() < 2 && qualifier != null && qualifierType == null) { + if (parameters.getInvocationCount() == 1) { + showInfo(); + } + return result; + } + } + final ElementFilter classFilter = getClassFilter(position); + final List items = arrayList(); reference.processVariants(matcher, parameters, new Consumer() { public void consume(Object element) { if (element instanceof PsiClass && inheritorsHolder.alreadyProcessed((PsiClass)element)) { @@ -448,22 +460,20 @@ public class GroovyCompletionContributor extends CompletionContributor { } LookupElement lookupElement = element instanceof PsiClass - ? GroovyCompletionUtil.createClassLookupItem(CompletionUtil.getOriginalOrSelf((PsiClass)element)) - : GroovyCompletionUtil.getLookupElement(element); + ? GroovyCompletionUtil.createClassLookupItem(CompletionUtil.getOriginalOrSelf((PsiClass)element)) + : GroovyCompletionUtil.getLookupElement(element); Object object = lookupElement.getObject(); - PsiSubstitutor substitutor = null; - GroovyResolveResult resolveResult = null; if (object instanceof GroovyResolveResult) { - resolveResult = (GroovyResolveResult)object; - substitutor = resolveResult.getSubstitutor(); object = ((GroovyResolveResult)object).getElement(); } if (object instanceof PsiMember && JavaCompletionUtil.isInExcludedPackage((PsiMember)object, true)) { return; } - lookupElement = tweakPriority(lookupElement, object, substitutor, resolveResult, qualifierType); + int priority = assignPriority(lookupElement, qualifierType); + lookupElement = JavaCompletionUtil.highlightIfNeeded(qualifierType, + PrioritizedLookupElement.withPriority(lookupElement, priority), object); if ((object instanceof PsiMethod || object instanceof PsiField) && ((PsiModifierListOwner)object).hasModifierProperty(PsiModifier.STATIC)) { @@ -475,7 +485,8 @@ public class GroovyCompletionContributor extends CompletionContributor { if (object instanceof PsiClass && !classFilter.isAcceptable(object, position)) { return; } - result.consume(JavaCompletionUtil.highlightIfNeeded(qualifierType, lookupElement, object)); + + items.add(lookupElement); } }); @@ -497,8 +508,25 @@ public class GroovyCompletionContributor extends CompletionContributor { }); } - for (LookupElement element : staticMembers.values()) { - result.consume(element); + items.addAll(staticMembers.values()); + + for (Iterator iterator = items.iterator(); iterator.hasNext(); ) { + LookupElement element = iterator.next(); + PrioritizedLookupElement prio = element.as(PrioritizedLookupElement.CLASS_CONDITION_KEY); + if (prio == null || prio.getPriority() >= 0) { + result.add(element); + iterator.remove(); + } + } + result.addAll(items); + + return result; + } + + private static void showInfo() { + if (StringUtil.isEmpty(CompletionService.getCompletionService().getAdvertisementText())) { + CompletionService.getCompletionService() + .setAdvertisementText(GroovyBundle.message("invoke.completion.second.time.to.show.skipped.methods")); } } @@ -513,33 +541,38 @@ public class GroovyCompletionContributor extends CompletionContributor { } - private static LookupElement tweakPriority(LookupElement lookupElement, - Object object, - PsiSubstitutor substitutor, - GroovyResolveResult resolveResult, - PsiType qualifierType) { + private static int assignPriority(LookupElement lookupElement, PsiType qualifierType) { + Object object = lookupElement.getObject(); + PsiSubstitutor substitutor = null; + GroovyResolveResult resolveResult = null; + if (object instanceof GroovyResolveResult) { + resolveResult = (GroovyResolveResult)object; + substitutor = resolveResult.getSubstitutor(); + object = ((GroovyResolveResult)object).getElement(); + } + // default groovy methods if (object instanceof GrGdkMethod && GroovyCompletionUtil.skipDefGroovyMethod((GrGdkMethod)object, substitutor, qualifierType)) { - return PrioritizedLookupElement.withPriority(lookupElement, -1); + return -1; } // operator methods if (object instanceof PsiMethod && GroovyCompletionUtil.OPERATOR_METHOD_NAMES.contains(((PsiMethod)object).getName()) && !checkForIterator((PsiMethod)object)) { - return PrioritizedLookupElement.withPriority(lookupElement, -3); + return -3; } // accessors if there is no get, set, is prefix if (object instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)object)) { - return PrioritizedLookupElement.withPriority(lookupElement, -1); + return -1; } // inaccessible elements if (resolveResult != null && !resolveResult.isAccessible()) { - return PrioritizedLookupElement.withPriority(lookupElement, -2); + return -2; } - return lookupElement; + return 0; } static StaticMemberProcessor completeStaticMembers(CompletionParameters parameters) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java index 957e080bd9f0..32fdbd4bb532 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java @@ -16,9 +16,21 @@ package org.jetbrains.plugins.groovy.lang.completion; import com.intellij.codeInsight.completion.*; +import com.intellij.codeInsight.completion.impl.CamelHumpMatcher; import com.intellij.codeInsight.lookup.AutoCompletionPolicy; import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiType; import com.intellij.util.Consumer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; /** * @author peter @@ -27,27 +39,114 @@ public class GroovyNoVariantsDelegator extends NoVariantsDelegator { @Override protected void delegate(CompletionParameters parameters, CompletionResultSet result, Consumer passResult) { - if (parameters.getCompletionType() == CompletionType.BASIC && - parameters.getInvocationCount() <= 1 && - JavaCompletionContributor.mayStartClassName(result, false) && - GroovyCompletionContributor.isClassNamePossible(parameters.getPosition()) && - !MapArgumentCompletionProvider.isMapKeyCompletion(parameters)) { - final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result); - - GroovyCompletionContributor.addAllClasses(parameters, result, - new Consumer() { - @Override - public void consume(LookupElement element) { - JavaPsiClassReferenceElement classElement = element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY); - if (classElement != null) { - classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); - } - merger.consume(classElement); - } - }, new InheritorsHolder(parameters.getPosition(), result)); - - merger.finishedClassProcessing(); + if (parameters.getCompletionType() == CompletionType.BASIC) { + if (parameters.getInvocationCount() <= 1 && + JavaCompletionContributor.mayStartClassName(result, false) && + GroovyCompletionContributor.isClassNamePossible(parameters.getPosition()) && + !MapArgumentCompletionProvider.isMapKeyCompletion(parameters)) { + suggestNonImportedClasses(parameters, result); + } + suggestChainedCalls(parameters, result); } } + + private static void suggestNonImportedClasses(CompletionParameters parameters, CompletionResultSet result) { + final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result); + + GroovyCompletionContributor.addAllClasses(parameters, new Consumer() { + @Override + public void consume(LookupElement element) { + JavaPsiClassReferenceElement classElement = + element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY); + if (classElement != null) { + classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); + } + merger.consume(classElement); + } + }, new InheritorsHolder(parameters.getPosition(), result), result.getPrefixMatcher()); + + merger.finishedClassProcessing(); + } + + private static void suggestChainedCalls(CompletionParameters parameters, CompletionResultSet result) { + PsiElement position = parameters.getPosition(); + PsiElement parent = position.getParent(); + if (!(parent instanceof GrReferenceElement)) { + return; + } + PsiElement qualifier = ((GrReferenceElement)parent).getQualifier(); + if (!(qualifier instanceof GrReferenceElement) || + ((GrReferenceElement)qualifier).getQualifier() != null || + ((GrReferenceElement)qualifier).resolve() != null) { + return; + } + + String fullPrefix = position.getContainingFile().getText().substring(parent.getTextRange().getStartOffset(), parameters.getOffset()); + final CompletionResultSet qualifiedCollector = result.withPrefixMatcher(fullPrefix); + InheritorsHolder inheritors = new InheritorsHolder(position, result); + for (final LookupElement base : suggestQualifierItems(parameters, (GrReferenceElement)qualifier, inheritors)) { + final PsiType type = JavaCompletionUtil.getLookupElementType(base); + if (type != null && !PsiType.VOID.equals(type)) { + GrReferenceElement ref = createMockReference(position, type, base); + PsiElement refName = ref.getReferenceNameElement(); + assert refName != null; + for (LookupElement element : GroovyCompletionContributor.completeReference( + parameters.withPosition(refName, refName.getTextRange().getStartOffset()), ref, inheritors, qualifiedCollector.getPrefixMatcher())) { + qualifiedCollector.addElement(new JavaChainLookupElement(base, element) { + @Override + protected boolean shouldParenthesizeQualifier(PsiFile file, int startOffset, int endOffset) { + return false; + } + }); + } + } + } + } + + private static GrReferenceElement createMockReference(final PsiElement place, @NotNull PsiType qualifierType, LookupElement qualifierItem) { + GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(place.getProject()); + if (qualifierItem.getObject() instanceof PsiClass) { + return factory + .createReferenceExpressionFromText(((PsiClass)qualifierItem.getObject()).getQualifiedName() + ".xxx", place); + } + + return factory.createReferenceExpressionFromText("xxx.xxx", + ReferenceExpressionCompletionContributor + .createContextWithXxxVariable(place, qualifierType)); + } + + + private static Set suggestQualifierItems(CompletionParameters _parameters, + GrReferenceElement qualifier, + InheritorsHolder inheritors) { + CompletionParameters parameters = + _parameters.withPosition(qualifier.getReferenceNameElement(), qualifier.getTextRange().getEndOffset()); + String referenceName = qualifier.getReferenceName(); + if (referenceName == null) { + return Collections.emptySet(); + } + + final PrefixMatcher qMatcher = new CamelHumpMatcher(referenceName); + final Set variants = new LinkedHashSet(); + for (LookupElement element : GroovyCompletionContributor.completeReference(parameters, qualifier, inheritors, qMatcher)) { + if (qMatcher.prefixMatches(element)) { + variants.add(element); + } + } + + if (variants.isEmpty()) { + GroovyCompletionContributor.addAllClasses(parameters, new Consumer() { + @Override + public void consume(LookupElement element) { + if (qMatcher.prefixMatches(element)) { + variants.add(element); + } + } + }, inheritors, qMatcher); + } + return variants; + } + + } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java index 54bdbe6af25b..2c4a6af49cfb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java @@ -25,7 +25,6 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import com.intellij.util.containers.hash.HashSet; import org.jetbrains.annotations.NotNull; @@ -48,7 +47,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrRe import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; -import org.jetbrains.plugins.groovy.lang.psi.util.GrClassImplUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ClosureMissingMethodContributor; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; @@ -88,7 +86,6 @@ public class CompleteReferenceExpression { private static void getVariantsImpl(PrefixMatcher matcher, GrReferenceExpression refExpr, CompleteReferenceProcessor processor) { GrExpression qualifier = refExpr.getQualifierExpression(); - getVariantsWithSameQualifier(matcher, qualifier, refExpr, processor); if (qualifier == null) { ResolveUtil.treeWalkUp(refExpr, processor, true); @@ -228,7 +225,8 @@ public class CompleteReferenceExpression { return; } } - getVariantsFromQualifierType(refExpr, processor, GrClassImplUtil.getGroovyObjectType(refExpr), project); + getVariantsFromQualifierType(refExpr, processor, + PsiType.getJavaLangObject(refExpr.getManager(), qualifier.getResolveScope()), project); } else if (qualifierType instanceof PsiIntersectionType) { for (PsiType conjunct : ((PsiIntersectionType)qualifierType).getConjuncts()) { @@ -256,20 +254,19 @@ public class CompleteReferenceExpression { } } - private static String[] getVariantsWithSameQualifier(PrefixMatcher matcher,GrExpression qualifier, GrReferenceExpression refExpr, CompleteReferenceProcessor processor) { - if (qualifier != null && qualifier.getType() != null) return ArrayUtil.EMPTY_STRING_ARRAY; + public static Set getVariantsWithSameQualifier(PrefixMatcher matcher, @Nullable GrExpression qualifier, GrReferenceExpression refExpr) { + if (qualifier != null && qualifier.getType() != null) return Collections.emptySet(); final PsiElement scope = PsiTreeUtil.getParentOfType(refExpr, GrMember.class, PsiFile.class); Set result = new LinkedHashSet(); - addVariantsWithSameQualifier(matcher, scope, refExpr, qualifier, result, processor); - return ArrayUtil.toStringArray(result); + addVariantsWithSameQualifier(matcher, scope, refExpr, qualifier, result); + return result; } private static void addVariantsWithSameQualifier(PrefixMatcher matcher, PsiElement element, GrReferenceExpression patternExpression, GrExpression patternQualifier, - Set result, - CompleteReferenceProcessor processor) { + Set result) { if (element instanceof GrReferenceExpression && element != patternExpression && !PsiUtil.isLValue((GroovyPsiElement)element)) { final GrReferenceExpression refExpr = (GrReferenceExpression)element; final String refName = refExpr.getReferenceName(); @@ -279,21 +276,19 @@ public class CompleteReferenceExpression { if (PsiEquivalenceUtil.areElementsEquivalent(hisQualifier, patternQualifier)) { if (refExpr.resolve() == null) { result.add(refName); - processor.consume(refName); } } } else if (hisQualifier == null && patternQualifier == null) { if (refExpr.resolve() == null) { result.add(refName); - processor.consume(refName); } } } } for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) { - addVariantsWithSameQualifier(matcher, child, patternExpression, patternQualifier, result, processor); + addVariantsWithSameQualifier(matcher, child, patternExpression, patternQualifier, result); } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy index 5cb4306414a9..e47e50a569e7 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy @@ -56,7 +56,7 @@ class GroovyAutoPopupTest extends CompletionAutoPopupTestCase { public void testNoLookupFocusOnUnresolvedQualifier() { myFixture.configureByText("a.groovy", """xxx.""") type 'h' //hashCode - assert !lookup.focused + assert !lookup } public void testNoLookupFocusOnUntypedQualifier() { @@ -65,7 +65,7 @@ class GroovyAutoPopupTest extends CompletionAutoPopupTestCase { xxx. }""") type 'h' - assert !lookup.focused + assert !lookup } public void testPossibleClosureParameter() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index c8ac6a4b037c..5adc0dd80ad8 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -1108,6 +1108,18 @@ public class KeyVO { checkSingleItemCompletion 'class Foo impl {}', 'class Foo implements {}' } + public void testAmbiguousClassQualifier() { + myFixture.addClass("package foo; public class Util { public static void foo() {} }") + myFixture.addClass("package bar; public class Util { public static void bar() {} }") + myFixture.configureByText 'a.groovy', 'Util.' + myFixture.completeBasic() + assert myFixture.lookupElementStrings[0..1] == ['Util.bar', 'Util.foo'] + myFixture.type 'f\n' + myFixture.checkResult '''import foo.Util + +Util.foo()''' + } + public void testPreferInterfacesInImplements() { myFixture.addClass('interface FooIntf {}') myFixture.addClass('class FooClass {}') diff --git a/plugins/groovy/testdata/groovy/oldCompletion/reference/tupleObjCompl.test b/plugins/groovy/testdata/groovy/oldCompletion/reference/tupleObjCompl.test index dc46468034b5..3da80cb6eb56 100644 --- a/plugins/groovy/testdata/groovy/oldCompletion/reference/tupleObjCompl.test +++ b/plugins/groovy/testdata/groovy/oldCompletion/reference/tupleObjCompl.test @@ -1,4 +1,3 @@ def (street, home, postCode) def s = street.toS ------ -toString \ No newline at end of file +----- \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/oldCompletion/reference/untyped.test b/plugins/groovy/testdata/groovy/oldCompletion/reference/untyped.test index 62a56f8f57b3..369b6e64961c 100644 --- a/plugins/groovy/testdata/groovy/oldCompletion/reference/untyped.test +++ b/plugins/groovy/testdata/groovy/oldCompletion/reference/untyped.test @@ -1,3 +1,2 @@ unknown.metaCl ------ -metaClass \ No newline at end of file +----- \ No newline at end of file From c2125f8ac57297f91ce3f43f1ae48836ae91e04b Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 8 Feb 2012 15:39:38 +0100 Subject: [PATCH 09/18] show location package in chained call items (IDEA-58766) --- .../completion/JavaChainLookupElement.java | 13 ++++++++++++- .../lookup/LookupElementPresentation.java | 6 ++++++ .../groovy/completion/GroovyCompletionTest.groovy | 6 ++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java index 6a8595751701..83243e975e63 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java @@ -19,11 +19,13 @@ import com.intellij.codeInsight.lookup.*; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.ClassConditionKey; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.util.PsiTreeUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Set; @@ -65,11 +67,16 @@ public class JavaChainLookupElement extends LookupElementDecorator' myFixture.completeBasic() assert myFixture.lookupElementStrings[0..1] == ['Util.bar', 'Util.foo'] + + def presentation = LookupElementPresentation.renderElement(myFixture.lookupElements[0]) + assert 'Util.bar' == presentation.itemText + assert '() (bar)' == presentation.tailText + assert !presentation.tailGrayed + myFixture.type 'f\n' myFixture.checkResult '''import foo.Util From 335577008ad3012f612f6d6e21a7c061a6a575ec Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 8 Feb 2012 16:36:48 +0100 Subject: [PATCH 10/18] chained property completion in groovy (IDEA-58766) --- .../groovy/lang/completion/GroovyNoVariantsDelegator.java | 2 +- .../plugins/groovy/completion/GroovyCompletionTest.groovy | 2 ++ .../testdata/groovy/completion/PropertyChain.groovy | 8 ++++++++ .../testdata/groovy/completion/PropertyChain_after.groovy | 8 ++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 plugins/groovy/testdata/groovy/completion/PropertyChain.groovy create mode 100644 plugins/groovy/testdata/groovy/completion/PropertyChain_after.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java index 32fdbd4bb532..55a8f20a93e5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java @@ -92,7 +92,7 @@ public class GroovyNoVariantsDelegator extends NoVariantsDelegator { PsiElement refName = ref.getReferenceNameElement(); assert refName != null; for (LookupElement element : GroovyCompletionContributor.completeReference( - parameters.withPosition(refName, refName.getTextRange().getStartOffset()), ref, inheritors, qualifiedCollector.getPrefixMatcher())) { + parameters.withPosition(refName, refName.getTextRange().getStartOffset()), ref, inheritors, result.getPrefixMatcher())) { qualifiedCollector.addElement(new JavaChainLookupElement(base, element) { @Override protected boolean shouldParenthesizeQualifier(PsiFile file, int startOffset, int endOffset) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index 34299c798c27..fe133175c2fb 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -1131,4 +1131,6 @@ Util.foo()''' myFixture.addClass('class FooClass {}') doVariantableTest('FooIntf', 'FooClass') } + + public void testPropertyChain() { doBasicTest() } } \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/completion/PropertyChain.groovy b/plugins/groovy/testdata/groovy/completion/PropertyChain.groovy new file mode 100644 index 000000000000..cc24bcc939bc --- /dev/null +++ b/plugins/groovy/testdata/groovy/completion/PropertyChain.groovy @@ -0,0 +1,8 @@ +class A { + File myFile; + + def foo() { + myf.cap + } + +} \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/completion/PropertyChain_after.groovy b/plugins/groovy/testdata/groovy/completion/PropertyChain_after.groovy new file mode 100644 index 000000000000..84c0be7c409a --- /dev/null +++ b/plugins/groovy/testdata/groovy/completion/PropertyChain_after.groovy @@ -0,0 +1,8 @@ +class A { + File myFile; + + def foo() { + myFile.canonicalPath + } + +} \ No newline at end of file From 606b53b92152210a6f8487159f3b57db9f200a39 Mon Sep 17 00:00:00 2001 From: Dmitry Boulytchev Date: Wed, 8 Feb 2012 22:24:43 +0400 Subject: [PATCH 11/18] Import import and a modest enhancement in integrate (compile server). --- .../ether/dependencyView/Mappings.java | 62 +++++++++++++++++-- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index 5cb34dc91432..67d9f9af2d2a 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -35,10 +35,18 @@ public class Mappings { private boolean myIsDifferentiated = false; private final List myChangedClasses; + private final List myChangedFiles; private void addChangedClass(final DependencyContext.S it) { - assert (myChangedClasses != null); + assert (myChangedClasses != null && myChangedFiles != null); myChangedClasses.add(it); + + final DependencyContext.S file = myClassToSourceFile.get(it); + + if (file != null) { + myChangedFiles.add(it); + } + myIsDifferentiated = true; } @@ -46,6 +54,10 @@ public class Mappings { return myChangedClasses; } + private Collection getChangedFiles() { + return myChangedFiles; + } + private boolean isDifferentiated() { return myIsDifferentiated; } @@ -110,6 +122,7 @@ public class Mappings { private Mappings(final Mappings base) throws IOException { myIsDelta = true; myChangedClasses = new LinkedList(); + myChangedFiles = new LinkedList(); myDeltaIsTransient = base.myDeltaIsTransient; myRootDir = new File(FileUtil.toSystemIndependentName(base.myRootDir.getAbsolutePath()) + File.separatorChar + "delta"); myContext = base.myContext; @@ -121,6 +134,7 @@ public class Mappings { public Mappings(final File rootDir, final boolean transientDelta) throws IOException { myIsDelta = false; myChangedClasses = null; + myChangedFiles = null; myDeltaIsTransient = transientDelta; myRootDir = rootDir; createImplementation(); @@ -1579,9 +1593,32 @@ public class Mappings { myClassToSourceFile.putAll(delta.myClassToSourceFile); } - mySourceFileToClasses.putAll(delta.mySourceFileToClasses); - mySourceFileToUsages.putAll(delta.mySourceFileToUsages); - mySourceFileToAnnotationUsages.putAll(delta.mySourceFileToAnnotationUsages); + if (delta.isDifferentiated()) { + for (DependencyContext.S f : delta.getChangedFiles()) { + mySourceFileToClasses.remove(f); + final Collection classes = delta.mySourceFileToClasses.get(f); + if (classes != null){ + mySourceFileToClasses.put(f, classes); + } + + mySourceFileToUsages.remove(f); + final Collection clusters = delta.mySourceFileToUsages.get(f); + if (clusters != null){ + mySourceFileToUsages.put(f, clusters); + } + + mySourceFileToAnnotationUsages.remove(f); + final Collection usages = delta.mySourceFileToAnnotationUsages.get(f); + if (usages != null){ + mySourceFileToAnnotationUsages.put(f, usages); + } + } + } + else { + mySourceFileToClasses.putAll(delta.mySourceFileToClasses); + mySourceFileToUsages.putAll(delta.mySourceFileToUsages); + mySourceFileToAnnotationUsages.putAll(delta.mySourceFileToAnnotationUsages); + } final Collection compiledSet = new HashSet(compiled.size()); @@ -1684,8 +1721,21 @@ public class Mappings { } @Override - public void registerImports(Collection imports, String rootClass) { - //To change body of implemented methods use File | Settings | File Templates. + public void registerImports(final Collection imports, final String rootClass) { + final DependencyContext.S rootClassName = myContext.get(rootClass); + final DependencyContext.S fileName = myClassToSourceFile.get(rootClassName); + + for (final String i : imports) { + final DependencyContext.S iname = myContext.get(i); + + myClassToClassDependency.put(rootClassName, iname); + + if (fileName != null) { + final UsageRepr.Cluster cluster = new UsageRepr.Cluster(); + cluster.addUsage(rootClassName, UsageRepr.createClassUsage(myContext, iname)); + mySourceFileToUsages.put(fileName, cluster); + } + } } }; } From 14d2a6388806db1bd882b674409760d84fd46a53 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Wed, 8 Feb 2012 19:38:01 +0100 Subject: [PATCH 12/18] IDEA-80929 focus is lost in commit dialog --- .../com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index 2967be12aeee..d96b8b17f2b8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -39,6 +39,7 @@ import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.ui.popup.JBPopupFactory; @@ -2186,6 +2187,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements if (root != null) { JComponent toFocus = IdeFocusTraversalPolicy.getPreferredFocusedComponent(root); if (toFocus != null) { + if (DialogWrapper.findInstance(toFocus) != null) { + return new ActionCallback.Done(); //IDEA-80929 + } return IdeFocusManager.findInstanceByComponent(toFocus).requestFocus(toFocus, forced); } } From c83ffde9432d1a839e8f6bf068e423eb0286633b Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 8 Feb 2012 13:00:11 +0100 Subject: [PATCH 13/18] collapse "-D" vm parameters if command line is too long (IDEA-76030) --- .../rt/execution/CommandLineWrapper.java | 39 ++++++++- .../openapi/projectRoots/JdkUtil.java | 83 ++++++++++++++----- 2 files changed, 98 insertions(+), 24 deletions(-) diff --git a/java/java-runtime/src/com/intellij/rt/execution/CommandLineWrapper.java b/java/java-runtime/src/com/intellij/rt/execution/CommandLineWrapper.java index e0b8236b9c72..57567b0a6d84 100644 --- a/java/java-runtime/src/com/intellij/rt/execution/CommandLineWrapper.java +++ b/java/java-runtime/src/com/intellij/rt/execution/CommandLineWrapper.java @@ -32,6 +32,7 @@ import java.util.ArrayList; import java.util.List; public class CommandLineWrapper { + private static final String PREFIX = "-D"; public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, InstantiationException { @@ -54,9 +55,41 @@ public class CommandLineWrapper { reader.close(); } file.delete(); - String progClass = args[1]; - String[] progArgs = new String[args.length - 2]; - System.arraycopy(args, 2, progArgs, 0, progArgs.length); + + int startArgsIdx = 2; + if (args[1].equals("@vm_params")) { + startArgsIdx = 4; + final File vmParamsFile = new File(args[2]); + final BufferedReader vmParamsReader = new BufferedReader(new FileReader(vmParamsFile)); + try { + while (vmParamsReader.ready()) { + final String vmParam = vmParamsReader.readLine().trim(); + final int eqIdx = vmParam.indexOf("="); + String vmParamName; + String vmParamValue; + + if (eqIdx > -1 && eqIdx < vmParam.length() - 1) { + vmParamName = vmParam.substring(0, eqIdx); + vmParamValue = vmParam.substring(eqIdx + 1); + } else { + vmParamName = vmParam; + vmParamValue = ""; + } + vmParamName = vmParamName.trim(); + if (vmParamName.startsWith(PREFIX)) { + vmParamName = vmParamName.substring(PREFIX.length()); + System.setProperty(vmParamName, vmParamValue); + } + } + } + finally { + vmParamsReader.close(); + } + vmParamsFile.delete(); + } + String progClass = args[startArgsIdx - 1]; + String[] progArgs = new String[args.length - startArgsIdx]; + System.arraycopy(args, startArgsIdx, progArgs, 0, progArgs.length); ClassLoader loader = new URLClassLoader((URL[])urls.toArray(new URL[urls.size()]), null); final String classloader = System.getProperty("java.system.class.loader"); if (classloader != null) { diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java index 23076fc95046..62ea6513fb23 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java @@ -40,6 +40,7 @@ import org.jetbrains.annotations.Nullable; import java.io.*; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; +import java.util.List; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; @@ -147,32 +148,13 @@ public class JdkUtil { commandLine.setExePath(exePath); ParametersList parametersList = javaParameters.getVMParametersList(); - commandLine.addParameters(parametersList.getList()); - - // Value of -Dfile.encoding and charset of GeneralCommandLine should be in sync in order process's input and output be correctly handled. - String encoding = parametersList.getPropertyValue("file.encoding"); - if (encoding == null) { - Charset charset = javaParameters.getCharset(); - if (charset == null) charset = EncodingManager.getInstance().getDefaultCharset(); - if (charset == null) charset = CharsetToolkit.getDefaultSystemCharset(); - commandLine.addParameter("-Dfile.encoding=" + charset.name()); - commandLine.setCharset(charset); - } - else { - try { - Charset charset = Charset.forName(encoding); - commandLine.setCharset(charset); - } - catch (UnsupportedCharsetException ignore) { - } - } - commandLine.setEnvParams(javaParameters.getEnv()); commandLine.setPassParentEnvs(javaParameters.isPassParentEnvs()); final Class commandLineWrapper; if (forceDynamicClasspath && (commandLineWrapper = getCommandLineWrapperClass()) != null) { File classpathFile = null; + File vmParamsFile = null; if(!parametersList.hasParameter("-classpath") && !parametersList.hasParameter("-cp")){ try { classpathFile = FileUtil.createTempFile("classpath", null); @@ -199,16 +181,55 @@ public class JdkUtil { catch (IOException e) { LOG.error(e); } + + try { + vmParamsFile = FileUtil.createTempFile("vm_params", null); + final PrintWriter writer = new PrintWriter(vmParamsFile); + try { + for (String param : parametersList.getList()) { + if (param.startsWith("-D")) { + writer.println(param); + } + } + } + finally { + writer.close(); + } + } + catch (IOException e) { + LOG.error(e); + } } + final List list = parametersList.getList(); + if (vmParamsFile == null) { + commandLine.addParameters(list); + } else { + for (String param : list) { + if (!param.trim().startsWith("-D")) { + commandLine.addParameter(param); + } + } + } + appendEncoding(javaParameters, commandLine, parametersList); if (classpathFile != null) { commandLine.addParameter(commandLineWrapper.getName()); commandLine.addParameter(classpathFile.getAbsolutePath()); } + if (vmParamsFile != null) { + commandLine.addParameter("@vm_params"); + commandLine.addParameter(vmParamsFile.getAbsolutePath()); + } } - else if(!parametersList.hasParameter("-classpath") && !parametersList.hasParameter("-cp")){ + else if (!parametersList.hasParameter("-classpath") && !parametersList.hasParameter("-cp")){ + commandLine.addParameters(parametersList.getList()); + appendEncoding(javaParameters, commandLine, parametersList); + commandLine.addParameter("-classpath"); commandLine.addParameter(javaParameters.getClassPath().getPathsString()); + } else { + commandLine.addParameters(parametersList.getList()); + appendEncoding(javaParameters, commandLine, parametersList); } final String mainClass = javaParameters.getMainClass(); @@ -220,6 +241,26 @@ public class JdkUtil { return commandLine; } + private static void appendEncoding(SimpleJavaParameters javaParameters, GeneralCommandLine commandLine, ParametersList parametersList) { + // Value of -Dfile.encoding and charset of GeneralCommandLine should be in sync in order process's input and output be correctly handled. + String encoding = parametersList.getPropertyValue("file.encoding"); + if (encoding == null) { + Charset charset = javaParameters.getCharset(); + if (charset == null) charset = EncodingManager.getInstance().getDefaultCharset(); + if (charset == null) charset = CharsetToolkit.getDefaultSystemCharset(); + commandLine.addParameter("-Dfile.encoding=" + charset.name()); + commandLine.setCharset(charset); + } + else { + try { + Charset charset = Charset.forName(encoding); + commandLine.setCharset(charset); + } + catch (UnsupportedCharsetException ignore) { + } + } + } + @Nullable private static Class getCommandLineWrapperClass() { try { From 7f34d2b6f38874c95c0ace0c65f9f9546be5018c Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 8 Feb 2012 13:13:23 +0100 Subject: [PATCH 14/18] introduce variable: reassign to existing one: reuse old name in everywhere --- .../introduceVariable/JavaVariableInplaceIntroducer.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java index 0ff43fa7f042..400611d56e47 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java @@ -45,6 +45,7 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.ArrayList; import java.util.List; /** @@ -85,8 +86,10 @@ public class JavaVariableInplaceIntroducer extends InplaceVariableIntroducer rangeMarkers = new ArrayList(occurrenceMarkers); + rangeMarkers.add(exprMarker); editor.putUserData(ReassignVariableUtil.OCCURRENCES_KEY, - occurrenceMarkers.toArray(new RangeMarker[occurrenceMarkers.size()])); + rangeMarkers.toArray(new RangeMarker[rangeMarkers.size()])); } myExpression = expression; final PsiType defaultType = elementToRename.getType(); From 1e784542b816af186635fcc9697c9965a039dacf Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 8 Feb 2012 14:13:46 +0100 Subject: [PATCH 15/18] move: move inner class with other files with its top level only (EA-33583 - CCE: JavaMoveFilesOrDirectoriesHandler.obtainContainingFile) --- .../JavaMoveFilesOrDirectoriesHandler.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/JavaMoveFilesOrDirectoriesHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/JavaMoveFilesOrDirectoriesHandler.java index 370d0e4f271b..c67b7b7b0967 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/JavaMoveFilesOrDirectoriesHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/JavaMoveFilesOrDirectoriesHandler.java @@ -24,6 +24,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.impl.file.JavaDirectoryServiceImpl; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.PsiUtilBase; import com.intellij.refactoring.move.MoveCallback; import com.intellij.util.ArrayUtil; @@ -76,9 +77,12 @@ public class JavaMoveFilesOrDirectoriesHandler extends MoveFilesOrDirectoriesHan @Override protected void run(Result result) throws Throwable { final List adjustedElements = new ArrayList(); - for (PsiElement element : elements) { + for (int i = 0, length = elements.length; i < length; i++) { + PsiElement element = elements[i]; if (element instanceof PsiClass) { - final PsiFile containingFile = obtainContainingFile(element, elements); + final PsiClass topLevelClass = PsiUtil.getTopLevelClass(element); + elements[i] = topLevelClass; + final PsiFile containingFile = obtainContainingFile(topLevelClass, elements); if (containingFile != null && !adjustedElements.contains(containingFile)) { adjustedElements.add(containingFile); } From 1551ce991fc97d3f1a64627dc70fe6f3cb454f57 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 8 Feb 2012 14:15:53 +0100 Subject: [PATCH 16/18] EA-33584 - assert: Alarm._addRequest --- .../src/com/intellij/diagnostic/logging/LogConsoleBase.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleBase.java b/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleBase.java index 6b6fd6351e66..452f22b6a61b 100644 --- a/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleBase.java +++ b/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleBase.java @@ -617,6 +617,7 @@ public abstract class LogConsoleBase extends AdditionalTabComponent implements L myAlarm.addRequest(this, 100); } }; + if (myAlarm.isDisposed()) return; myAlarm.addRequest(runnable, 10); } From c5fc815080a84c066d80390f78782a14a6372fe7 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 8 Feb 2012 19:38:41 +0100 Subject: [PATCH 17/18] check for writable: EA-33580 - IOE: CheckUtil.checkWritable --- .../codeInsight/daemon/impl/quickfix/PullAsAbstractUpFix.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/PullAsAbstractUpFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/PullAsAbstractUpFix.java index 92134363acbf..883c17f21592 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/PullAsAbstractUpFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/PullAsAbstractUpFix.java @@ -122,6 +122,7 @@ public class PullAsAbstractUpFix extends LocalQuickFixAndIntentionActionOnPsiEle } private static void pullUp(PsiMethod method, PsiClass containingClass, PsiClass baseClass) { + if (!CodeInsightUtilBase.prepareFileForWrite(baseClass.getContainingFile())) return; final MemberInfo memberInfo = new MemberInfo(method); memberInfo.setChecked(true); memberInfo.setToAbstract(true); From 64e49569a2a0237102ac87a2123a474020e96b6c Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Wed, 8 Feb 2012 23:01:34 +0400 Subject: [PATCH 18/18] Android Designer --- plugins/android-designer/android-designer.iml | 2 + .../android-designer/src/META-INF/plugin.xml | 7 ++ .../designer/AndroidDesignerBundle.java | 50 ++++++++++ .../designer/AndroidDesignerEditor.java | 65 +++++++++++++ .../AndroidDesignerEditorProvider.java | 87 +++++++++++++++++ .../messages/AndroidDesignerBundle.properties | 1 + .../ui-designer-new/src/META-INF/plugin.xml | 11 ++- .../intellij/uiDesigner/DesignerEditor.java | 97 +++++++++++++++++++ .../intellij/uiDesigner/UIDesignerBundle.java | 50 ++++++++++ .../UIDesignerToolWindowManager.java | 52 ++++++++++ .../componentTree/ComponentTree.java | 30 ++++++ .../designSurface/DesignerEditorPanel.java | 48 +++++++++ .../uiDesigner/model/RadComponent.java | 47 +++++++++ .../uiDesigner/propertyTable/Property.java | 60 ++++++++++++ .../propertyTable/PropertyEditor.java | 29 ++++++ .../propertyTable/PropertyRenderer.java | 41 ++++++++ .../propertyTable/PropertyTable.java | 30 ++++++ .../propertyTable/PropertyTablePanel.java | 29 ++++++ 18 files changed, 735 insertions(+), 1 deletion(-) create mode 100644 plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerBundle.java create mode 100644 plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerEditor.java create mode 100644 plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerEditorProvider.java create mode 100644 plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/DesignerEditor.java create mode 100644 plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/UIDesignerBundle.java create mode 100644 plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/UIDesignerToolWindowManager.java create mode 100644 plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/componentTree/ComponentTree.java create mode 100644 plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/designSurface/DesignerEditorPanel.java create mode 100644 plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/model/RadComponent.java create mode 100644 plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/Property.java create mode 100644 plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyEditor.java create mode 100644 plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyRenderer.java create mode 100644 plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyTable.java create mode 100644 plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyTablePanel.java diff --git a/plugins/android-designer/android-designer.iml b/plugins/android-designer/android-designer.iml index 9a14d495950f..a6cb9856732d 100644 --- a/plugins/android-designer/android-designer.iml +++ b/plugins/android-designer/android-designer.iml @@ -22,6 +22,8 @@ + + diff --git a/plugins/android-designer/src/META-INF/plugin.xml b/plugins/android-designer/src/META-INF/plugin.xml index 6705ae7c0b31..b808ad518995 100644 --- a/plugins/android-designer/src/META-INF/plugin.xml +++ b/plugins/android-designer/src/META-INF/plugin.xml @@ -2,9 +2,16 @@ Android Designer com.intellij.android-designer JetBrains + messages.AndroidDesignerBundle + com.intellij.java-i18n com.intellij.properties org.jetbrains.android com.intellij.ui-designer-new + + + + + diff --git a/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerBundle.java b/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerBundle.java new file mode 100644 index 000000000000..6442f216e766 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerBundle.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.android.designer; + +import com.intellij.CommonBundle; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.PropertyKey; + +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.util.ResourceBundle; + +/** + * @author yole + */ +public class AndroidDesignerBundle { + private static Reference ourBundle; + + @NonNls private static final String BUNDLE = "messages.AndroidDesignerBundle"; + + private AndroidDesignerBundle() { + } + + public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) { + return CommonBundle.message(getBundle(), key, params); + } + + private static ResourceBundle getBundle() { + ResourceBundle bundle = null; + if (ourBundle != null) bundle = ourBundle.get(); + if (bundle == null) { + bundle = ResourceBundle.getBundle(BUNDLE); + ourBundle = new SoftReference(bundle); + } + return bundle; + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerEditor.java b/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerEditor.java new file mode 100644 index 000000000000..da32138b3de3 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerEditor.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.android.designer; + +import com.intellij.openapi.fileEditor.FileEditorState; +import com.intellij.openapi.fileEditor.FileEditorStateLevel; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.uiDesigner.DesignerEditor; +import org.jetbrains.annotations.NotNull; + +/** + * @author Alexander Lobas + */ +public final class AndroidDesignerEditor extends DesignerEditor { + public AndroidDesignerEditor(Project project, VirtualFile file) { + super(project, file); + } + + @NotNull + @Override + public String getName() { + return AndroidDesignerBundle.message("editor.tab.title"); + } + + @Override + public boolean isValid() { + return true; // TODO: Auto-generated method stub + } + + @NotNull + @Override + public FileEditorState getState(@NotNull FileEditorStateLevel level) { + // TODO: Auto-generated method stub + return new FileEditorState() { + @Override + public boolean canBeMergedWith(FileEditorState otherState, FileEditorStateLevel level) { + return false; + } + }; + } + + @Override + public void setState(@NotNull FileEditorState state) { + // TODO: Auto-generated method stub + } + + @Override + public boolean isModified() { + return false; + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerEditorProvider.java b/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerEditorProvider.java new file mode 100644 index 000000000000..cb4e2796aa59 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/AndroidDesignerEditorProvider.java @@ -0,0 +1,87 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.android.designer; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.*; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.xml.XmlFile; +import org.jdom.Element; +import org.jetbrains.android.dom.layout.LayoutDomFileDescription; +import org.jetbrains.android.facet.AndroidFacet; +import org.jetbrains.annotations.NotNull; + +/** + * @author Alexander Lobas + */ +public final class AndroidDesignerEditorProvider implements FileEditorProvider, DumbAware { + @Override + public boolean accept(@NotNull Project project, @NotNull VirtualFile file) { + Document document = FileDocumentManager.getInstance().getDocument(file); + if (document != null) { + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); + return psiFile instanceof XmlFile && + AndroidFacet.getInstance(psiFile) != null && + LayoutDomFileDescription.isLayoutFile((XmlFile)psiFile); + } + return false; + } + + @NotNull + @Override + public FileEditor createEditor(@NotNull Project project, @NotNull VirtualFile file) { + return new AndroidDesignerEditor(project, file); + } + + @Override + public void disposeEditor(@NotNull FileEditor editor) { + Disposer.dispose(editor); + } + + @NotNull + @Override + public FileEditorState readState(@NotNull Element sourceElement, @NotNull Project project, @NotNull VirtualFile file) { + // TODO: Auto-generated method stub + return new FileEditorState() { + @Override + public boolean canBeMergedWith(FileEditorState otherState, FileEditorStateLevel level) { + return false; + } + }; + } + + @Override + public void writeState(@NotNull FileEditorState state, @NotNull Project project, @NotNull Element targetElement) { + // TODO: Auto-generated method stub + } + + @NotNull + @Override + public String getEditorTypeId() { + return "android-designer"; + } + + @NotNull + @Override + public FileEditorPolicy getPolicy() { + return FileEditorPolicy.PLACE_BEFORE_DEFAULT_EDITOR; + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/messages/AndroidDesignerBundle.properties b/plugins/android-designer/src/messages/AndroidDesignerBundle.properties index e69de29bb2d1..d45742e29143 100644 --- a/plugins/android-designer/src/messages/AndroidDesignerBundle.properties +++ b/plugins/android-designer/src/messages/AndroidDesignerBundle.properties @@ -0,0 +1 @@ +editor.tab.title=Design \ No newline at end of file diff --git a/plugins/ui-designer/ui-designer-new/src/META-INF/plugin.xml b/plugins/ui-designer/ui-designer-new/src/META-INF/plugin.xml index 1f86521a5c16..f17e6122d390 100644 --- a/plugins/ui-designer/ui-designer-new/src/META-INF/plugin.xml +++ b/plugins/ui-designer/ui-designer-new/src/META-INF/plugin.xml @@ -1,8 +1,17 @@ - UI Designer + UI Designer (Core) com.intellij.ui-designer-new JetBrains + messages.UIDesignerBundle + com.intellij.java-i18n com.intellij.properties + + + + com.intellij.uiDesigner.UIDesignerToolWindowManager + + + diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/DesignerEditor.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/DesignerEditor.java new file mode 100644 index 000000000000..9612ef06c6c3 --- /dev/null +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/DesignerEditor.java @@ -0,0 +1,97 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner; + +import com.intellij.codeHighlighting.BackgroundEditorHighlighter; +import com.intellij.ide.structureView.StructureViewBuilder; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.fileEditor.FileEditorLocation; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.UserDataHolderBase; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.LightVirtualFile; +import com.intellij.uiDesigner.designSurface.DesignerEditorPanel; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.beans.PropertyChangeListener; + +/** + * @author Alexander Lobas + */ +public abstract class DesignerEditor extends UserDataHolderBase implements FileEditor { + private final DesignerEditorPanel myDesignerPanel; + + public DesignerEditor(Project project, VirtualFile file) { + if (file instanceof LightVirtualFile) { + file = ((LightVirtualFile)file).getOriginalFile(); + } + Module module = ModuleUtil.findModuleForFile(file, project); + if (module == null) { + throw new IllegalArgumentException("No module for file " + file + " in project " + project); + } + myDesignerPanel = new DesignerEditorPanel(module, file); + } + + @NotNull + @Override + public JComponent getComponent() { + return myDesignerPanel; + } + + @Override + public JComponent getPreferredFocusedComponent() { + return myDesignerPanel.getPreferredFocusedComponent(); + } + + @Override + public void dispose() { + myDesignerPanel.dispose(); + } + + @Override + public void selectNotify() { + } + + @Override + public void deselectNotify() { + } + + @Override + public void addPropertyChangeListener(@NotNull PropertyChangeListener listener) { + } + + @Override + public void removePropertyChangeListener(@NotNull PropertyChangeListener listener) { + } + + @Override + public BackgroundEditorHighlighter getBackgroundHighlighter() { + return null; + } + + @Override + public FileEditorLocation getCurrentLocation() { + return null; + } + + @Override + public StructureViewBuilder getStructureViewBuilder() { + return null; + } +} \ No newline at end of file diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/UIDesignerBundle.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/UIDesignerBundle.java new file mode 100644 index 000000000000..ec46f725d320 --- /dev/null +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/UIDesignerBundle.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner; + +import com.intellij.CommonBundle; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.PropertyKey; + +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.util.ResourceBundle; + +/** + * @author yole + */ +public class UIDesignerBundle { + private static Reference ourBundle; + + @NonNls private static final String BUNDLE = "messages.UIDesignerBundle"; + + private UIDesignerBundle() { + } + + public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) { + return CommonBundle.message(getBundle(), key, params); + } + + private static ResourceBundle getBundle() { + ResourceBundle bundle = null; + if (ourBundle != null) bundle = ourBundle.get(); + if (bundle == null) { + bundle = ResourceBundle.getBundle(BUNDLE); + ourBundle = new SoftReference(bundle); + } + return bundle; + } +} \ No newline at end of file diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/UIDesignerToolWindowManager.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/UIDesignerToolWindowManager.java new file mode 100644 index 000000000000..03f0171f0aaa --- /dev/null +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/UIDesignerToolWindowManager.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner; + +import com.intellij.openapi.components.ProjectComponent; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +/** + * @author Alexander Lobas + */ +public final class UIDesignerToolWindowManager implements ProjectComponent { + @Override + public void projectOpened() { + // TODO: Auto-generated method stub + } + + @Override + public void projectClosed() { + // TODO: Auto-generated method stub + } + + @Override + public void initComponent() { + // TODO: Auto-generated method stub + } + + @Override + public void disposeComponent() { + // TODO: Auto-generated method stub + } + + @NotNull + @NonNls + @Override + public String getComponentName() { + return "UIDesignerToolWindowManager2"; + } +} \ No newline at end of file diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/componentTree/ComponentTree.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/componentTree/ComponentTree.java new file mode 100644 index 000000000000..25e524e08173 --- /dev/null +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/componentTree/ComponentTree.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner.componentTree; + +import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.ui.treeStructure.Tree; +import org.jetbrains.annotations.NonNls; + +/** + * @author Alexander Lobas + */ +public final class ComponentTree extends Tree implements DataProvider { + @Override + public Object getData(@NonNls String dataId) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } +} \ No newline at end of file diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/designSurface/DesignerEditorPanel.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/designSurface/DesignerEditorPanel.java new file mode 100644 index 000000000000..da8039a5f012 --- /dev/null +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/designSurface/DesignerEditorPanel.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner.designSurface; + +import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; + +/** + * @author Alexander Lobas + */ +public final class DesignerEditorPanel extends JPanel implements DataProvider { + public DesignerEditorPanel(@NotNull Module module, @NotNull VirtualFile file) { + setLayout(new BorderLayout()); + add(new JLabel("Design Surface"), BorderLayout.CENTER); + } + + @Override + public Object getData(@NonNls String dataId) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public void dispose() { + // TODO: Auto-generated method stub + } + + public JComponent getPreferredFocusedComponent() { + return null; // TODO: Auto-generated method stub + } +} \ No newline at end of file diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/model/RadComponent.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/model/RadComponent.java new file mode 100644 index 000000000000..23225a438671 --- /dev/null +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/model/RadComponent.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner.model; + +import com.intellij.uiDesigner.propertyTable.Property; + +import java.util.List; + +/** + * @author Alexander Lobas + */ +public abstract class RadComponent { + private RadComponent myParent; + + public RadComponent getRoot() { + return myParent == null ? this : myParent.getRoot(); + } + + public final RadComponent getParent() { + return myParent; + } + + public final void setParent(RadComponent parent) { + myParent = parent; + } + + public List getChildren() { + return null; + } + + public List getProperties() { + return null; + } +} \ No newline at end of file diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/Property.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/Property.java new file mode 100644 index 000000000000..f2b8bfd4171b --- /dev/null +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/Property.java @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner.propertyTable; + +import com.intellij.uiDesigner.model.RadComponent; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * @author Alexander Lobas + */ +public abstract class Property { + private final Property myParent; + @NotNull private final String myName; + + public Property(Property parent, @NotNull @NonNls String name) { + + myParent = parent; + myName = name; + } + + public final Property getParent() { + return myParent; + } + + @NotNull + public final String getName() { + return myName; + } + + public List getChildren(RadComponent component) { + return null; + } + + public Object getValue(RadComponent component) { + return null; + } + + @NotNull + public abstract PropertyRenderer getRenderer(); + + @Nullable + public abstract PropertyEditor getEditor(); +} \ No newline at end of file diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyEditor.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyEditor.java new file mode 100644 index 000000000000..91029fa37dbd --- /dev/null +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyEditor.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner.propertyTable; + +import com.intellij.uiDesigner.model.RadComponent; + +import javax.swing.*; + +/** + * @author Alexander Lobas + */ +public interface PropertyEditor { + JComponent getComponent(RadComponent component, Object value); + + Object getValue(); +} \ No newline at end of file diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyRenderer.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyRenderer.java new file mode 100644 index 000000000000..5b63bf8b66ac --- /dev/null +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyRenderer.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner.propertyTable; + +import com.intellij.uiDesigner.model.RadComponent; + +import javax.swing.*; + +/** + * @author Alexander Lobas + */ +public interface PropertyRenderer { + /** + * @return JComponent to represent the value + * somewhere in UI (for example in the JList of in the JTree). To be + * consistent with other UI additional parameter abount selection and + * focus are also passed. + */ + JComponent getComponent(RadComponent component, Object value, boolean selected, boolean hasFocus); + + /** + * Renderer should update UI of all its internal components to fit current + * IDEA Look And Feel. We cannot directly update UI of the component + * that is returned by {@link #getComponent } method + * because hidden component that are not in the Swing tree can exist. + */ + void updateUI(); +} \ No newline at end of file diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyTable.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyTable.java new file mode 100644 index 000000000000..0e79e343a095 --- /dev/null +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyTable.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner.propertyTable; + +import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.ui.table.JBTable; +import org.jetbrains.annotations.NonNls; + +/** + * @author Alexander Lobas + */ +public final class PropertyTable extends JBTable implements DataProvider { + @Override + public Object getData(@NonNls String dataId) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } +} \ No newline at end of file diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyTablePanel.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyTablePanel.java new file mode 100644 index 000000000000..b6f6e9ee00a2 --- /dev/null +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/uiDesigner/propertyTable/PropertyTablePanel.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner.propertyTable; + +import javax.swing.*; +import java.awt.*; + +/** + * @author Alexander Lobas + */ +public final class PropertyTablePanel extends JPanel { + public PropertyTablePanel() { + setLayout(new BorderLayout()); + add(new JLabel("Design Surface"), BorderLayout.CENTER); + } +} \ No newline at end of file