1 16 17 package org.eclipse.ant.internal.ui.editor; 18 19 import java.io.File ; 20 import java.io.IOException ; 21 import java.io.InputStream ; 22 import java.io.InputStreamReader ; 23 import java.io.Reader ; 24 import java.lang.reflect.InvocationTargetException ; 25 import java.util.ArrayList ; 26 import java.util.Arrays ; 27 import java.util.Collections ; 28 import java.util.Comparator ; 29 import java.util.Enumeration ; 30 import java.util.HashMap ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Map ; 34 import java.util.Set ; 35 36 import org.apache.tools.ant.BuildException; 37 import org.apache.tools.ant.ComponentHelper; 38 import org.apache.tools.ant.IntrospectionHelper; 39 import org.apache.tools.ant.Project; 40 import org.apache.tools.ant.Target; 41 import org.apache.tools.ant.taskdefs.MacroDef; 42 import org.apache.tools.ant.taskdefs.MacroInstance; 43 import org.apache.tools.ant.types.EnumeratedAttribute; 44 import org.apache.tools.ant.types.Reference; 45 import org.eclipse.ant.internal.ui.AntUIImages; 46 import org.eclipse.ant.internal.ui.AntUIPlugin; 47 import org.eclipse.ant.internal.ui.IAntUIConstants; 48 import org.eclipse.ant.internal.ui.dtd.IAttribute; 49 import org.eclipse.ant.internal.ui.dtd.IDfm; 50 import org.eclipse.ant.internal.ui.dtd.IElement; 51 import org.eclipse.ant.internal.ui.dtd.ISchema; 52 import org.eclipse.ant.internal.ui.dtd.ParseError; 53 import org.eclipse.ant.internal.ui.dtd.Parser; 54 import org.eclipse.ant.internal.ui.editor.templates.AntContext; 55 import org.eclipse.ant.internal.ui.editor.templates.AntTemplateAccess; 56 import org.eclipse.ant.internal.ui.editor.templates.AntTemplateInformationControlCreator; 57 import org.eclipse.ant.internal.ui.editor.templates.AntTemplateProposal; 58 import org.eclipse.ant.internal.ui.editor.templates.BuildFileContextType; 59 import org.eclipse.ant.internal.ui.editor.templates.TargetContextType; 60 import org.eclipse.ant.internal.ui.editor.templates.TaskContextType; 61 import org.eclipse.ant.internal.ui.model.AntDefiningTaskNode; 62 import org.eclipse.ant.internal.ui.model.AntElementNode; 63 import org.eclipse.ant.internal.ui.model.AntModel; 64 import org.eclipse.ant.internal.ui.model.AntProjectNode; 65 import org.eclipse.ant.internal.ui.model.AntTargetNode; 66 import org.eclipse.ant.internal.ui.model.AntTaskNode; 67 import org.eclipse.core.commands.Command; 68 import org.eclipse.core.commands.ParameterizedCommand; 69 import org.eclipse.core.runtime.IProgressMonitor; 70 import org.eclipse.jface.bindings.TriggerSequence; 71 import org.eclipse.jface.operation.IRunnableWithProgress; 72 import org.eclipse.jface.text.BadLocationException; 73 import org.eclipse.jface.text.IDocument; 74 import org.eclipse.jface.text.IRegion; 75 import org.eclipse.jface.text.ITextSelection; 76 import org.eclipse.jface.text.ITextViewer; 77 import org.eclipse.jface.text.Position; 78 import org.eclipse.jface.text.Region; 79 import org.eclipse.jface.text.contentassist.ContentAssistEvent; 80 import org.eclipse.jface.text.contentassist.ICompletionListener; 81 import org.eclipse.jface.text.contentassist.ICompletionProposal; 82 import org.eclipse.jface.text.contentassist.IContentAssistProcessor; 83 import org.eclipse.jface.text.contentassist.IContentAssistant; 84 import org.eclipse.jface.text.contentassist.IContentAssistantExtension2; 85 import org.eclipse.jface.text.contentassist.IContextInformation; 86 import org.eclipse.jface.text.contentassist.IContextInformationValidator; 87 import org.eclipse.jface.text.templates.Template; 88 import org.eclipse.jface.text.templates.TemplateCompletionProcessor; 89 import org.eclipse.jface.text.templates.TemplateContext; 90 import org.eclipse.jface.text.templates.TemplateContextType; 91 import org.eclipse.jface.text.templates.TemplateException; 92 import org.eclipse.jface.text.templates.TemplateProposal; 93 import org.eclipse.swt.graphics.Image; 94 import org.eclipse.swt.graphics.Point; 95 import org.eclipse.ui.IEditorPart; 96 import org.eclipse.ui.IWorkbenchPage; 97 import org.eclipse.ui.PlatformUI; 98 import org.eclipse.ui.commands.ICommandService; 99 import org.eclipse.ui.keys.IBindingService; 100 import org.eclipse.ui.part.FileEditorInput; 101 import org.eclipse.ui.progress.IProgressService; 102 import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; 103 import org.w3c.dom.Element ; 104 import org.w3c.dom.Node ; 105 import org.w3c.dom.NodeList ; 106 107 import com.ibm.icu.text.MessageFormat; 108 109 112 public class AntEditorCompletionProcessor extends TemplateCompletionProcessor implements IContentAssistProcessor, ICompletionListener { 113 114 private static final class ProposalComparator implements Comparator { 115 public int compare(Object o1, Object o2) { 116 return ((TemplateProposal) o2).getRelevance() - ((TemplateProposal) o1).getRelevance(); 117 } 118 } 119 120 private static final Comparator fgProposalComparator= new ProposalComparator(); 121 122 private Comparator proposalComparator= new Comparator () { 123 public int compare(Object o1, Object o2) { 124 125 int type1= getProposalType(o1); 126 int type2= getProposalType(o2); 127 if (type1 != type2) { 128 if (type1 > type2) { 129 return 1; 130 } 131 return -1; 132 } 133 String string1 = ((ICompletionProposal)o1).getDisplayString(); 134 String string2 = ((ICompletionProposal)o2).getDisplayString(); 135 return string1.compareToIgnoreCase(string2); 136 } 137 private int getProposalType(Object o){ 138 if(o instanceof AntCompletionProposal){ 139 return ((AntCompletionProposal) o).getType(); 140 } 141 return AntCompletionProposal.TASK_PROPOSAL; 142 } 143 }; 144 145 protected final static int PROPOSAL_MODE_NONE = 0; 146 protected final static int PROPOSAL_MODE_BUILDFILE = 1; 147 protected final static int PROPOSAL_MODE_TASK_PROPOSAL = 2; 148 protected final static int PROPOSAL_MODE_PROPERTY_PROPOSAL = 3; 149 protected final static int PROPOSAL_MODE_ATTRIBUTE_PROPOSAL = 4; 150 protected final static int PROPOSAL_MODE_TASK_PROPOSAL_CLOSING = 5; 151 protected final static int PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL = 6; 152 protected final static int PROPOSAL_MODE_NESTED_ELEMENT_PROPOSAL = 7; 153 154 private final static ICompletionProposal[] NO_PROPOSALS= new ICompletionProposal[0]; 155 156 161 protected int lineNumber = -1; 162 163 168 protected int columnNumber = -1; 169 170 174 private int additionalProposalOffset = -1; 175 176 private static final String ANT_DTD_FILENAME = "/org/eclipse/ant/internal/ui/editor/ant1.6.2.dtd"; 178 181 private static ISchema fgDtd; 182 183 188 protected int cursorPosition = -1; 189 190 193 private ITextViewer viewer; 194 195 199 private char[] autoActivationChars= null; 200 201 private String errorMessage; 202 203 protected AntModel antModel; 204 205 209 private int currentProposalMode= -1; 210 211 214 protected String currentPrefix= null; 215 216 220 protected String currentTaskString= null; 221 222 private boolean fTemplatesOnly= false; 223 protected IContentAssistantExtension2 fContentAssistant; 224 225 public AntEditorCompletionProcessor(AntModel model) { 226 super(); 227 antModel= model; 228 } 229 230 233 private ISchema parseDtd() throws ParseError, IOException { 234 InputStream stream= null; 235 Reader reader= null; 236 try { 237 stream= getClass().getResourceAsStream(ANT_DTD_FILENAME); 238 reader=new InputStreamReader (stream, "UTF-8"); Parser parser = new Parser(); 240 ISchema schema= parser.parseDTD(reader, "project"); return schema; 242 } finally { 243 if (reader != null) { 244 reader.close(); 245 } 246 if (stream != null) { 247 stream.close(); 248 } 249 } 250 } 251 252 255 public ICompletionProposal[] computeCompletionProposals(ITextViewer refViewer, int documentOffset) { 256 this.viewer = refViewer; 257 try { 258 if (fTemplatesOnly) { 259 fContentAssistant.setStatusMessage(getIterationGestureMessage(AntEditorMessages.getString("AntEditorCompletionProcessor.0"))); fContentAssistant.setEmptyMessage(AntEditorMessages.getString("AntEditorCompletionProcessor.60")); ICompletionProposal[] templates= determineTemplateProposals(refViewer, documentOffset); 262 Arrays.sort(templates, proposalComparator); 263 return templates; 264 } 265 fContentAssistant.setStatusMessage(getIterationGestureMessage(AntEditorMessages.getString("AntEditorCompletionProcessor.61"))); fContentAssistant.setEmptyMessage(AntEditorMessages.getString("AntEditorCompletionProcessor.62")); ICompletionProposal[] matchingProposals= determineProposals(); 268 ICompletionProposal[] matchingTemplateProposals = determineTemplateProposals(refViewer, documentOffset); 269 return mergeProposals(matchingProposals, matchingTemplateProposals); 270 } finally { 271 currentPrefix= null; 272 currentProposalMode= -1; 273 fTemplatesOnly= !fTemplatesOnly; 274 } 275 } 276 277 protected ICompletionProposal[] determineTemplateProposals(ITextViewer refViewer, int documentOffset) { 278 this.viewer= refViewer; 279 String prefix = getCurrentPrefix(); 280 ICompletionProposal[] matchingTemplateProposals; 281 if (prefix.length() == 0) { 282 matchingTemplateProposals = determineTemplateProposalsForContext(documentOffset); 283 } else { 284 ICompletionProposal[] templateProposals = determineTemplateProposalsForContext(documentOffset); 285 List templateProposalList = new ArrayList (templateProposals.length); 286 for (int i = 0; i < templateProposals.length; i++) { 287 if (templateProposals[i].getDisplayString().toLowerCase().startsWith(prefix)) { 288 templateProposalList.add(templateProposals[i]); 289 } 290 } 291 matchingTemplateProposals = 292 (ICompletionProposal[]) templateProposalList.toArray(new ICompletionProposal[templateProposalList.size()]); 293 } 294 return matchingTemplateProposals; 295 } 296 297 private ICompletionProposal[] determineTemplateProposalsForContext(int offset) { 300 ITextSelection selection= (ITextSelection) viewer.getSelectionProvider().getSelection(); 301 302 if (selection.getOffset() == offset) { 304 offset= selection.getOffset() + selection.getLength(); 305 } 306 307 String prefix= extractPrefix(viewer, offset); 308 Region region= new Region(offset - prefix.length(), prefix.length()); 309 TemplateContext context= createContext(viewer, region); 310 if (context == null) { 311 return new ICompletionProposal[0]; 312 } 313 314 context.setVariable("selection", selection.getText()); 316 Template[] templates; 317 String contextTypeId = context.getContextType().getId(); 318 boolean isTargetContextType = contextTypeId.equals(TargetContextType.TARGET_CONTEXT_TYPE); 319 if (isTargetContextType) { 320 Template[] tasks = AntTemplateAccess.getDefault().getTemplateStore().getTemplates(TaskContextType.TASK_CONTEXT_TYPE); 321 Template[] targets = getTemplates(contextTypeId); 322 templates = new Template[tasks.length + targets.length]; 323 System.arraycopy(tasks, 0, templates, 0, tasks.length); 324 System.arraycopy(targets, 0, templates, tasks.length, targets.length); 325 } else { 326 templates = getTemplates(contextTypeId); 327 } 328 329 List matches= new ArrayList (); 330 for (int i= 0; i < templates.length; i++) { 331 Template template= templates[i]; 332 try { 333 context.getContextType().validate(template.getPattern()); 334 } catch (TemplateException e) { 335 continue; 336 } 337 if (template.matches(prefix, contextTypeId) || (isTargetContextType && template.matches(prefix, TaskContextType.TASK_CONTEXT_TYPE))) { 338 matches.add(createProposal(template, context, (IRegion) region, getRelevance(template, prefix))); 339 } 340 } 341 342 Collections.sort(matches, fgProposalComparator); 343 344 return (ICompletionProposal[]) matches.toArray(new ICompletionProposal[matches.size()]); 345 } 346 347 private ICompletionProposal[] mergeProposals(ICompletionProposal[] proposals1, ICompletionProposal[] proposals2) { 348 349 ICompletionProposal[] combinedProposals = new ICompletionProposal[proposals1.length + proposals2.length]; 350 351 System.arraycopy(proposals1, 0, combinedProposals, 0, proposals1.length); 352 System.arraycopy(proposals2, 0, combinedProposals, proposals1.length, proposals2.length); 353 354 Arrays.sort(combinedProposals, proposalComparator); 355 return combinedProposals; 356 } 357 358 361 public IContextInformation[] computeContextInformation(ITextViewer refViewer, int documentOffset) { 362 return new IContextInformation[0]; 363 } 364 365 368 public char[] getCompletionProposalAutoActivationCharacters() { 369 return autoActivationChars; 370 } 371 372 375 public char[] getContextInformationAutoActivationCharacters() { 376 return null; 377 } 378 379 382 public IContextInformationValidator getContextInformationValidator() { 383 return null; 384 } 385 386 389 public String getErrorMessage() { 390 return errorMessage; 391 } 392 393 396 private ICompletionProposal[] determineProposals() { 397 ITextSelection selection= (ITextSelection)viewer.getSelectionProvider().getSelection(); 398 cursorPosition = selection.getOffset() + selection.getLength(); 399 400 IDocument doc = viewer.getDocument(); 401 try { 402 lineNumber = doc.getLineOfOffset(cursorPosition); 403 columnNumber = cursorPosition - doc.getLineOffset(lineNumber); 404 } catch (BadLocationException e) { 405 AntUIPlugin.log(e); 406 } 407 408 String prefix = getCurrentPrefix(); 409 if (prefix == null || cursorPosition == -1) { 410 AntUIPlugin.getStandardDisplay().beep(); 411 return NO_PROPOSALS; 412 } 413 414 ICompletionProposal[] proposals = getProposalsFromDocument(doc, prefix); 415 currentTaskString= null; 416 return proposals; 417 } 418 419 422 protected ICompletionProposal[] getProposalsFromDocument(IDocument document, String prefix) { 423 ICompletionProposal[] proposals= null; 424 currentProposalMode= determineProposalMode(document, cursorPosition, prefix); 425 switch (currentProposalMode) { 426 case PROPOSAL_MODE_ATTRIBUTE_PROPOSAL: 427 proposals= getAttributeProposals(currentTaskString, prefix); 428 if (proposals.length == 0) { 429 errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.28"); } 431 break; 432 case PROPOSAL_MODE_TASK_PROPOSAL: 433 String parentName= getParentName(document, lineNumber, columnNumber); 434 if (parentName == null || parentName.length() == 0) { proposals= NO_PROPOSALS; 436 currentProposalMode= PROPOSAL_MODE_NONE; 437 } else { 438 proposals= getTaskProposals(document, parentName, prefix); 439 } 440 if (proposals.length == 0) { 441 errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.29"); } 443 break; 444 case PROPOSAL_MODE_BUILDFILE: 445 proposals= getBuildFileProposals(document, prefix); 446 if (proposals.length == 0) { 447 errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.29"); } 449 break; 450 case PROPOSAL_MODE_TASK_PROPOSAL_CLOSING: 451 ICompletionProposal proposal= getClosingTaskProposal(getOpenElementName(), prefix, true); 452 if (proposal == null) { 453 errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.30"); proposals= NO_PROPOSALS; 455 } else { 456 proposals= new ICompletionProposal[]{proposal}; 457 } 458 break; 459 case PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL: 460 String textToSearch= document.get().substring(0, cursorPosition-prefix.length()); 461 String attributeString = getAttributeStringFromDocumentStringToPrefix(textToSearch); 462 if ("target".equalsIgnoreCase(currentTaskString)) { proposals= getTargetAttributeValueProposals(document, textToSearch, prefix, attributeString); 464 } else if ("antcall".equalsIgnoreCase(currentTaskString)) { proposals= getAntCallAttributeValueProposals(document, prefix, attributeString); 466 } else if ("project".equalsIgnoreCase(currentTaskString)) { proposals= getProjectAttributeValueProposals(prefix, attributeString); 468 } else if ("refid".equalsIgnoreCase(attributeString) || "classpathref".equalsIgnoreCase(attributeString) || "sourcepathref".equalsIgnoreCase(attributeString) || "bootpathref".equalsIgnoreCase(attributeString)) { proposals= getReferencesValueProposals(prefix); 471 } else { 472 proposals= getAttributeValueProposals(currentTaskString, attributeString, prefix); 473 } 474 if (proposals.length == 0) { 475 errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.31"); } 477 break; 478 case PROPOSAL_MODE_PROPERTY_PROPOSAL: 479 proposals= getPropertyProposals(document, prefix, cursorPosition); 480 if (proposals.length == 0) { 481 errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.32"); } 483 break; 484 case PROPOSAL_MODE_NONE : 485 default : 486 proposals= NO_PROPOSALS; 487 errorMessage= AntEditorMessages.getString("AntEditorCompletionProcessor.33"); } 489 490 if (proposals.length > 0) { 491 errorMessage= ""; } 493 return proposals; 494 495 } 496 497 private ICompletionProposal[] getProjectAttributeValueProposals(String prefix, String attributeName) { 498 if (attributeName.equalsIgnoreCase("default")) { return getDefaultValueProposals(prefix); 500 } 501 502 return NO_PROPOSALS; 503 } 504 505 private ICompletionProposal[] getDefaultValueProposals(String prefix) { 506 Map targets = getTargets(); 507 List defaultProposals = new ArrayList (targets.size()); 508 Iterator itr = targets.values().iterator(); 509 510 Target target; 511 String targetName; 512 while (itr.hasNext()) { 513 target = (Target) itr.next(); 514 targetName= target.getName(); 515 if (targetName.toLowerCase().startsWith(prefix) && targetName.length() > 0) { 516 defaultProposals.add(new AntCompletionProposal(targetName, cursorPosition - prefix.length(), prefix.length(), targetName.length(), null, targetName, target.getDescription(), AntCompletionProposal.TASK_PROPOSAL)); 517 } 518 } 519 520 ICompletionProposal[] proposals = new ICompletionProposal[defaultProposals.size()]; 521 return (ICompletionProposal[])defaultProposals.toArray(proposals); 522 } 523 524 private ICompletionProposal[] getReferencesValueProposals(String prefix) { 525 Project project= antModel.getProjectNode().getProject(); 526 Map references= project.getReferences(); 527 if (references.isEmpty()) { 528 return NO_PROPOSALS; 529 } 530 Set refIds= references.keySet(); 531 AntElementNode node= antModel.getNode(cursorPosition, false); 532 if (node == null) { 533 return NO_PROPOSALS; 534 } 535 while (node.getParentNode() instanceof AntTaskNode) { 536 node= node.getParentNode(); 537 } 538 String id= null; 539 if (node instanceof AntTaskNode) { 540 id= ((AntTaskNode)node).getId(); 541 } 542 List proposals= new ArrayList (refIds.size()); 543 int i= 0; 544 String refId; 545 ICompletionProposal proposal; 546 int prefixLength= prefix.length(); 547 int replacementOffset= cursorPosition - prefixLength; 548 for (Iterator iter = refIds.iterator(); iter.hasNext(); i++) { 549 refId= (String ) iter.next(); 550 if (!refId.equals(id) && (prefixLength == 0 || refId.toLowerCase().startsWith(prefix))) { 551 proposal= new AntCompletionProposal(refId, replacementOffset, prefixLength, refId.length(), null, refId, null, AntCompletionProposal.TASK_PROPOSAL); 552 proposals.add(proposal); 553 } 554 } 555 return (ICompletionProposal[])proposals.toArray(new ICompletionProposal[proposals.size()]); 556 } 557 558 protected ICompletionProposal[] getTargetAttributeValueProposals(IDocument document, String textToSearch, String prefix, String attributeName) { 559 if (attributeName.equalsIgnoreCase("depends")) { return getDependsValueProposals(document, prefix); 561 } else if (attributeName.equalsIgnoreCase("if") || attributeName.equalsIgnoreCase("unless")) { if (!textToSearch.trim().endsWith(",")) { return getPropertyProposals(document, prefix, cursorPosition); 564 } 565 } 566 567 return NO_PROPOSALS; 568 } 569 570 protected ICompletionProposal[] getAntCallAttributeValueProposals(IDocument document, String prefix, String attributeName) { 571 if (attributeName.equalsIgnoreCase("target")) { return getTargetProposals(document, prefix); 573 } 574 575 return NO_PROPOSALS; 576 } 577 578 private ICompletionProposal[] getTargetProposals(IDocument document, String prefix) { 579 String currentTargetName= getEnclosingTargetName(document, lineNumber, columnNumber); 580 if(currentTargetName == null) { 581 return NO_PROPOSALS; 582 } 583 584 Map targets= getTargets(); 585 Set targetNames= targets.keySet(); 586 List proposals= new ArrayList (targets.size() - 2); int index= 0; 588 Iterator itr= targetNames.iterator(); 589 while (itr.hasNext()) { 590 String targetName = (String ) itr.next(); 591 if (targetName.equals(currentTargetName)) { 592 continue; 593 } 594 if (targetName.toLowerCase().startsWith(prefix) && targetName.length() > 0){ 595 ICompletionProposal proposal = new AntCompletionProposal(targetName, cursorPosition - prefix.length(), prefix.length(), targetName.length(), null, targetName, ((Target)targets.get(targetName)).getDescription(), AntCompletionProposal.TASK_PROPOSAL); 596 proposals.add(proposal); 597 index++; 598 } 599 } 600 return (ICompletionProposal[])proposals.toArray(new ICompletionProposal[proposals.size()]); 601 } 602 603 private ICompletionProposal[] getDependsValueProposals(IDocument document, String prefix) { 604 List possibleDependencies = new ArrayList (); 605 String currentTargetName= getEnclosingTargetName(document, lineNumber, columnNumber); 606 if(currentTargetName == null) { 607 return NO_PROPOSALS; 608 } 609 610 Map targets= getTargets(); 611 Set targetNames= targets.keySet(); 612 Iterator itr= targetNames.iterator(); 613 Enumeration dependencies= null; 614 while (itr.hasNext()) { 615 String targetName = (String ) itr.next(); 616 if (targetName.equals(currentTargetName)) { 617 Target currentTarget= (Target)targets.get(targetName); 618 dependencies= currentTarget.getDependencies(); 619 continue; 620 } 621 if (targetName.toLowerCase().startsWith(prefix) && targetName.length() > 0){ 622 possibleDependencies.add(targetName); 623 } 624 } 625 626 if (dependencies != null) { 627 while (dependencies.hasMoreElements()) { 628 possibleDependencies.remove(dependencies.nextElement()); 629 } 630 } 631 632 ICompletionProposal[] proposals= new ICompletionProposal[possibleDependencies.size()]; 633 int i= 0; 634 for (Iterator iter = possibleDependencies.iterator(); iter.hasNext(); i++) { 635 String targetName = (String ) iter.next(); 636 ICompletionProposal proposal = new AntCompletionProposal(targetName, cursorPosition - prefix.length(), prefix.length(), targetName.length(), null, targetName, ((Target)targets.get(targetName)).getDescription(), AntCompletionProposal.TASK_PROPOSAL); 637 proposals[i]= proposal; 638 } 639 return proposals; 640 } 641 642 650 protected ICompletionProposal[] getAttributeProposals(String taskName, String prefix) { 651 List proposals = new ArrayList (); 652 IElement element = getDtd().getElement(taskName); 653 if (element != null) { 654 Iterator keys = element.getAttributes().keySet().iterator(); 655 while (keys.hasNext()) { 656 String attrName = (String ) keys.next(); 657 if (prefix.length() == 0 || attrName.toLowerCase().startsWith(prefix)) { 658 IAttribute dtdAttributes = (IAttribute) element.getAttributes().get(attrName); 659 String replacementString = attrName+"=\"\""; String displayString = attrName; 661 String [] items = dtdAttributes.getEnum(); 662 if (items != null) { 663 if(items.length > 1) { 664 displayString += " - ("; } 666 for (int i = 0; i < items.length; i++) { 667 displayString += items[i]; 668 if(i+1 < items.length) { 669 displayString += " | "; } else { 671 displayString += ")"; } 673 } 674 } 675 676 addAttributeProposal(taskName, prefix, proposals, attrName, replacementString, displayString, true); 677 } 678 } 679 } else { Class taskClass= getTaskClass(taskName); 681 if (taskClass != null) { 682 if (taskClass == MacroInstance.class) { 683 addMacroDefAttributeProposals(taskName, prefix, proposals); 684 } else { 685 IntrospectionHelper helper= getIntrospectionHelper(taskClass); 686 if (helper != null) { 687 addAttributeProposals(helper, taskName, prefix, proposals); 688 } 689 } 690 } else { Class nestedType= getNestedType(); 692 if (nestedType != null) { 693 IntrospectionHelper helper= getIntrospectionHelper(nestedType); 694 if (helper != null) { 695 addAttributeProposals(helper, taskName, prefix, proposals); 696 } 697 } 698 } 699 } 700 return (ICompletionProposal[])proposals.toArray(new ICompletionProposal[proposals.size()]); 701 } 702 703 private void addAttributeProposals(IntrospectionHelper helper, String taskName, String prefix, List proposals) { 704 Enumeration attributes= helper.getAttributes(); 705 while (attributes.hasMoreElements()) { 706 String attribute = (String ) attributes.nextElement(); 707 if (prefix.length() == 0 || attribute.toLowerCase().startsWith(prefix)) { 708 String replacementString = attribute + "=\"\""; addAttributeProposal(taskName, prefix, proposals, attribute, replacementString, attribute, false); 710 } 711 } 712 } 713 714 private Class getNestedType() { 715 AntElementNode currentNode= antModel.getNode(cursorPosition, false); 716 if (currentNode == null) { 717 return null; 718 } 719 AntElementNode parent= currentNode.getParentNode(); 720 if (parent instanceof AntTaskNode) { 721 String parentName= parent.getName(); 722 if (hasNestedElements(parentName)) { 723 Class taskClass= getTaskClass(parentName); 724 if (taskClass != null) { 725 IntrospectionHelper helper= getIntrospectionHelper(taskClass); 726 if (helper != null) { 727 Class nestedType= null; 728 try { 729 nestedType= helper.getElementType(currentNode.getName()); 730 } catch (BuildException be) { 731 } 732 return nestedType; 733 } 734 } 735 } 736 } 737 return null; 738 } 739 740 private IntrospectionHelper getIntrospectionHelper(Class taskClass) { 741 IntrospectionHelper helper= null; 742 try { 743 helper= IntrospectionHelper.getHelper(antModel.getProjectNode().getProject(), taskClass); 744 } catch (NoClassDefFoundError e) { 745 } 747 return helper; 748 } 749 750 private void addMacroDefAttributeProposals(String taskName, String prefix, List proposals) { 751 currentProposalMode= PROPOSAL_MODE_ATTRIBUTE_PROPOSAL; 752 AntDefiningTaskNode node= antModel.getDefininingTaskNode(taskName); 753 Object task= node.getRealTask(); 754 if (!(task instanceof MacroDef)) { 755 return; 756 } 757 List attributes= ((MacroDef)task).getAttributes(); 758 Iterator itr= attributes.iterator(); 759 while (itr.hasNext()) { 760 MacroDef.Attribute attribute = (MacroDef.Attribute) itr.next(); 761 String attributeName= attribute.getName(); 762 if (!(prefix.length() == 0 || attributeName.toLowerCase().startsWith(prefix))) { 763 continue; 764 } 765 String replacementString = attributeName + "=\"\""; String proposalInfo = null; 767 768 String description = attribute.getDescription(); 769 if(description != null) { 770 proposalInfo= description; 771 } 772 String deflt = attribute.getDefault(); 773 if(deflt != null && deflt.length() > 0) { 774 proposalInfo= (proposalInfo == null ? "<BR><BR>" : (proposalInfo += "<BR><BR>")); proposalInfo+= MessageFormat.format(AntEditorMessages.getString("AntEditorCompletionProcessor.59"), new String []{deflt}); } 777 778 ICompletionProposal proposal = new AntCompletionProposal(replacementString, cursorPosition - prefix.length(), prefix.length(), attributeName.length() + 2, null, attributeName, proposalInfo, AntCompletionProposal.TASK_PROPOSAL); 779 proposals.add(proposal); 780 } 781 } 782 783 private void addMacroDefElementProposals(String taskName, String prefix, List proposals) { 784 AntDefiningTaskNode node= antModel.getDefininingTaskNode(taskName); 785 Object task= node.getRealTask(); 786 if (!(task instanceof MacroDef)) { 787 return; 788 } 789 Map elements= ((MacroDef)task).getElements(); 790 Iterator itr= elements.keySet().iterator(); 791 int prefixLength= prefix.length(); 792 int replacementOffset= cursorPosition - prefixLength; 793 while (itr.hasNext()) { 794 String elementName = (String ) itr.next(); 795 if (!(prefixLength == 0 || elementName.toLowerCase().startsWith(prefix))) { 796 continue; 797 } 798 MacroDef.TemplateElement element = (MacroDef.TemplateElement) elements.get(elementName); 799 String replacementString = MessageFormat.format("<{0}>\n</{1}>", new String []{elementName, elementName}); String proposalInfo = null; 801 802 String description = element.getDescription(); 803 if(description != null) { 804 proposalInfo= description; 805 } 806 proposalInfo= (proposalInfo == null ? "<BR><BR>" : (proposalInfo += "<BR><BR>")); 808 if(element.isOptional()) { 809 proposalInfo+= AntEditorMessages.getString("AntEditorCompletionProcessor.1"); } else { 811 proposalInfo+= AntEditorMessages.getString("AntEditorCompletionProcessor.2"); } 813 814 ICompletionProposal proposal = new AntCompletionProposal(replacementString, replacementOffset, prefixLength, elementName.length() + 2, null, elementName, proposalInfo, AntCompletionProposal.TASK_PROPOSAL); 815 proposals.add(proposal); 816 } 817 } 818 819 private void addAttributeProposal(String taskName, String prefix, List proposals, String attrName, String replacementString, String displayString, boolean lookupDescription) { 820 821 String proposalInfo = null; 822 if (lookupDescription) { 823 String required = getDescriptionProvider().getRequiredAttributeForTaskAttribute(taskName, attrName); 824 if(required != null && required.length() > 0) { 825 proposalInfo = AntEditorMessages.getString("AntEditorCompletionProcessor.Required___4") + required; proposalInfo += "<BR><BR>"; } 828 String description = getDescriptionProvider().getDescriptionForTaskAttribute(taskName, attrName); 829 if(description != null) { 830 proposalInfo = (proposalInfo == null ? "" : proposalInfo); proposalInfo += description; 832 } 833 } 834 835 ICompletionProposal proposal = new AntCompletionProposal(replacementString, cursorPosition - prefix.length(), prefix.length(), attrName.length()+2, null, displayString, proposalInfo, AntCompletionProposal.TASK_PROPOSAL); 836 proposals.add(proposal); 837 } 838 839 852 private ICompletionProposal[] getAttributeValueProposals(String taskName, String attributeName, String prefix) { 853 List proposals = new ArrayList (); 854 IElement taskElement = getDtd().getElement(taskName); 855 if (taskElement != null) { 856 IAttribute attribute = (IAttribute) taskElement.getAttributes().get(attributeName); 857 if (attribute != null) { 858 String [] items = attribute.getEnum(); 859 if (items != null) { 860 String item; 861 for (int i = 0; i < items.length; i++) { 862 item= items[i]; 863 if(prefix.length() ==0 || item.toLowerCase().startsWith(prefix)) { 864 proposals.add( 865 new AntCompletionProposal(item, cursorPosition - prefix.length(), prefix.length(), item.length(), null, item, null, AntCompletionProposal.TASK_PROPOSAL)); 866 } 867 } 868 } 869 } 870 } else { Class taskClass= getTaskClass(taskName); 872 if (taskClass != null) { 873 IntrospectionHelper helper= getIntrospectionHelper(taskClass); 874 if (helper != null) { 875 addAttributeValueProposals(helper, attributeName, prefix, proposals); 876 } 877 } else { Class nestedType= getNestedType(); 879 if (nestedType != null) { 880 IntrospectionHelper helper= getIntrospectionHelper(nestedType); 881 if (helper != null) { 882 addAttributeValueProposals(helper, attributeName, prefix, proposals); 883 } 884 } 885 } 886 } 887 return (ICompletionProposal[])proposals.toArray(new ICompletionProposal[proposals.size()]); 888 } 889 890 private void addAttributeValueProposals(IntrospectionHelper helper, String attributeName, String prefix, List proposals) { 891 Enumeration attributes= helper.getAttributes(); 892 while (attributes.hasMoreElements()) { 893 String attribute= (String ) attributes.nextElement(); 894 if (attribute.equals(attributeName)) { 895 Class attributeType= helper.getAttributeType(attribute); 896 addAttributeValueProposalsForAttributeType(attributeType, prefix, proposals); 897 break; 898 } 899 } 900 } 901 902 private void addAttributeValueProposalsForAttributeType(Class attributeType, String prefix, List proposals) { 903 if ((attributeType == Boolean.TYPE || attributeType == Boolean .class) && prefix.length() <= 5) { 904 addBooleanAttributeValueProposals(prefix, proposals); 905 } else if (EnumeratedAttribute.class.isAssignableFrom(attributeType)) { 906 try { 907 addEnumeratedAttributeValueProposals(attributeType, prefix, proposals); 908 } catch (InstantiationException e) { 909 } catch (IllegalAccessException e) { 910 } 911 } else if (Reference.class == attributeType) { 912 proposals.addAll(Arrays.asList(getReferencesValueProposals(prefix))); 913 } 914 } 915 916 private void addEnumeratedAttributeValueProposals(Class type, String prefix, List proposals) throws InstantiationException , IllegalAccessException { 917 EnumeratedAttribute ea= (EnumeratedAttribute) type.newInstance(); 918 String [] values = ea.getValues(); 919 String enumerated; 920 for (int i = 0; i < values.length; i++) { 921 enumerated= values[i].toLowerCase(); 922 if (prefix.length() == 0 || enumerated.startsWith(prefix)) { 923 proposals.add(new AntCompletionProposal(enumerated, cursorPosition - prefix.length(), prefix.length(), enumerated.length(), null, enumerated, null, AntCompletionProposal.TASK_PROPOSAL)); 924 } 925 } 926 } 927 928 private void addBooleanAttributeValueProposals(String prefix, List proposals) { 929 String [] booleanValues = new String []{"true","false","on","off","yes","no"}; String booleanAssist; 931 for (int i = 0; i < booleanValues.length; i++) { 932 booleanAssist= booleanValues[i].toLowerCase(); 933 if (prefix.length() == 0 || booleanAssist.startsWith(prefix)) { 934 proposals.add(new AntCompletionProposal(booleanAssist, cursorPosition -prefix.length(), 935 prefix.length(), booleanAssist.length(), null, booleanAssist, 936 null, AntCompletionProposal.TASK_PROPOSAL)); 937 } 938 } 939 } 940 941 947 protected ICompletionProposal[] getPropertyProposals(IDocument document, String prefix, int aCursorPosition) { 948 List proposals = new ArrayList (); 949 Map displayStringToProposals= new HashMap (); 950 Map properties = findPropertiesFromDocument(); 951 952 Image image = AntUIImages.getImage(IAntUIConstants.IMG_PROPERTY); 953 int replacementLength = prefix.length(); 956 int replacementOffset = 0; 957 String text= document.get(); 958 String stringToPrefix = text.substring(0, aCursorPosition - prefix.length()); 959 String lastTwoCharacters = stringToPrefix.substring(stringToPrefix.length()-2, stringToPrefix.length()); 961 boolean appendBraces= true; 962 if(lastTwoCharacters.equals("${")) { replacementLength += 2; 964 replacementOffset = aCursorPosition - prefix.length() - 2; 965 } else if(lastTwoCharacters.endsWith("$")) { replacementLength += 1; 967 replacementOffset = aCursorPosition - prefix.length() - 1; 968 } else { 969 replacementOffset= aCursorPosition - prefix.length(); 971 appendBraces= false; 972 } 973 974 if(text.length() > aCursorPosition && text.charAt(aCursorPosition) == '}') { 975 replacementLength += 1; 976 } 977 String propertyName; 978 for(Iterator i=properties.keySet().iterator(); i.hasNext(); ) { 979 propertyName= (String )i.next(); 980 if(prefix.length() == 0 || propertyName.toLowerCase().startsWith(prefix)) { 981 String additionalPropertyInfo = (String )properties.get(propertyName); 982 983 StringBuffer replacementString = new StringBuffer (); 984 if (appendBraces) { 985 replacementString.append("${"); } 987 replacementString.append(propertyName); 988 if (appendBraces) { 989 replacementString.append('}'); 990 } 991 992 if (displayStringToProposals.get(propertyName) == null) { 993 ICompletionProposal proposal = 994 new AntCompletionProposal( 995 replacementString.toString(), replacementOffset, replacementLength, 996 replacementString.length(), image, propertyName, 997 additionalPropertyInfo, AntCompletionProposal.PROPERTY_PROPOSAL); 998 proposals.add(proposal); 999 displayStringToProposals.put(propertyName, proposal); 1000 } 1001 } 1002 } 1003 return (ICompletionProposal[])proposals.toArray(new ICompletionProposal[proposals.size()]); 1004 } 1005 1006 1007 1018 protected ICompletionProposal[] getTaskProposals(IDocument document, String parentName, String prefix) { 1019 List proposals = new ArrayList (250); 1020 ICompletionProposal proposal; 1021 if (areTasksOrTypesValidChildren(parentName)) { 1022 Project project= antModel.getProjectNode().getProject(); 1024 Map tasksAndTypes= ComponentHelper.getComponentHelper(project).getAntTypeTable(); 1025 createProposals(document, prefix, proposals, tasksAndTypes); 1026 if (parentName.equals("project") && "target".startsWith(prefix)) { proposals.add(newCompletionProposal(document, prefix, "target")); } 1029 } else { 1030 IElement parent = getDtd().getElement(parentName); 1031 if (parent != null) { 1032 IDfm dfm = parent.getDfm(); 1033 String [] accepts = dfm.getAccepts(); 1034 if (accepts.length == 0) { 1035 currentProposalMode= PROPOSAL_MODE_NONE; 1036 } 1037 String elementName; 1038 for (int i = 0; i < accepts.length; i++) { 1039 elementName = accepts[i]; 1040 if(prefix.length() == 0 || elementName.toLowerCase().startsWith(prefix)) { 1041 proposal = newCompletionProposal(document, prefix, elementName); 1042 proposals.add(proposal); 1043 } 1044 } 1045 } else { 1046 Class taskClass= getTaskClass(parentName); 1048 if (taskClass != null) { 1049 if (taskClass == MacroInstance.class) { 1050 currentProposalMode= PROPOSAL_MODE_ATTRIBUTE_PROPOSAL; 1051 addMacroDefElementProposals(parentName, prefix, proposals); 1052 } else { 1053 currentProposalMode= PROPOSAL_MODE_NESTED_ELEMENT_PROPOSAL; 1054 IntrospectionHelper helper= getIntrospectionHelper(taskClass); 1055 if (helper != null) { 1056 Enumeration nested= helper.getNestedElements(); 1057 String nestedElement; 1058 while (nested.hasMoreElements()) { 1059 nestedElement = (String ) nested.nextElement(); 1060 if (prefix.length() == 0 || nestedElement.toLowerCase().startsWith(prefix)) { 1061 proposal = newCompletionProposal(document, prefix, nestedElement); 1062 proposals.add(proposal); 1063 } 1064 } 1065 } 1066 } 1067 } 1068 } 1069 } 1070 1071 proposal= getClosingTaskProposal(getOpenElementName(), prefix, false); 1072 if (proposal != null) { 1073 proposals.add(proposal); 1074 } 1075 1076 return (ICompletionProposal[])proposals.toArray(new ICompletionProposal[proposals.size()]); 1077 } 1078 1079 private boolean areTasksOrTypesValidChildren(String parentName) { 1080 return parentName == "project" || parentName == "target" || parentName == "sequential" || parentName == "presetdef" || parentName == "parallel" || parentName == "daemons"; } 1083 1084 1095 protected ICompletionProposal[] getBuildFileProposals(IDocument document, String prefix) { 1096 String rootElementName= "project"; IElement rootElement = getDtd().getElement(rootElementName); 1098 if (rootElement != null && rootElementName.toLowerCase().startsWith(prefix)) { 1099 ICompletionProposal proposal = newCompletionProposal(document, prefix, rootElementName); 1100 return new ICompletionProposal[] {proposal}; 1101 } 1102 1103 return NO_PROPOSALS; 1104 } 1105 1106 private void createProposals(IDocument document, String prefix, List proposals, Map tasks) { 1107 Iterator keys= tasks.keySet().iterator(); 1108 ICompletionProposal proposal; 1109 String key; 1110 while (keys.hasNext()) { 1111 key= antModel.getUserNamespaceCorrectName((String ) keys.next()); 1112 if (prefix.length() == 0 || key.toLowerCase().startsWith(prefix)) { 1113 proposal = newCompletionProposal(document, prefix, key); 1114 proposals.add(proposal); 1115 } 1116 } 1117 } 1118 1119 private ICompletionProposal newCompletionProposal(IDocument document, String aPrefix, String elementName) { 1120 additionalProposalOffset= 0; 1121 Image proposalImage = AntUIImages.getImage(IAntUIConstants.IMG_TASK_PROPOSAL); 1122 String proposalInfo = getDescriptionProvider().getDescriptionForTask(elementName); 1123 boolean hasNestedElements= hasNestedElements(elementName); 1124 String replacementString = getTaskProposalReplacementString(elementName, hasNestedElements); 1125 int replacementOffset = cursorPosition - aPrefix.length(); 1126 int replacementLength = aPrefix.length(); 1127 if (replacementOffset > 0 && document.get().charAt(replacementOffset - 1) == '<') { 1128 replacementOffset--; 1129 replacementLength++; 1130 } 1131 int proposalCursorPosition; 1132 if (hasNestedElements) { 1133 proposalCursorPosition= elementName.length() + 2 + additionalProposalOffset; 1134 } else { 1135 if (additionalProposalOffset > 0) { 1136 additionalProposalOffset+=2; } else { 1138 additionalProposalOffset+=1; } 1140 proposalCursorPosition= elementName.length() + additionalProposalOffset; 1141 } 1142 return new AntCompletionProposal(replacementString, replacementOffset, 1143 replacementLength, proposalCursorPosition, proposalImage, elementName, proposalInfo, AntCompletionProposal.TASK_PROPOSAL); 1144 } 1145 1146 1155 private ICompletionProposal getClosingTaskProposal(String openElementName, String prefix, boolean closingMode) { 1156 char previousChar = getPreviousChar(); 1157 ICompletionProposal proposal= null; 1158 if(openElementName != null) { 1159 if(prefix.length() == 0 || openElementName.toLowerCase().startsWith(prefix)) { 1160 StringBuffer replaceString = new StringBuffer (); 1161 if (!closingMode) { 1162 if (previousChar != '/') { 1163 if (previousChar != '<') { 1164 replaceString.append('<'); 1165 } 1166 replaceString.append('/'); 1167 } 1168 } 1169 replaceString.append(openElementName); 1170 replaceString.append('>'); 1171 StringBuffer displayString= new StringBuffer ("</"); displayString.append(openElementName); 1173 displayString.append('>'); 1174 proposal= new AntCompletionProposal(replaceString.toString(), cursorPosition - prefix.length(), prefix.length(), replaceString.length(), null, displayString.toString(), AntEditorMessages.getString("AntEditorCompletionProcessor.39"), AntCompletionProposal.TAG_CLOSING_PROPOSAL); } 1176 } 1177 1178 return proposal; 1179 } 1180 1181 protected char getPreviousChar() { 1182 ITextSelection selection = (ITextSelection)viewer.getSelectionProvider().getSelection(); 1183 int offset= selection.getOffset(); 1184 char previousChar= '?'; 1185 try { 1186 previousChar= viewer.getDocument().getChar(offset-1); 1187 } catch (BadLocationException e) { 1188 1189 } 1190 return previousChar; 1191 } 1192 1193 1196 private String getTaskProposalReplacementString(String aTaskName, boolean hasNested) { 1197 StringBuffer replacement = new StringBuffer ("<"); replacement.append(aTaskName); 1199 Node attributeNode= getDescriptionProvider().getAttributesNode(aTaskName); 1200 1201 if (attributeNode != null) { 1202 appendRequiredAttributes(replacement, attributeNode); 1203 } 1204 1205 if (hasNested) { 1206 replacement.append("></"); replacement.append(aTaskName); 1208 replacement.append('>'); 1209 } else { 1210 replacement.append("/>"); } 1212 return replacement.toString(); 1213 } 1214 1215 private void appendRequiredAttributes(StringBuffer replacement, Node attributeNode) { 1216 boolean requiredAdded= false; 1217 NodeList attributes= attributeNode.getChildNodes(); 1218 String required; 1219 Node attribute; 1220 for (int i = 0; i < attributes.getLength(); i++) { 1221 attribute = attributes.item(i); 1222 required= getDescriptionProvider().getRequiredOfNode(attribute); 1223 if (required.equalsIgnoreCase("yes")) { String attributeName= getDescriptionProvider().getTaskAttributeName(attribute); 1225 replacement.append(' '); 1226 replacement.append(attributeName); 1227 replacement.append("=\"\""); if (!requiredAdded){ 1229 additionalProposalOffset= attributeName.length() + 2; 1230 requiredAdded= true; 1231 } 1232 } 1233 } 1234 } 1235 1236 1239 private boolean hasNestedElements(String elementName) { 1240 IElement element = getDtd().getElement(elementName); 1241 if (element != null) { 1242 return !element.isEmpty(); 1243 } 1244 Class taskClass= getTaskClass(elementName); 1245 if (taskClass != null) { 1246 IntrospectionHelper helper= getIntrospectionHelper(taskClass); 1247 if (helper != null) { 1248 Enumeration nested= helper.getNestedElements(); 1249 return nested.hasMoreElements(); 1250 } 1251 } 1252 return false; 1253 } 1254 1255 1264 protected Element findChildElementNamedOf(Element anElement, String aChildElementName) { 1265 NodeList nodeList = anElement.getChildNodes(); 1266 for (int i = 0; i < nodeList.getLength(); i++) { 1267 Node childNode = nodeList.item(i); 1268 if(childNode.getNodeType() == Node.ELEMENT_NODE) { 1269 if(childNode.getNodeName().equals(aChildElementName)) { 1270 return (Element)childNode; 1271 } 1272 } 1273 } 1274 return null; 1275 } 1276 1277 1280 private String getCurrentPrefix() { 1281 if (currentPrefix != null) { 1282 return currentPrefix; 1283 } 1284 ITextSelection selection = (ITextSelection)viewer.getSelectionProvider().getSelection(); 1285 IDocument doc = viewer.getDocument(); 1286 return getPrefixFromDocument(doc.get(), selection.getOffset() + selection.getLength()).toLowerCase(); 1287 } 1288 1289 1290 1297 protected String getPrefixFromDocument(String aDocumentText, int anOffset) { 1298 if (currentPrefix != null) { 1299 return currentPrefix; 1300 } 1301 int startOfWordToken = anOffset; 1302 1303 char token= 'a'; 1304 if (startOfWordToken > 0) { 1305 token= aDocumentText.charAt(startOfWordToken - 1); 1306 } 1307 1308 while (startOfWordToken > 0 1309 && (Character.isJavaIdentifierPart(token) 1310 || '.' == token 1311 || '-' == token 1312 || ';' == token) 1313 && !('$' == token)) { 1314 startOfWordToken--; 1315 if (startOfWordToken == 0) { 1316 break; } 1318 token= aDocumentText.charAt(startOfWordToken - 1); 1319 } 1320 1321 if (startOfWordToken != anOffset) { 1322 currentPrefix= aDocumentText.substring(startOfWordToken, anOffset).toLowerCase(); 1323 } else { 1324 currentPrefix= ""; } 1326 return currentPrefix; 1327 } 1328 1329 1330 1333 protected int determineProposalMode(IDocument document, int aCursorPosition, String aPrefix) { 1334 if (currentProposalMode != -1) { 1335 return currentProposalMode; 1336 } 1337 if (document.getLength() == 0 || (document.getLength() == 1 && document.get().equals("<"))) { return PROPOSAL_MODE_BUILDFILE; 1339 } 1340 1341 String text= document.get(); 1343 String stringToPrefix = text.substring(0, aCursorPosition - aPrefix.length()); 1344 if (stringToPrefix.length() == 0) { 1345 return PROPOSAL_MODE_BUILDFILE; 1346 } 1347 String trimmedString = stringToPrefix.trim(); 1349 if (antModel != null && antModel.getProjectNode() == null) { 1350 currentTaskString= getTaskStringFromDocumentStringToPrefix(trimmedString); 1351 if ("project".equals(currentTaskString)) { return PROPOSAL_MODE_ATTRIBUTE_PROPOSAL; 1353 } 1354 return PROPOSAL_MODE_BUILDFILE; 1355 } 1356 1357 char lastChar = 0; 1358 if(trimmedString.length() > 0) { 1359 lastChar = trimmedString.charAt(trimmedString.length()-1); 1360 } else { 1361 return PROPOSAL_MODE_TASK_PROPOSAL; 1362 } 1363 if(stringToPrefix.charAt(stringToPrefix.length()-1) != lastChar && lastChar != '>' && lastChar != ',') { 1364 1370 1371 if(lastChar != '>' && lastChar != '<') { 1373 currentTaskString= getTaskStringFromDocumentStringToPrefix(trimmedString); 1374 if(currentTaskString != null && isKnownElement(currentTaskString)) { 1375 return PROPOSAL_MODE_ATTRIBUTE_PROPOSAL; 1376 } 1377 } 1378 } else if(stringToPrefix.charAt(stringToPrefix.length() - 1) == '"' || trimmedString.charAt(trimmedString.length() - 1) == ',') { 1379 currentTaskString= getTaskStringFromDocumentStringToPrefix(trimmedString); 1381 if (currentTaskString != null && isKnownElement(currentTaskString)) { 1382 return PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL; 1383 } 1384 } else { int spaceIndex = stringToPrefix.lastIndexOf(' '); 1386 int lessThanIndex = stringToPrefix.lastIndexOf('<'); 1387 int greaterThanIndex = stringToPrefix.lastIndexOf('>'); 1388 1389 if(lessThanIndex > spaceIndex && greaterThanIndex < lessThanIndex) { 1391 int slashIndex = stringToPrefix.lastIndexOf('/'); 1392 if(slashIndex == lessThanIndex +1) { 1393 return PROPOSAL_MODE_TASK_PROPOSAL_CLOSING; } 1395 return PROPOSAL_MODE_TASK_PROPOSAL; 1396 } 1397 if(lessThanIndex < greaterThanIndex) { 1398 if (isPropertyProposalMode(stringToPrefix)) { 1399 return PROPOSAL_MODE_PROPERTY_PROPOSAL; 1400 } 1401 return PROPOSAL_MODE_TASK_PROPOSAL; 1402 } 1403 } 1404 1405 if (isPropertyProposalMode(stringToPrefix)) { 1407 return PROPOSAL_MODE_PROPERTY_PROPOSAL; 1408 } 1409 1410 return PROPOSAL_MODE_NONE; 1411 } 1412 1413 1414 private boolean isPropertyProposalMode(String stringToPrefix) { 1415 if(stringToPrefix.length() >= 2) { 1416 String lastTwoChars = stringToPrefix.substring(stringToPrefix.length()-2, stringToPrefix.length()); 1417 if(lastTwoChars.equals("${") || stringToPrefix.charAt(stringToPrefix.length()-1) == '$') { 1419 return true; 1420 } 1421 } 1422 return false; 1423 } 1424 1438 private String getTaskStringFromDocumentStringToPrefix(String aDocumentStringToPrefix) { 1439 1440 int lessThanIndex = aDocumentStringToPrefix.lastIndexOf('<'); 1441 1442 if(lessThanIndex > -1) { 1443 String taskString = aDocumentStringToPrefix.trim(); 1444 taskString = taskString.substring(lessThanIndex+1, taskString.length()); 1445 int index = taskString.indexOf(' '); 1446 if(index > 0) { 1447 taskString = taskString.substring(0, index); 1448 } 1449 index = taskString.indexOf('\n'); 1450 if(index > 0) { 1451 taskString = taskString.substring(0, index); 1452 } 1453 index = taskString.indexOf('\r'); 1454 if(index > 0) { 1455 taskString = taskString.substring(0, index); 1456 } 1457 return taskString; 1458 } 1459 1460 return null; 1461 } 1462 1463 1464 1471 public static String getAttributeStringFromDocumentStringToPrefix(String docStringToPrefix) { 1472 int index = docStringToPrefix.lastIndexOf('='); 1473 if (index == -1) { 1474 return null; 1475 } 1476 String subString = docStringToPrefix.substring(0, index); 1477 subString = subString.trim(); 1478 1479 index = subString.lastIndexOf(' '); 1480 if(index > 0) { 1481 subString = subString.substring(index+1, subString.length()); 1482 } 1483 index = subString.lastIndexOf('\n'); 1484 if(index > 0) { 1485 subString = subString.substring(index+1, subString.length()); 1486 } 1487 index = subString.lastIndexOf('\r'); 1488 if(index > 0) { 1489 subString = subString.substring(index+1, subString.length()); 1490 } 1491 return trimBeginning(subString); 1492 } 1493 1494 private static String trimBeginning(String toBeTrimmed) { 1495 int i= 0; 1496 while ((i != toBeTrimmed.length()) && Character.isWhitespace(toBeTrimmed.charAt(i))) { 1497 i++; 1498 } 1499 return toBeTrimmed.substring(i); 1500 } 1501 1502 1503 1506 protected boolean isKnownElement(String elementName) { 1507 if (elementName.equals("target") || elementName.equals("project")) { return true; 1509 } 1510 AntProjectNode node= antModel.getProjectNode(); 1511 if (node != null) { 1512 Project antProject= node.getProject(); 1513 ComponentHelper helper= ComponentHelper.getComponentHelper(antProject); 1514 if (helper.getDefinition(elementName) != null) { 1515 return true; 1516 } 1517 if (helper.getDefinition(antModel.getNamespaceCorrectName(elementName)) != null) { 1518 return true; 1519 } 1520 if (getDtd().getElement(elementName) != null) { 1522 return true; 1523 } 1524 1525 if (getNestedType() != null) { 1526 return true; 1527 } 1528 } 1529 1530 return false; 1531 } 1532 1533 private Class getTaskClass(String taskName) { 1534 Class clss= null; 1535 AntProjectNode node= antModel.getProjectNode(); 1536 if (node != null) { 1537 Project antProject= node.getProject(); 1538 Map tasksAndTypes= ComponentHelper.getComponentHelper(antProject).getAntTypeTable(); 1539 clss= (Class )tasksAndTypes.get(taskName); 1540 if (clss == null) { 1541 clss= (Class )tasksAndTypes.get(antModel.getNamespaceCorrectName(taskName)); 1542 } 1543 } 1544 return clss; 1545 } 1546 1547 1552 protected String getParentName(IDocument document, int aLineNumber, int aColumnNumber) { 1553 if (document.getLength() == 0) { 1554 return null; 1555 } 1556 AntProjectNode project= antModel.getProjectNode(); 1557 if (project == null) { 1558 return null; 1559 } 1560 int offset= getOffset(document, aLineNumber, aColumnNumber); 1561 if (offset == -1) { 1562 return null; 1563 } 1564 AntElementNode node= project.getNode(offset); 1565 if (node == null) { 1566 node= antModel.getOpenElement(); 1567 } 1568 if (node == null) { 1569 return ""; } else if (node instanceof AntTaskNode) { 1571 String name= node.getName(); 1572 if (offset <= node.getOffset() + name.length() - 1) { 1573 node= node.getParentNode(); 1575 } else { 1576 return name; 1577 } 1578 } 1579 if (node instanceof AntTaskNode) { 1580 return node.getName(); 1581 } else if (node instanceof AntTargetNode) { 1582 return "target"; } else { 1584 return "project"; } 1586 } 1587 1588 1593 private Map findPropertiesFromDocument() { 1594 Project project= antModel.getProjectNode().getProject(); 1595 return project.getProperties(); 1596 } 1597 1598 private Map getTargets() { 1599 Project project = antModel.getProjectNode().getProject(); 1600 return project.getTargets(); 1601 } 1602 1603 protected File getEditedFile() { 1604 IWorkbenchPage page= AntUIPlugin.getActivePage(); 1605 if (page == null) { 1606 return null; 1607 } 1608 IEditorPart editor= page.getActiveEditor(); 1609 if (editor == null) { 1610 return null; 1611 } 1612 FileEditorInput input = (FileEditorInput) editor.getEditorInput(); 1613 String projectPath = input.getFile().getProject().getLocation().toFile().getAbsolutePath(); 1614 String projectRelativeFilePath = input.getFile().getFullPath().removeFirstSegments(1).makeRelative().toString(); 1615 return new File (projectPath + File.separator + projectRelativeFilePath); 1616 } 1617 1618 private String getOpenElementName() { 1619 AntElementNode node= antModel.getOpenElement(); 1620 if (node == null) { 1621 return null; 1622 } 1623 return node.getName(); 1624 } 1625 1626 1632 private String getEnclosingTargetName(IDocument document, int aLineNumber, int aColumnNumber) { 1633 1634 AntProjectNode project= antModel.getProjectNode(); 1635 int offset= getOffset(document, aLineNumber, aColumnNumber); 1636 if(offset == -1) { 1637 return null; 1638 } 1639 AntElementNode node= project.getNode(offset); 1640 if (node instanceof AntTaskNode) { 1641 node= node.getParentNode(); 1642 if (!(node instanceof AntTargetNode)) { 1643 node= null; 1645 } 1646 } else if (node instanceof AntProjectNode) { 1647 node= null; 1648 } 1649 String targetName = null; 1650 if(node == null 1651 || (targetName = ((AntTargetNode)node).getTarget().getName()) == null 1652 || targetName.length() == 0) { 1653 return null; 1654 } 1655 return targetName; 1656 } 1657 1658 private int getOffset(IDocument document, int line, int column) { 1659 try { 1660 return document.getLineOffset(line ) + column - 1; 1661 } catch (BadLocationException e) { 1662 return -1; 1663 } 1664 } 1665 1666 1672 public void setCompletionProposalAutoActivationCharacters(char[] activationSet) { 1673 autoActivationChars= activationSet; 1674 } 1675 1676 1679 protected String extractPrefix(ITextViewer textViewer, int offset) { 1680 return getPrefixFromDocument(textViewer.getDocument().get(), offset); 1681 } 1682 1683 1687 protected int getRelevance(Template template, String prefix) { 1688 if (prefix.startsWith("<")) prefix= prefix.substring(1); 1690 if (template.getName().startsWith(prefix)) 1691 return 90; 1692 return 0; 1693 } 1694 1695 1698 protected Template[] getTemplates(String contextTypeId) { 1699 return AntTemplateAccess.getDefault().getTemplateStore().getTemplates(contextTypeId); 1700 } 1701 1702 1705 protected TemplateContextType getContextType(ITextViewer textViewer, IRegion region) { 1706 switch (determineProposalMode(textViewer.getDocument(), cursorPosition, getCurrentPrefix())) { 1707 case PROPOSAL_MODE_TASK_PROPOSAL: 1708 if (getEnclosingTargetName(textViewer.getDocument(), lineNumber, columnNumber) == null) { 1709 return AntTemplateAccess.getDefault().getContextTypeRegistry().getContextType(TargetContextType.TARGET_CONTEXT_TYPE); 1710 } 1711 return AntTemplateAccess.getDefault().getContextTypeRegistry().getContextType(TaskContextType.TASK_CONTEXT_TYPE); 1712 case PROPOSAL_MODE_BUILDFILE: 1713 return AntTemplateAccess.getDefault().getContextTypeRegistry().getContextType(BuildFileContextType.BUILDFILE_CONTEXT_TYPE); 1714 case PROPOSAL_MODE_NONE: 1715 case PROPOSAL_MODE_ATTRIBUTE_PROPOSAL: 1716 case PROPOSAL_MODE_TASK_PROPOSAL_CLOSING: 1717 case PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL: 1718 case PROPOSAL_MODE_PROPERTY_PROPOSAL: 1719 case PROPOSAL_MODE_NESTED_ELEMENT_PROPOSAL: 1720 default : 1721 return null; 1722 } 1723 } 1724 1725 1728 protected Image getImage(Template template) { 1729 return AntUIImages.getImage(IAntUIConstants.IMG_TEMPLATE_PROPOSAL); 1730 } 1731 1732 1735 protected TemplateContext createContext(ITextViewer contextViewer, IRegion region) { 1736 TemplateContextType contextType= getContextType(contextViewer, region); 1737 if (contextType != null) { 1738 Point selection= contextViewer.getSelectedRange(); 1739 Position position; 1740 if (selection.y > 0) { 1741 position= new Position(selection.x, selection.y); 1742 } else { 1743 position= new Position(region.getOffset(), region.getLength()); 1744 } 1745 1746 IDocument document= contextViewer.getDocument(); 1747 return new AntContext(contextType, document, antModel, position); 1748 } 1749 return null; 1750 } 1751 1752 1755 protected ICompletionProposal createProposal(Template template,TemplateContext context, IRegion region, int relevance) { 1756 AntTemplateProposal proposal= new AntTemplateProposal(template, context, region, getImage(template), relevance); 1757 proposal.setInformationControlCreator(new AntTemplateInformationControlCreator()); 1758 return proposal; 1759 } 1760 1761 protected ISchema getDtd() { 1762 if (fgDtd == null) { 1763 IRunnableWithProgress runnable= new IRunnableWithProgress() { 1764 public void run(IProgressMonitor monitor) 1765 throws InvocationTargetException , InterruptedException { 1766 try { 1767 fgDtd= parseDtd(); 1768 } catch (IOException e) { 1769 AntUIPlugin.log(e); 1770 } catch (ParseError e) { 1771 AntUIPlugin.log(e); 1772 } 1773 } 1774 }; 1775 1776 IProgressService service= PlatformUI.getWorkbench().getProgressService(); 1777 try { 1778 service.busyCursorWhile(runnable); 1779 } catch (InvocationTargetException e) { 1780 } catch (InterruptedException e) { 1781 } 1782 } 1783 return fgDtd; 1784 } 1785 1786 1789 private TaskDescriptionProvider getDescriptionProvider() { 1790 return TaskDescriptionProvider.getDefault(); 1791 } 1792 1793 protected static void resetCodeCompletionDataStructures() { 1794 fgDtd= null; 1795 TaskDescriptionProvider.reset(); 1796 } 1797 1798 1801 public void assistSessionStarted(ContentAssistEvent event) { 1802 IContentAssistant assistant= event.assistant; 1803 if (assistant instanceof IContentAssistantExtension2) { 1804 fContentAssistant= (IContentAssistantExtension2) assistant; 1805 } 1806 } 1807 1808 1811 public void assistSessionEnded(ContentAssistEvent event) { 1812 fContentAssistant= null; 1813 fTemplatesOnly= false; 1814 } 1815 1816 1819 public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) { 1820 } 1821 1822 private String getIterationGestureMessage(String showMessage) { 1823 final IBindingService bindingSvc= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class); 1824 TriggerSequence[] triggers= bindingSvc.getActiveBindingsFor(getContentAssistCommand()); 1825 String message; 1826 if (triggers.length > 0) { 1827 message= MessageFormat.format(AntEditorMessages.getString("AntEditorCompletionProcessor.63"), new Object [] { triggers[0].format(), showMessage }); } else { 1829 message= MessageFormat.format(AntEditorMessages.getString("AntEditorCompletionProcessor.64"), new String [] {showMessage}); } 1831 return message; 1832 } 1833 1834 private ParameterizedCommand getContentAssistCommand() { 1835 final ICommandService commandSvc= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class); 1836 final Command command= commandSvc.getCommand(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); 1837 ParameterizedCommand pCmd= new ParameterizedCommand(command, null); 1838 return pCmd; 1839 } 1840} | Popular Tags |