2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com
.intellij
.codeInsight
.completion
;
18 import com
.intellij
.codeInsight
.lookup
.*;
19 import com
.intellij
.featureStatistics
.FeatureUsageTracker
;
20 import com
.intellij
.openapi
.editor
.Document
;
21 import com
.intellij
.psi
.*;
22 import com
.intellij
.psi
.codeStyle
.CodeStyleSettingsManager
;
23 import com
.intellij
.psi
.util
.PsiTreeUtil
;
24 import gnu
.trove
.THashSet
;
25 import org
.jetbrains
.annotations
.NotNull
;
32 public class JavaChainLookupElement
extends LookupElementDecorator
<LookupElement
> implements TypedLookupItem
{
33 private final LookupElement myQualifier
;
35 private JavaChainLookupElement(LookupElement qualifier
, LookupElement main
) {
37 myQualifier
= qualifier
;
42 public String
getLookupString() {
43 return maybeAddParentheses(myQualifier
.getLookupString()) + "." + getDelegate().getLookupString();
46 public LookupElement
getQualifier() {
51 public Set
<String
> getAllLookupStrings() {
52 final Set
<String
> strings
= getDelegate().getAllLookupStrings();
53 final THashSet
<String
> result
= new THashSet
<String
>();
54 result
.addAll(strings
);
55 result
.add(getLookupString());
61 public String
toString() {
62 return maybeAddParentheses(myQualifier
.toString()) + "." + getDelegate();
65 private String
maybeAddParentheses(String s
) {
66 return myQualifier
.getObject() instanceof PsiMethod ? s
+ "()" : s
;
70 public void renderElement(LookupElementPresentation presentation
) {
71 super.renderElement(presentation
);
72 final LookupElementPresentation qualifierPresentation
= new LookupElementPresentation(presentation
.isReal());
73 myQualifier
.renderElement(qualifierPresentation
);
74 String name
= maybeAddParentheses(qualifierPresentation
.getItemText());
75 final String qualifierText
= myQualifier
.as(CastingLookupElementDecorator
.class) != null ?
"(" + name
+ ")" : name
;
76 presentation
.setItemText(qualifierText
+ "." + presentation
.getItemText());
80 public void handleInsert(InsertionContext context
) {
81 FeatureUsageTracker
.getInstance().triggerFeatureUsed(JavaCompletionFeatures
.SECOND_SMART_COMPLETION_CHAIN
);
83 final Document document
= context
.getEditor().getDocument();
84 document
.replaceString(context
.getStartOffset(), context
.getTailOffset(), ";");
85 final InsertionContext qualifierContext
= CompletionUtil
.emulateInsertion(context
, context
.getStartOffset(), myQualifier
, (char)0);
87 if (shouldParenthesizeQualifier(qualifierContext
.getFile(), context
.getStartOffset(), qualifierContext
.getTailOffset())) {
88 final String space
= CodeStyleSettingsManager
.getSettings(qualifierContext
.getProject()).SPACE_WITHIN_PARENTHESES ?
" " : "";
89 document
.insertString(context
.getStartOffset(), "(" + space
);
90 document
.insertString(qualifierContext
.getTailOffset(), space
+ ")");
93 final char atTail
= document
.getCharsSequence().charAt(context
.getTailOffset() - 1);
94 assert atTail
== ';' : atTail
;
95 document
.replaceString(context
.getTailOffset() - 1, context
.getTailOffset(), ".");
97 CompletionUtil
.emulateInsertion(getDelegate(), context
.getTailOffset(), context
);
100 private static boolean shouldParenthesizeQualifier(final PsiFile file
, final int startOffset
, final int endOffset
) {
101 PsiElement element
= file
.findElementAt(startOffset
);
102 if (element
== null) {
106 PsiElement last
= element
;
107 while (element
!= null && element
.getTextRange().getStartOffset() >= startOffset
&& element
.getTextRange().getEndOffset() <= endOffset
) {
109 element
= element
.getParent();
111 PsiExpression expr
= PsiTreeUtil
.getParentOfType(last
, PsiExpression
.class, false);
112 if (expr
== null || expr
.getTextRange().getEndOffset() > endOffset
) {
116 if (expr
instanceof PsiReferenceExpression
|| expr
instanceof PsiMethodCallExpression
) {
124 private LookupElement
getComparableQualifier() {
125 final CastingLookupElementDecorator casting
= myQualifier
.as(CastingLookupElementDecorator
.class);
126 return casting
== null ? myQualifier
: casting
.getDelegate();
130 public boolean equals(Object o
) {
131 if (this == o
) return true;
132 if (o
== null || getClass() != o
.getClass()) return false;
133 if (!super.equals(o
)) return false;
135 return getComparableQualifier().equals(((JavaChainLookupElement
)o
).getComparableQualifier());
139 public int hashCode() {
140 return 31 * super.hashCode() + getComparableQualifier().hashCode();
143 public PsiType
getType() {
144 final Object object
= getObject();
145 if (object
instanceof PsiMember
) {
146 return JavaCompletionUtil
.getQualifiedMemberReferenceType(JavaCompletionUtil
.getLookupElementType(myQualifier
), (PsiMember
)object
);
148 return ((PsiVariable
) object
).getType();
151 public static LookupElement
chainElements(LookupElement qualifier
, LookupElement main
) {
152 return new JavaChainLookupElement(qualifier
, main
);