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
.hint
.api
.impls
;
18 import com
.intellij
.codeInsight
.CodeInsightBundle
;
19 import com
.intellij
.codeInsight
.daemon
.DaemonCodeAnalyzer
;
20 import com
.intellij
.codeInsight
.lookup
.LookupElement
;
21 import com
.intellij
.codeInsight
.lookup
.MutableLookupElement
;
22 import com
.intellij
.openapi
.util
.TextRange
;
23 import com
.intellij
.psi
.PsiElement
;
24 import com
.intellij
.psi
.PsiFile
;
25 import com
.intellij
.psi
.xml
.XmlFile
;
26 import com
.intellij
.psi
.xml
.XmlTag
;
27 import com
.intellij
.psi
.xml
.XmlToken
;
28 import com
.intellij
.psi
.xml
.XmlTokenType
;
29 import com
.intellij
.xml
.XmlAttributeDescriptor
;
30 import com
.intellij
.xml
.XmlElementDescriptor
;
31 import com
.intellij
.lang
.parameterInfo
.*;
32 import org
.jetbrains
.annotations
.NotNull
;
33 import org
.jetbrains
.annotations
.Nullable
;
35 import java
.util
.Arrays
;
36 import java
.util
.Comparator
;
39 * Created by IntelliJ IDEA.
40 * User: Maxim.Mossienko
43 * To change this template use File | Settings | File Templates.
45 public class XmlParameterInfoHandler
implements ParameterInfoHandler
<XmlTag
,XmlElementDescriptor
> {
46 private static final Comparator
<XmlAttributeDescriptor
> COMPARATOR
= new Comparator
<XmlAttributeDescriptor
>() {
47 public int compare(final XmlAttributeDescriptor o1
, final XmlAttributeDescriptor o2
) {
48 return o1
.getName().compareTo(o2
.getName());
52 public Object
[] getParametersForLookup(LookupElement item
, ParameterInfoContext context
) {
53 if (!(item
instanceof MutableLookupElement
)) return null;
54 final Object lookupItem
= ((MutableLookupElement
)item
).getObject();
55 if (lookupItem
instanceof XmlElementDescriptor
) return new Object
[]{lookupItem
};
59 public Object
[] getParametersForDocumentation(final XmlElementDescriptor p
, final ParameterInfoContext context
) {
60 return getSortedDescriptors(p
);
63 private static XmlAttributeDescriptor
[] getSortedDescriptors(final XmlElementDescriptor p
) {
64 final XmlAttributeDescriptor
[] xmlAttributeDescriptors
= p
.getAttributesDescriptors(null);
65 Arrays
.sort(xmlAttributeDescriptors
, COMPARATOR
);
66 return xmlAttributeDescriptors
;
69 public boolean couldShowInLookup() {
73 public XmlTag
findElementForParameterInfo(final CreateParameterInfoContext context
) {
74 final XmlTag tag
= findXmlTag(context
.getFile(), context
.getOffset());
75 final XmlElementDescriptor descriptor
= tag
!= null ? tag
.getDescriptor() : null;
77 if (descriptor
== null) {
78 DaemonCodeAnalyzer
.getInstance(context
.getProject()).updateVisibleHighlighters(context
.getEditor());
82 context
.setItemsToShow(new Object
[] {descriptor
});
86 public void showParameterInfo(final @NotNull XmlTag element
, final CreateParameterInfoContext context
) {
87 context
.showHint(element
, element
.getTextRange().getStartOffset() + 1, this);
90 public XmlTag
findElementForUpdatingParameterInfo(final UpdateParameterInfoContext context
) {
91 final XmlTag tag
= findXmlTag(context
.getFile(), context
.getOffset());
93 final PsiElement currentXmlTag
= context
.getParameterOwner();
94 if (currentXmlTag
== null || currentXmlTag
== tag
) return tag
;
100 public void updateParameterInfo(@NotNull final XmlTag o
, final UpdateParameterInfoContext context
) {
101 if (context
.getParameterOwner() == null || o
.equals(context
.getParameterOwner())) {
102 context
.setParameterOwner( o
);
104 context
.removeHint();
108 public String
getParameterCloseChars() {
112 public boolean tracksParameterIndex() {
117 private static XmlTag
findXmlTag(PsiFile file
, int offset
){
118 if (!(file
instanceof XmlFile
)) return null;
120 PsiElement element
= file
.findElementAt(offset
);
121 if (element
== null) return null;
122 element
= element
.getParent();
124 while (element
!= null) {
125 if (element
instanceof XmlTag
) {
126 XmlTag tag
= (XmlTag
)element
;
128 final PsiElement
[] children
= tag
.getChildren();
130 if (offset
<= children
[0].getTextRange().getStartOffset()) return null;
132 for (PsiElement child
: children
) {
133 final TextRange range
= child
.getTextRange();
134 if (range
.getStartOffset() <= offset
&& range
.getEndOffset() > offset
) return tag
;
136 if (child
instanceof XmlToken
) {
137 XmlToken token
= (XmlToken
)child
;
138 if (token
.getTokenType() == XmlTokenType
.XML_TAG_END
) return null;
145 element
= element
.getParent();
151 public void updateUI(XmlElementDescriptor o
, ParameterInfoUIContext context
) {
152 updateElementDescriptor(o
, context
);
155 private static void updateElementDescriptor(XmlElementDescriptor descriptor
, ParameterInfoUIContext context
) {
156 final XmlAttributeDescriptor
[] attributes
= descriptor
!= null ?
getSortedDescriptors(descriptor
) : XmlAttributeDescriptor
.EMPTY
;
158 StringBuffer buffer
= new StringBuffer();
159 int highlightStartOffset
= -1;
160 int highlightEndOffset
= -1;
162 if (attributes
.length
== 0) {
163 buffer
.append(CodeInsightBundle
.message("xml.tag.info.no.attributes"));
166 StringBuffer text1
= new StringBuffer(" ");
167 StringBuffer text2
= new StringBuffer(" ");
168 StringBuffer text3
= new StringBuffer(" ");
170 final XmlTag parameterOwner
= (XmlTag
)context
.getParameterOwner();
172 for (XmlAttributeDescriptor attribute
: attributes
) {
173 if (parameterOwner
!= null && parameterOwner
.getAttributeValue(attribute
.getName()) != null) {
174 if (!(text1
.toString().equals(" "))) {
177 text1
.append(attribute
.getName());
179 else if (attribute
.isRequired()) {
180 if (!(text2
.toString().equals(" "))) {
183 text2
.append(attribute
.getName());
186 if (!(text3
.toString().equals(" "))) {
189 text3
.append(attribute
.getName());
193 if (!text1
.toString().equals(" ") && !text2
.toString().equals(" ")) {
197 if (!text2
.toString().equals(" ") && !text3
.toString().equals(" ")) {
201 if (!text1
.toString().equals(" ") && !text3
.toString().equals(" ") && text2
.toString().equals(" ")) {
205 buffer
.append(text1
);
206 highlightStartOffset
= buffer
.length();
207 buffer
.append(text2
);
208 highlightEndOffset
= buffer
.length();
209 buffer
.append(text3
);
212 context
.setupUIComponentPresentation(buffer
.toString(), highlightStartOffset
, highlightEndOffset
, false,
213 false, true, context
.getDefaultParameterColor());