1 19 20 package org.netbeans.modules.web.core.syntax.completion; 21 22 import java.util.*; 23 import javax.swing.text.JTextComponent ; 24 import javax.swing.text.BadLocationException ; 25 import javax.servlet.jsp.tagext.TagInfo ; 26 import javax.servlet.jsp.tagext.TagAttributeInfo ; 27 import org.netbeans.editor.*; 28 import org.netbeans.editor.ext.*; 29 import org.netbeans.editor.ext.html.HTMLCompletionQuery; 30 import org.netbeans.modules.editor.NbEditorUtilities; 31 import org.netbeans.modules.web.core.syntax.deprecated.JspTagTokenContext; 32 import org.openide.loaders.DataObject; 33 import org.openide.util.NbBundle; 34 import org.netbeans.modules.web.core.syntax.*; 35 import org.netbeans.modules.web.jsps.parserapi.PageInfo.BeanData; 36 import org.openide.loaders.DataObject; 37 import org.netbeans.spi.editor.completion.CompletionItem; 38 39 40 46 47 public class JspCompletionQuery implements CompletionQuery { 48 49 52 private static final Set stdXMLEntities = new TreeSet(); 53 54 static{ 55 stdXMLEntities.add("<"); 56 stdXMLEntities.add(">"); 57 stdXMLEntities.add("'"); 58 stdXMLEntities.add("""); 59 stdXMLEntities.add("&"); 60 } 61 62 protected CompletionQuery contentQuery; 63 64 public JspCompletionQuery(CompletionQuery contentQuery) { 65 super(); 66 this.contentQuery = contentQuery; 67 } 68 69 79 public CompletionQuery.Result query(JTextComponent component, int offset, SyntaxSupport support) { 80 BaseDocument doc = (BaseDocument)component.getDocument(); 81 JspSyntaxSupport sup = (JspSyntaxSupport)support.get(JspSyntaxSupport.class); 82 83 try { 84 SyntaxElement elem = sup.getElementChain( offset ); 85 if (elem == null) 86 return null; 88 89 CompletionData jspData; 90 switch (elem.getCompletionContext()) { 91 case JspSyntaxSupport.TAG_COMPLETION_CONTEXT : 93 return queryJspTag(component, offset, sup, 94 (SyntaxElement.Tag)elem); 95 96 case JspSyntaxSupport.ENDTAG_COMPLETION_CONTEXT : 98 jspData = queryJspEndTag(offset, sup, 99 (SyntaxElement.EndTag)elem, doc); 100 return result(component, offset, jspData); 101 102 case JspSyntaxSupport.SCRIPTINGL_COMPLETION_CONTEXT: 104 return queryJspDirectiveInScriptlet(component, offset, sup, elem, doc); 105 106 case JspSyntaxSupport.DIRECTIVE_COMPLETION_CONTEXT : 108 return queryJspDirective(component, offset, sup, 109 (SyntaxElement.Directive)elem, doc); 110 111 case JspSyntaxSupport.EL_COMPLETION_CONTEXT: 113 return queryEL(component, offset, sup, elem, doc); 114 115 case JspSyntaxSupport.CONTENTL_COMPLETION_CONTEXT : 117 CompletionQuery.Result contentLResult = (contentQuery == null) ? 119 null : 120 contentQuery.query(component, offset, support); 121 122 jspData = queryJspTagInContent(offset, sup, doc); 124 125 CompletionQuery.Result jspDirec = queryJspDirectiveInContent(component, offset, sup, doc); 127 128 if(jspData.completionItems.isEmpty() && jspDirec.getData().isEmpty() && (contentLResult == null || contentLResult.getData().isEmpty())) 130 return null; 131 132 CompletionQuery.Result jspRes = result(component, offset, jspData); 133 134 ArrayList all = new ArrayList(); 136 all.addAll(jspDirec.getData()); 137 all.addAll(jspRes.getData()); 138 if(contentLResult != null){ 139 DataObject dobj = NbEditorUtilities.getDataObject(doc); 140 141 if(dobj != null && JspUtils.getJSPColoringData(doc, dobj.getPrimaryFile()).isXMLSyntax()){ 142 filterNonStandardXMLEntities(all, contentLResult.getData()); 143 } else{ 144 all.addAll(contentLResult.getData()); 145 } 146 } 147 148 int htmlAnchorOffset = contentLResult == null || contentLResult.getData().isEmpty() ? - 1 : ((HTMLCompletionQuery.HTMLCompletionResult)contentLResult).getSubstituteOffset(); 149 150 CompletionQuery.Result result = new JspCompletionResult(component, 151 NbBundle.getMessage(JSPKit.class, "CTL_JSP_Completion_Title"), all, 152 offset, jspData.removeLength, htmlAnchorOffset); 153 154 return result; 155 } 156 157 } catch (BadLocationException e) { 158 e.printStackTrace(); 159 } 160 return null; 161 } 162 163 166 private void filterNonStandardXMLEntities(List completionItemsRep, List htmlSuggestions) { 167 Iterator it = htmlSuggestions.iterator(); 168 169 while (it.hasNext()){ 170 CompletionQuery.ResultItem item = (CompletionQuery.ResultItem) it.next(); 171 172 String itemText = item.getItemText(); 173 boolean filterOut = false; 174 175 if (itemText.startsWith("&") && itemText.endsWith(";")){ 177 if (!stdXMLEntities.contains(itemText)){ 179 filterOut = true; 180 } 181 } 182 183 if (!filterOut){ 184 completionItemsRep.add(item); 185 } 186 } 187 } 188 189 190 private void setResultItemsOffset(List items, int removeLength, int ccoffset) { 191 Iterator i = items.iterator(); 192 while(i.hasNext()) { 193 Object obj = i.next(); 194 if(obj instanceof org.netbeans.modules.web.core.syntax.completion.ResultItem) 195 ((org.netbeans.modules.web.core.syntax.completion.ResultItem)obj).setSubstituteOffset(ccoffset - removeLength); 196 } 197 } 198 199 private void setResultItemsOffset(CompletionData cd, int ccoffset) { 200 setResultItemsOffset(cd.completionItems, cd.removeLength, ccoffset); 201 } 202 203 210 protected CompletionQuery.Result queryJspTag(JTextComponent component, int offset, 211 JspSyntaxSupport sup, SyntaxElement.Tag elem) throws BadLocationException { 212 BaseDocument doc = (BaseDocument)component.getDocument(); 213 List compItems = new ArrayList(); 215 int removeLength = 0; 216 217 TokenItem item = sup.getItemAtOrBefore(offset); 218 219 if (item == null) { 220 return result(component, offset, new CompletionData(compItems, 0)); 221 } 222 223 TokenID id = item.getTokenID(); 224 String tokenPart = item.getImage().substring(0, offset - item.getOffset()); 225 String token = item.getImage().trim(); 226 227 if (id == JspTagTokenContext.SYMBOL) { 229 if (tokenPart.equals("<")) { removeLength = 0; 232 addTagPrefixItems(sup, compItems, sup.getTagPrefixes("")); } 234 if (tokenPart.endsWith("\"")) { String attrName = findAttributeForValue(sup, item); 237 if (attrName != null) { 238 AttributeValueSupport attSup = 239 AttributeValueSupport.getSupport(true, elem.getName(), attrName); 240 if (attSup != null) { 241 return attSup.getResult(component, offset, sup, elem, ""); } 243 } 244 } 245 if(tokenPart.endsWith(">") && !tokenPart.endsWith("/>")) { 246 compItems = sup.getAutocompletedEndTag(offset); 247 } 248 249 250 } 251 252 if (id == JspTagTokenContext.TAG 254 || id == JspTagTokenContext.WHITESPACE 255 || id == JspTagTokenContext.EOL) { 256 if (isBlank(tokenPart.charAt(tokenPart.length() - 1)) 258 || tokenPart.equals("\n")) { 259 removeLength = 0; 261 addAttributeItems(sup, compItems, elem, sup.getTagAttributes(elem.getName(), ""), null); } else { 263 int colonIndex = tokenPart.indexOf(":"); if (colonIndex == -1) { 265 removeLength = tokenPart.length(); 266 addTagPrefixItems(sup, compItems, sup.getTagPrefixes(tokenPart)); 267 } else { 268 String prefix = tokenPart.substring(0, colonIndex); 269 removeLength = tokenPart.length(); 270 addTagPrefixItems(sup, compItems, prefix, sup.getTags(tokenPart), elem); 271 } 272 } 273 } 274 275 if (id == JspTagTokenContext.ATTRIBUTE) { 277 if (isBlank(tokenPart.charAt(tokenPart.length() - 1))) { 279 removeLength = 0; 281 addAttributeItems(sup, compItems, elem, sup.getTagAttributes(elem.getName(), ""), null); } else { 283 removeLength = tokenPart.length(); 284 addAttributeItems(sup, compItems, elem, sup.getTagAttributes(elem.getName(), tokenPart), token); 285 } 286 } 287 288 if (id == JspTagTokenContext.ATTR_VALUE) { 290 String valuePart = tokenPart.trim(); 292 if(valuePart.length() == 0) return result(component, offset, new CompletionData(compItems, 0)); 294 295 item = item.getPrevious(); 296 while ((item != null) && (item.getTokenID() == JspTagTokenContext.ATTR_VALUE)) { 297 valuePart = item.getImage() + valuePart; 298 item = item.getPrevious(); 299 } 300 valuePart = valuePart.substring(1); 302 removeLength = valuePart.length(); 303 String attrName = findAttributeForValue(sup, item); 304 if (attrName != null) { 305 AttributeValueSupport attSup = 306 AttributeValueSupport.getSupport(true, elem.getName(), attrName); 307 if (attSup != null) { 308 CompletionQuery.Result result = attSup.getResult(component, offset, sup, elem, valuePart); 309 if(!(attSup instanceof AttrSupports.FilenameSupport)) 310 setResultItemsOffset(result.getData(), valuePart.length(), offset); 311 return result; 312 } 313 } 314 315 } 316 317 return result(component, offset, new CompletionData(compItems, removeLength)); 318 } 319 320 326 protected CompletionData queryJspEndTag(int offset, JspSyntaxSupport sup, 327 SyntaxElement.EndTag elem, BaseDocument doc) throws BadLocationException { 328 List compItems = new ArrayList(); 330 int removeLength = 0; 331 332 TokenItem item = sup.getItemAtOrBefore(offset); 333 if (item == null) { 334 return new CompletionData(compItems, 0); 335 } 336 337 TokenID id = item.getTokenID(); 338 String tokenPart = item.getImage().substring(0, offset - item.getOffset()); 339 340 removeLength = tokenPart.length(); 341 return new CompletionData(sup.getPossibleEndTags(offset, tokenPart), removeLength); 342 } 343 344 345 protected CompletionQuery.Result queryEL(JTextComponent component, int offset, JspSyntaxSupport sup, 346 SyntaxElement elem, BaseDocument doc) throws BadLocationException { 347 ELExpression elExpr = new ELExpression(sup); 348 ArrayList complItems = new ArrayList(); 349 350 switch (elExpr.parse(offset)){ 351 case ELExpression.EL_START: 352 for (ELImplicitObjects.ELImplicitObject implOb : ELImplicitObjects.getELImplicitObjects(elExpr.getReplace())) { 354 complItems.add(new JspCompletionItem.ELImplicitObject(implOb.getName(), implOb.getType())); 355 } 356 357 BeanData[] beans = sup.getBeanData(); 359 if (beans != null){ 360 for (int i = 0; i < beans.length; i++) { 361 if (beans[i].getId().startsWith(elExpr.getReplace())) 362 complItems.add(new JspCompletionItem.ELBean(beans[i].getId(), beans[i].getClassName())); 363 } 364 } 365 List functions = ELFunctions.getFunctions(sup, elExpr.getReplace()); 367 Iterator iter = functions.iterator(); 368 while (iter.hasNext()) { 369 ELFunctions.Function fun = (ELFunctions.Function) iter.next(); 370 complItems.add(new JspCompletionItem.ELFunction( 371 fun.getPrefix(), 372 fun.getName(), 373 fun.getReturnType(), 374 fun.getParameters())); 375 } 376 break; 377 case ELExpression.EL_BEAN: 378 case ELExpression.EL_IMPLICIT: 379 380 List<CompletionItem> items = elExpr.getPropertyCompletionItems(elExpr.getObjectClass()); 381 complItems.addAll(items); 382 383 break; 384 } 385 386 return result(component, offset, new CompletionData(complItems, elExpr.getReplace().length())); 387 } 388 389 390 protected CompletionQuery.Result queryJspDirectiveInScriptlet(JTextComponent component, int offset, JspSyntaxSupport sup, 391 SyntaxElement elem, BaseDocument doc) throws BadLocationException { 392 393 List compItems = new ArrayList(); 394 395 TokenItem item = sup.getItemAtOrBefore(offset); 396 if (item == null) { 397 return result(component, offset, new CompletionData(compItems, 0)); 398 } 399 400 TokenID id = item.getTokenID(); 401 String tokenPart = item.getImage().substring(0, offset - item.getOffset()); 402 403 if(id == JspTagTokenContext.SYMBOL2 && tokenPart.equals("<%")) 404 addDirectiveItems(sup, compItems, sup.getDirectives("")); 406 return result(component, offset, new CompletionData(compItems, 1 )); 407 } 408 409 410 417 protected CompletionQuery.Result queryJspDirective(JTextComponent component, int offset, JspSyntaxSupport sup, 418 SyntaxElement.Directive elem, BaseDocument doc) throws BadLocationException { 419 List compItems = new ArrayList(); 421 int removeLength = 0; 422 423 TokenItem item = sup.getItemAtOrBefore(offset); 424 if (item == null) { 425 return result(component, offset, new CompletionData(compItems, 0)); 426 } 427 428 TokenID id = item.getTokenID(); 429 String tokenPart = item.getImage().substring(0, offset - item.getOffset()); 430 String token = item.getImage().trim(); 431 432 if (id.getNumericID() == JspTagTokenContext.SYMBOL_ID) { 434 if (tokenPart.startsWith("<")) { removeLength = tokenPart.length() - 1; 437 addDirectiveItems(sup, compItems, sup.getDirectives("")); } 439 if (tokenPart.endsWith("\"")) { String attrName = findAttributeForValue(sup, item); 442 if (attrName != null) { 443 AttributeValueSupport attSup = 444 AttributeValueSupport.getSupport(false, elem.getName(), attrName); 445 if (attSup != null) { 446 return attSup.getResult(component, offset, sup, elem, ""); } 448 } 449 } 450 } 451 452 if (id.getNumericID() == JspTagTokenContext.TAG_ID 454 || id.getNumericID() == JspTagTokenContext.WHITESPACE_ID 455 || id.getNumericID() == JspTagTokenContext.EOL_ID) { 456 if (isBlank(tokenPart.charAt(tokenPart.length() - 1)) 458 || tokenPart.equals("\n")) { 459 TokenItem prevItem = item.getPrevious(); 460 TokenID prevId = prevItem.getTokenID(); 461 String prevToken = prevItem.getImage().trim(); 462 if (prevId.getNumericID() == JspTagTokenContext.TAG_ID 463 || prevId.getNumericID() == JspTagTokenContext.ATTR_VALUE_ID 464 || prevId.getNumericID() == JspTagTokenContext.WHITESPACE_ID 465 || prevId.getNumericID() == JspTagTokenContext.EOL_ID) { 466 removeLength = 0; 468 addAttributeItems(sup, compItems, elem, sup.getDirectiveAttributes(elem.getName(), ""), null); } else if (prevId.getNumericID() == JspTagTokenContext.SYMBOL_ID && prevToken.equals("<%@")) { removeLength = tokenPart.length() + 2; 472 addDirectiveItems(sup, compItems, sup.getDirectives("")); } 474 } else { 475 boolean add = true; 476 int whitespaceLength = 0; 478 TokenItem prevItem = item.getPrevious(); 479 TokenID prevId = prevItem.getTokenID(); 480 if(prevId.getNumericID() == JspTagTokenContext.TAG_ID && "".equals(prevItem.getImage().trim())) whitespaceLength = prevItem.getImage().length(); 483 484 485 List list = sup.getDirectives(tokenPart); 486 if (list.size() == 1){ 487 Object directive = list.get(0); 488 if (directive instanceof TagInfo && ((TagInfo )directive).getTagName().equalsIgnoreCase(tokenPart)) 490 add = false; 491 } 492 if (add){ 493 removeLength = whitespaceLength + tokenPart.length() + 2; 494 addDirectiveItems(sup, compItems, list); 495 } 496 } 497 } 498 499 if (id.getNumericID() == JspTagTokenContext.ATTRIBUTE_ID) { 501 if (isBlank(tokenPart.charAt(tokenPart.length() - 1))) { 503 removeLength = 0; 505 addAttributeItems(sup, compItems, elem, sup.getDirectiveAttributes(elem.getName(), ""), null); } else { 507 removeLength = tokenPart.length(); 508 addAttributeItems(sup, compItems, elem, sup.getDirectiveAttributes(elem.getName(), tokenPart), token); 509 } 510 } 511 512 if (id.getNumericID() == JspTagTokenContext.ATTR_VALUE_ID) { 514 String valuePart = tokenPart; 516 item = item.getPrevious(); 517 while ((item != null) && (item.getTokenID().getNumericID() == JspTagTokenContext.ATTR_VALUE_ID)) { 518 valuePart = item.getImage() + valuePart; 519 item = item.getPrevious(); 520 } 521 valuePart = valuePart.substring(1); 523 removeLength = valuePart.length(); 524 String attrName = findAttributeForValue(sup, item); 525 if (attrName != null) { 526 AttributeValueSupport attSup = 527 AttributeValueSupport.getSupport(false, elem.getName(), attrName); 528 if (attSup != null) { 530 CompletionQuery.Result result = attSup.getResult(component, offset, sup, elem, valuePart); if(!(attSup instanceof AttrSupports.FilenameSupport)) 532 setResultItemsOffset(result.getData(), valuePart.length(), offset); 533 return result; 534 } 535 } 536 537 } 538 539 return result(component, offset, new CompletionData(compItems, removeLength)); 540 } 541 542 543 protected CompletionData queryJspTagInContent(int offset, JspSyntaxSupport sup, BaseDocument doc) throws BadLocationException { 544 List compItems = new ArrayList(); 546 int removeLength = 0; 547 548 TokenItem item = sup.getItemAtOrBefore(offset); 549 if (item == null) { 550 return new CompletionData(compItems, 0); 551 } 552 553 String tokenPart = item.getImage().substring(0, 554 (offset - item.getOffset()) >= item.getImage().length() ? item.getImage().length() : offset - item.getOffset()); 555 int ltIndex = tokenPart.lastIndexOf('<'); 556 if (ltIndex != -1) { 557 tokenPart = tokenPart.substring(ltIndex + 1); 558 } 559 while (ltIndex == -1) { 560 item = item.getPrevious(); 561 if (item == null) { 562 return new CompletionData(compItems, 0); 563 } 564 String newImage = item.getImage(); 565 ltIndex = newImage.lastIndexOf('<'); 566 if (ltIndex != -1) 567 tokenPart = newImage.substring(ltIndex + 1) + tokenPart; 568 else { 569 tokenPart = newImage + tokenPart; 570 } 571 if (tokenPart.length() > 20) { 572 return new CompletionData(compItems, 0); 573 } 574 } 575 if (tokenPart.startsWith("/")) { tokenPart = tokenPart.substring(1); 579 compItems = sup.getPossibleEndTags(offset, tokenPart, true); } else { 581 addTagPrefixItems(sup, compItems, sup.getTagPrefixes(tokenPart)); 582 } 583 removeLength = tokenPart.length(); 584 return new CompletionData(compItems, removeLength); 585 } 586 587 protected CompletionQuery.Result queryJspDirectiveInContent(JTextComponent component, int offset, JspSyntaxSupport sup, BaseDocument doc) throws BadLocationException { 588 List compItems = new ArrayList(); 590 int removeLength = 0; 591 592 TokenItem item = sup.getItemAtOrBefore(offset); 593 if (item == null) { 594 return result(component, offset, new CompletionData(compItems, 0)); 596 } 597 598 String tokenPart = item.getImage().substring(0, 599 (offset - item.getOffset()) >= item.getImage().length() ? item.getImage().length() : offset - item.getOffset()); 600 601 if(!tokenPart.equals("<") && !tokenPart.equals("<%")) return result(component, offset, new CompletionData(compItems, 0)); 605 606 if("<%".equals(tokenPart)) removeLength = 1; else removeLength = 0; 609 addDirectiveItems(sup, compItems, sup.getDirectives("")); 611 return result(component, offset, new CompletionData(compItems, removeLength)); 612 } 613 614 private boolean isBlank(char c) { 615 return c == ' '; 616 } 617 618 622 protected String findAttributeForValue(JspSyntaxSupport sup, TokenItem item) { 623 while ((item != null) && (item.getTokenID().getNumericID() == JspTagTokenContext.ATTR_VALUE_ID)) 625 item = item.getPrevious(); 626 String symbols = ""; while ((item != null) && (item.getTokenID().getNumericID() == JspTagTokenContext.SYMBOL_ID)) { 629 symbols = item.getImage() + symbols; 630 item = item.getPrevious(); 631 } 632 if (!sup.isValueBeginning(symbols)) 634 return null; 635 String attributeName = ""; while ((item != null) && (item.getImage().trim().length() == 0)) { 640 item = item.getPrevious(); 641 } 642 while ((item != null) && (item.getTokenID().getNumericID() == JspTagTokenContext.ATTRIBUTE_ID)) { 644 attributeName = item.getImage() + attributeName; 645 item = item.getPrevious(); 646 } 647 if (attributeName.trim().length() > 0) 648 return attributeName.trim(); 649 return null; 650 } 651 652 656 private void addTagPrefixItems(JspSyntaxSupport sup, List compItemList, String prefix, List tagStringItems, SyntaxElement.Tag set) { 657 for (int i = 0; i < tagStringItems.size(); i++) { 658 Object item = tagStringItems.get(i); 659 if (item instanceof TagInfo ) 660 compItemList.add(new JspCompletionItem.PrefixTag(prefix , (TagInfo )item, set)); 661 else 662 compItemList.add(new JspCompletionItem.PrefixTag(prefix + ":" + (String )item)); } 664 } 665 666 669 private void addTagPrefixItems(JspSyntaxSupport sup, List compItemList, List prefixStringItems) { 670 for (int i = 0; i < prefixStringItems.size(); i++) { 671 String prefix = (String )prefixStringItems.get(i); 672 List tags = sup.getTags(prefix, ""); for (int j = 0; j < tags.size(); j++) { 675 Object item = tags.get(j); 676 if (item instanceof TagInfo ) 677 compItemList.add(new JspCompletionItem.PrefixTag(prefix , (TagInfo )item)); 678 else 679 compItemList.add(new JspCompletionItem.PrefixTag(prefix + ":" + (String )item)); } 681 } 682 } 683 684 687 private void addDirectiveItems(JspSyntaxSupport sup, List compItemList, List directiveStringItems) { 688 for (int i = 0; i < directiveStringItems.size(); i++) { 689 Object item = directiveStringItems.get(i); 690 if(item instanceof TagInfo ){ 691 TagInfo ti = (TagInfo ) item; 692 compItemList.add(new JspCompletionItem.Directive( ti.getTagName(), ti)); 693 } else 694 compItemList.add(new JspCompletionItem.Directive( (String )item)); 695 } 696 } 697 698 706 private void addAttributeItems(JspSyntaxSupport sup, List compItemList, 707 SyntaxElement.TagDirective tagDir, List attributeItems, String currentAttr) { 708 for (int i = 0; i < attributeItems.size(); i++) { 709 Object item = attributeItems.get(i); 710 String attr; 711 if (item instanceof TagAttributeInfo ) 712 attr = ((TagAttributeInfo )item).getName(); 713 else 714 attr = (String )item; 715 boolean isThere = tagDir.getAttributes().keySet().contains(attr); 716 if (!isThere || attr.equalsIgnoreCase(currentAttr) || 717 (currentAttr != null && attr.startsWith(currentAttr) && attr.length()>currentAttr.length() && !isThere)) { 718 if (item instanceof TagAttributeInfo ) 719 if ("taglib".equalsIgnoreCase(tagDir.getName())){ if (attr.equalsIgnoreCase("prefix") || (attr.equalsIgnoreCase("uri") && !tagDir.getAttributes().keySet().contains("tagdir")) || (attr.equalsIgnoreCase("tagdir") && !tagDir.getAttributes().keySet().contains("uri"))) compItemList.add(new JspCompletionItem.Attribute((TagAttributeInfo )item)); 729 } else { 730 compItemList.add(new JspCompletionItem.Attribute((TagAttributeInfo )item)); 731 } else 732 compItemList.add(new JspCompletionItem.Attribute((String )item)); 733 } 734 } 735 } 736 737 private CompletionQuery.Result result(JTextComponent component, int offset, CompletionData complData) { 738 setResultItemsOffset(complData, offset); 739 return new JspCompletionResult(component, 740 NbBundle.getMessage(JSPKit.class, "CTL_JSP_Completion_Title"), complData.completionItems, 741 offset, complData.removeLength, -1); 742 } 743 744 746 public static class CompletionData { 747 748 public List completionItems; 749 public int removeLength; 750 751 public CompletionData(List items, int length) { 752 this.completionItems = items; 753 this.removeLength = length; 754 } 755 756 public String toString() { 757 StringBuffer sb = new StringBuffer (); 758 sb.append("------ completion items, remove " + removeLength + " : ----------\n"); for (int i = 0; i < completionItems.size(); i++) { 760 CompletionQuery.ResultItem item = 761 (CompletionQuery.DefaultResultItem)completionItems.get(i); 762 sb.append(item.getItemText()); 763 sb.append("\n"); } 765 return sb.toString(); 766 } 767 768 769 } 770 771 static interface SubstituteOffsetProvider { 772 public int getSubstituteOffset(); 773 } 774 775 public static class JspCompletionResult extends CompletionQuery.DefaultResult implements SubstituteOffsetProvider { 776 private int substituteOffset; 777 public JspCompletionResult(JTextComponent component, String title, List data, int offset, int len, int htmlAnchorOffset ) { 778 super(component, title, data, offset, len); 779 substituteOffset = htmlAnchorOffset == -1 ? offset - len : htmlAnchorOffset; 780 } 781 782 public int getSubstituteOffset() { 783 return substituteOffset; 784 } 785 } 786 } 787 | Popular Tags |