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.
18 * Created by IntelliJ IDEA.
19 * User: Maxim.Mossienko
23 package com
.intellij
.codeInsight
.completion
;
25 import com
.intellij
.psi
.xml
.*;
26 import com
.intellij
.psi
.filters
.*;
27 import com
.intellij
.psi
.filters
.position
.XmlTokenTypeFilter
;
28 import com
.intellij
.psi
.filters
.position
.LeftNeighbour
;
29 import com
.intellij
.psi
.PsiElement
;
30 import com
.intellij
.psi
.PsiDocumentManager
;
31 import com
.intellij
.psi
.PsiNamedElement
;
32 import com
.intellij
.psi
.search
.PsiElementProcessor
;
33 import com
.intellij
.psi
.util
.PsiTreeUtil
;
34 import com
.intellij
.codeInsight
.lookup
.LookupElement
;
35 import com
.intellij
.codeInsight
.lookup
.MutableLookupElement
;
36 import com
.intellij
.codeInsight
.TailType
;
37 import com
.intellij
.xml
.util
.XmlUtil
;
38 import com
.intellij
.util
.ArrayUtil
;
43 * Created by IntelliJ IDEA.
47 * To change this template use Options | File Templates.
49 public class DtdCompletionData
extends CompletionData
{
50 public DtdCompletionData() {
51 final LeftNeighbour entityFilter
= new LeftNeighbour(new XmlTextFilter("%"));
53 declareFinalScope(XmlToken
.class);
56 final CompletionVariant variant
= new CompletionVariant(
60 new XmlTextFilter(new String
[] {"#", "!", "(", ",", "|", "["}),
61 new XmlTokenTypeFilter(XmlTokenType
.XML_NAME
)
64 new NotFilter(entityFilter
)
67 variant
.includeScopeClass(XmlToken
.class, true);
68 variant
.addCompletion(
70 "#PCDATA","#IMPLIED","#REQUIRED","#FIXED","<!ATTLIST", "<!ELEMENT", "<!NOTATION", "INCLUDE", "IGNORE", "CDATA", "ID" , "IDREF", "EMPTY", "ANY",
71 "IDREFS", "ENTITIES", "ENTITY", "<!ENTITY", "NMTOKEN", "NMTOKENS", "SYSTEM", "PUBLIC"
75 variant
.setInsertHandler(new MyInsertHandler());
76 registerVariant(variant
);
80 final CompletionVariant variant
= new CompletionVariant(entityFilter
);
81 variant
.includeScopeClass(XmlToken
.class, true);
82 variant
.addCompletion(new DtdEntityGetter());
83 variant
.setInsertHandler(new XmlCompletionData
.EntityRefInsertHandler());
84 registerVariant(variant
);
88 public String
findPrefix(PsiElement insertedElement
, int offset
) {
89 final PsiElement prevLeaf
= PsiTreeUtil
.prevLeaf(insertedElement
);
90 final PsiElement prevPrevLeaf
= prevLeaf
!= null ? PsiTreeUtil
.prevLeaf(prevLeaf
):null;
91 String prefix
= super.findPrefix(insertedElement
, offset
);
93 if (prevLeaf
!= null) {
94 final String prevLeafText
= prevLeaf
.getText();
96 if("#".equals(prevLeafText
)) {
97 prefix
= "#" + prefix
;
98 } else if ("!".equals(prevLeafText
) && prevPrevLeaf
!= null && "<".equals(prevPrevLeaf
.getText())) {
99 prefix
= "<!" + prefix
;
106 static class DtdEntityGetter
implements ContextGetter
{
108 public Object
[] get(final PsiElement context
, CompletionContext completionContext
) {
109 final List
<String
> results
= new LinkedList
<String
>();
111 final PsiElementProcessor processor
= new PsiElementProcessor() {
112 public boolean execute(final PsiElement element
) {
113 if (element
instanceof XmlEntityDecl
) {
114 final XmlEntityDecl xmlEntityDecl
= (XmlEntityDecl
)element
;
115 if (xmlEntityDecl
.isInternalReference()) {
116 results
.add(xmlEntityDecl
.getName());
123 XmlUtil
.processXmlElements((XmlFile
)context
.getContainingFile().getOriginalFile(), processor
, true);
124 return ArrayUtil
.toObjectArray(results
);
127 static class MyInsertHandler
extends BasicInsertHandler
{
129 public void handleInsert(InsertionContext context
, LookupElement item
) {
130 super.handleInsert(context
, item
);
132 if (((MutableLookupElement
)item
).getObject().toString().startsWith("<!")) {
133 PsiDocumentManager
.getInstance(context
.getProject()).commitAllDocuments();
135 int caretOffset
= context
.getEditor().getCaretModel().getOffset();
136 PsiElement tag
= PsiTreeUtil
.getParentOfType(context
.getFile().findElementAt(caretOffset
), PsiNamedElement
.class);
139 context
.getEditor().getDocument().insertString(caretOffset
, " >");
140 context
.getEditor().getCaretModel().moveToOffset(caretOffset
+ 1);