1 19 20 package org.netbeans.modules.web.core.syntax.completion; 21 22 import java.net.URL ; 23 import java.util.List ; 24 import javax.swing.Action ; 25 import javax.swing.text.Document ; 26 import javax.swing.text.JTextComponent ; 27 import org.netbeans.api.editor.completion.Completion; 28 import org.netbeans.api.html.lexer.HTMLTokenId; 29 import org.netbeans.api.lexer.Token; 30 import org.netbeans.api.lexer.TokenHierarchy; 31 import org.netbeans.api.lexer.TokenSequence; 32 import org.netbeans.editor.BaseDocument; 33 import org.netbeans.editor.Utilities; 34 import org.netbeans.editor.ext.CompletionQuery; 35 import org.netbeans.editor.ext.ExtSyntaxSupport; 36 import org.netbeans.editor.ext.html.HTMLCompletionQuery; 37 import org.netbeans.editor.ext.html.HTMLCompletionQuery.HTMLResultItem; 38 import org.netbeans.modules.web.core.syntax.JspSyntaxSupport; 39 import org.netbeans.spi.editor.completion.CompletionDocumentation; 40 import org.netbeans.spi.editor.completion.CompletionResultSet; 41 import org.netbeans.spi.editor.completion.CompletionProvider; 42 import org.netbeans.spi.editor.completion.CompletionTask; 43 import org.netbeans.spi.editor.completion.support.AsyncCompletionQuery; 44 import org.netbeans.spi.editor.completion.support.AsyncCompletionTask; 45 46 47 51 public class JspCompletionProvider implements CompletionProvider { 52 53 54 public JspCompletionProvider() { 55 } 56 57 public int getAutoQueryTypes(JTextComponent component, String typedText) { 58 int type = ((JspSyntaxSupport)Utilities.getDocument(component).getSyntaxSupport()).checkCompletion(component, typedText, false); 59 if(type == ExtSyntaxSupport.COMPLETION_POPUP) { 60 return COMPLETION_QUERY_TYPE + DOCUMENTATION_QUERY_TYPE; 61 } else return 0; 62 } 63 64 public CompletionTask createTask(int type, JTextComponent component) { 65 if ((type & COMPLETION_QUERY_TYPE & COMPLETION_ALL_QUERY_TYPE) != 0) { 66 return new AsyncCompletionTask(new Query(component.getCaret().getDot()), component); 67 } else if (type == DOCUMENTATION_QUERY_TYPE) { 68 return new AsyncCompletionTask(new DocQuery(null), component); 69 } 70 return null; 71 } 72 73 static final class Query extends AbstractQuery { 74 75 private JTextComponent component; 76 77 private int creationCaretOffset; 78 79 Query(int caretOffset) { 80 this.creationCaretOffset = caretOffset; 81 } 82 83 protected void prepareQuery(JTextComponent component) { 84 this.component = component; 85 } 86 87 protected void doQuery(CompletionResultSet resultSet, Document doc, int caretOffset) { 88 CompletionQuery.Result res = queryImpl(component, caretOffset); 89 if(res != null) { 90 List results = res.getData(); 91 resultSet.addAllItems(results); 92 resultSet.setTitle(res.getTitle()); 93 resultSet.setAnchorOffset(((JspCompletionQuery.SubstituteOffsetProvider)res).getSubstituteOffset()); 94 } 95 } 96 } 97 98 static class DocQuery extends AbstractQuery { 99 100 private JTextComponent component; 101 private ResultItem item; 102 103 public DocQuery(ResultItem item) { 104 this.item = item; 105 } 106 107 protected void prepareQuery(JTextComponent component) { 108 this.component = component; 109 } 110 111 protected void doQuery(CompletionResultSet resultSet, Document doc, int caretOffset) { 112 CompletionQuery.Result res = queryImpl(component, caretOffset); 113 if(item == null) { 114 if(res != null) { 115 List result = res.getData(); 116 if(result != null && result.size() > 0) { 117 Object resultObj = result.get(0); 118 if(resultObj instanceof ResultItem) { 119 item = (ResultItem)resultObj; 120 } else if(resultObj instanceof HTMLResultItem) { 121 HTMLResultItem htmlItem = (HTMLResultItem)resultObj; 122 if(htmlItem != null && htmlItem.getHelpID() != null) { 123 resultSet.setDocumentation(new HTMLCompletionQuery.DocItem(htmlItem)); 124 resultSet.setTitle(res.getTitle()); 125 return ; 126 } 127 } 128 } 129 } 130 } 131 if(item != null && 132 !(item instanceof JspCompletionItem.ELItem) && 133 (item.getHelp() != null || item.getHelpURL() != null)) { 134 resultSet.setDocumentation(new DocItem(item)); 135 if(res != null) { 136 resultSet.setTitle(res.getTitle()); 137 } 138 } 139 } 140 } 141 142 static class DocItem implements CompletionDocumentation { 143 private ResultItem ri; 144 145 public DocItem(ResultItem ri) { 146 this.ri = ri; 147 } 148 149 public String getText() { 150 return ri.getHelp(); 151 } 152 153 public URL getURL() { 154 return ri.getHelpURL(); 155 } 156 157 public CompletionDocumentation resolveLink(String link) { 158 return null; 160 } 161 162 public Action getGotoSourceAction() { 163 return null; 164 } 165 } 166 167 static CompletionQuery.Result queryImpl(JTextComponent component, int offset) { 168 Class kitClass = Utilities.getKitClass(component); 169 if (kitClass != null) { 170 JspSyntaxSupport support = (JspSyntaxSupport)Utilities.getSyntaxSupport(component); 171 return new JspCompletionQuery(HTMLCompletionQuery.getDefault()).query(component, offset, support); 172 } else { 173 return null; 174 } 175 } 176 177 private static abstract class AbstractQuery extends AsyncCompletionQuery { 178 179 protected void preQueryUpdate(JTextComponent component) { 180 int caretOffset = component.getCaretPosition(); 181 Document doc = component.getDocument(); 182 checkHideCompletion((BaseDocument)doc, caretOffset); 183 } 184 185 protected void query(CompletionResultSet resultSet, Document doc, int caretOffset) { 186 if(doc != null) { 188 checkHideCompletion((BaseDocument)doc, caretOffset); 189 } 190 doQuery(resultSet, doc, caretOffset); 191 resultSet.finish(); 192 } 193 194 abstract void doQuery(CompletionResultSet resultSet, Document doc, int caretOffset); 195 196 } 197 198 private static void checkHideCompletion(BaseDocument doc, int caretOffset) { 199 int adjustedOffset = caretOffset == 0 ? 0 : caretOffset - 1; 203 doc.readLock(); 204 try { 205 TokenHierarchy tokenHierarchy = TokenHierarchy.get(doc); 206 TokenSequence tokenSequence = JspSyntaxSupport.tokenSequence(tokenHierarchy, HTMLTokenId.language(), adjustedOffset); 207 if(tokenSequence != null) { 208 tokenSequence.move(adjustedOffset); 209 if (!tokenSequence.moveNext() && !tokenSequence.movePrevious()) { 210 return; } 212 213 Token tokenItem = tokenSequence.token(); 214 if(tokenItem.id() == HTMLTokenId.TEXT && !tokenItem.text().toString().startsWith("<") && !tokenItem.text().toString().startsWith("&")) { 215 hideCompletion(); 216 } 217 } 218 } finally { 219 doc.readUnlock(); 220 } 221 } 222 223 private static void hideCompletion() { 224 Completion.get().hideCompletion(); 225 Completion.get().hideDocumentation(); 226 } 227 228 } 229 | Popular Tags |