|
Lines 12-21
Link Here
|
| 12 |
|
12 |
|
| 13 |
import java.util.ArrayList; |
13 |
import java.util.ArrayList; |
| 14 |
import java.util.Arrays; |
14 |
import java.util.Arrays; |
| 15 |
import java.util.Collections; |
|
|
| 16 |
import java.util.HashMap; |
15 |
import java.util.HashMap; |
| 17 |
import java.util.Iterator; |
16 |
import java.util.Iterator; |
| 18 |
import java.util.List; |
17 |
import java.util.List; |
|
|
18 |
import java.util.Set; |
| 19 |
import java.util.TreeSet; |
| 19 |
import java.util.Vector; |
20 |
import java.util.Vector; |
| 20 |
|
21 |
|
| 21 |
import org.eclipse.core.runtime.Path; |
22 |
import org.eclipse.core.runtime.Path; |
|
Lines 43-48
Link Here
|
| 43 |
import org.eclipse.jst.jsp.ui.internal.editor.JSPEditorPluginImageHelper; |
44 |
import org.eclipse.jst.jsp.ui.internal.editor.JSPEditorPluginImageHelper; |
| 44 |
import org.eclipse.jst.jsp.ui.internal.editor.JSPEditorPluginImages; |
45 |
import org.eclipse.jst.jsp.ui.internal.editor.JSPEditorPluginImages; |
| 45 |
import org.eclipse.jst.jsp.ui.internal.templates.TemplateContextTypeIdsJSP; |
46 |
import org.eclipse.jst.jsp.ui.internal.templates.TemplateContextTypeIdsJSP; |
|
|
47 |
import org.eclipse.swt.graphics.Image; |
| 46 |
import org.eclipse.wst.css.ui.internal.contentassist.CSSContentAssistProcessor; |
48 |
import org.eclipse.wst.css.ui.internal.contentassist.CSSContentAssistProcessor; |
| 47 |
import org.eclipse.wst.html.core.internal.contentmodel.JSPCMDocument; |
49 |
import org.eclipse.wst.html.core.internal.contentmodel.JSPCMDocument; |
| 48 |
import org.eclipse.wst.html.core.text.IHTMLPartitions; |
50 |
import org.eclipse.wst.html.core.text.IHTMLPartitions; |
|
Lines 72-77
Link Here
|
| 72 |
import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryRegistry; |
74 |
import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryRegistry; |
| 73 |
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument; |
75 |
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument; |
| 74 |
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration; |
76 |
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration; |
|
|
77 |
import org.eclipse.wst.xml.core.internal.contentmodel.CMNode; |
| 75 |
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery; |
78 |
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery; |
| 76 |
import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil; |
79 |
import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil; |
| 77 |
import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser; |
80 |
import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser; |
|
Lines 88-93
Link Here
|
| 88 |
import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentAssistProcessor; |
91 |
import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentAssistProcessor; |
| 89 |
import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentAssistUtilities; |
92 |
import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentAssistUtilities; |
| 90 |
import org.eclipse.wst.xml.ui.internal.contentassist.XMLRelevanceConstants; |
93 |
import org.eclipse.wst.xml.ui.internal.contentassist.XMLRelevanceConstants; |
|
|
94 |
import org.eclipse.wst.xml.ui.internal.editor.CMImageUtil; |
| 95 |
import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper; |
| 96 |
import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages; |
| 91 |
import org.w3c.dom.Attr; |
97 |
import org.w3c.dom.Attr; |
| 92 |
import org.w3c.dom.Document; |
98 |
import org.w3c.dom.Document; |
| 93 |
import org.w3c.dom.Element; |
99 |
import org.w3c.dom.Element; |
|
Lines 245-282
Link Here
|
| 245 |
ITextRegion nameRegion = null; |
251 |
ITextRegion nameRegion = null; |
| 246 |
while (i >= 0) { |
252 |
while (i >= 0) { |
| 247 |
nameRegion = openRegions.get(i--); |
253 |
nameRegion = openRegions.get(i--); |
| 248 |
if (nameRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) |
254 |
if (nameRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) { |
| 249 |
break; |
255 |
break; |
|
|
256 |
} |
| 250 |
} |
257 |
} |
| 251 |
|
258 |
|
| 252 |
// on an empty value, add all the JSP and taglib tags |
|
|
| 253 |
CMElementDeclaration elementDecl = getCMElementDeclaration(node); |
259 |
CMElementDeclaration elementDecl = getCMElementDeclaration(node); |
| 254 |
if (nameRegion != null && elementDecl != null) { |
260 |
if (nameRegion != null && elementDecl != null) { |
| 255 |
String attributeName = open.getText(nameRegion); |
261 |
String attributeName = open.getText(nameRegion); |
| 256 |
if (attributeName != null) { |
262 |
if (attributeName != null) { |
| 257 |
String currentValue = node.getAttributes().getNamedItem(attributeName).getNodeValue(); |
263 |
Node parent = contentAssistRequest.getParent(); |
| 258 |
|
264 |
|
| 259 |
if(currentValue == null || currentValue.length() == 0) { //$NON-NLS-1$ |
265 |
//ignore starte quote in match string |
| 260 |
List additionalElements = ModelQueryUtil.getModelQuery(node.getOwnerDocument()).getAvailableContent((Element) node, elementDecl, ModelQuery.INCLUDE_ATTRIBUTES); |
266 |
String matchString = contentAssistRequest.getMatchString().trim(); |
| 261 |
for (i = 0; i < additionalElements.size(); i++) { |
267 |
if(matchString.startsWith("'") || matchString.startsWith("\"")) { |
| 262 |
Object additionalElement = additionalElements.get(i); |
268 |
matchString = matchString.substring(1); |
| 263 |
if(additionalElement instanceof CMElementDeclaration) { |
269 |
} |
| 264 |
CMElementDeclaration ed = (CMElementDeclaration) additionalElement; |
270 |
|
| 265 |
|
271 |
//get all the proposals |
|
|
272 |
List additionalElements = ModelQueryUtil.getModelQuery(node.getOwnerDocument()).getAvailableContent((Element) node, elementDecl, 0); |
| 273 |
Iterator nodeIterator = additionalElements.iterator(); |
| 274 |
|
| 275 |
//check each suggestion |
| 276 |
while (nodeIterator.hasNext()) { |
| 277 |
CMNode additionalElementDecl = (CMNode) nodeIterator.next(); |
| 278 |
if (additionalElementDecl != null && additionalElementDecl instanceof CMElementDeclaration) { |
| 279 |
CMElementDeclaration ed = (CMElementDeclaration) additionalElementDecl; |
| 280 |
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=89811 |
| 281 |
StringBuffer sb = new StringBuffer(); |
| 282 |
getContentGenerator().generateTag(parent, ed, sb); |
| 283 |
|
| 284 |
String proposedText = sb.toString(); |
| 285 |
|
| 286 |
//filter out any proposals that dont match matchString |
| 287 |
if (beginsWith(proposedText, matchString)) { |
| 288 |
//wrap with ' because JSP attributes are warped with " |
| 289 |
proposedText = "'" + proposedText; |
| 290 |
|
| 291 |
//if its a container its possible the closing quote is already there |
| 292 |
//don't want to risk injecting an extra |
| 293 |
if(!(contentAssistRequest.getRegion() instanceof ITextRegionContainer)) { |
| 294 |
proposedText += "'"; |
| 295 |
} |
| 296 |
|
| 297 |
Image image = CMImageUtil.getImage(elementDecl); |
| 298 |
if (image == null) { |
| 299 |
image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC); |
| 300 |
} |
| 301 |
|
| 302 |
//create the proposal |
| 303 |
int cursorAdjustment = getCursorPositionForProposedText(proposedText); |
| 304 |
String proposedInfo = getAdditionalInfo(getCMElementDeclaration(parent), elementDecl); |
| 266 |
String tagname = getContentGenerator().getRequiredName(node, ed); |
305 |
String tagname = getContentGenerator().getRequiredName(node, ed); |
| 267 |
StringBuffer contents = new StringBuffer("\""); //$NON-NLS-1$ |
306 |
CustomCompletionProposal proposal = new CustomCompletionProposal( |
| 268 |
getContentGenerator().generateTag(node, ed, contents); |
307 |
proposedText, contentAssistRequest.getReplacementBeginPosition(), |
| 269 |
contents.append('"'); //$NON-NLS-1$ |
308 |
contentAssistRequest.getReplacementLength(), cursorAdjustment, image, tagname, null, proposedInfo, |
| 270 |
CustomCompletionProposal proposal = new CustomCompletionProposal(contents.toString(), contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), contents.length(), JSPEditorPluginImageHelper.getInstance().getImage(JSPEditorPluginImages.IMG_OBJ_TAG_GENERIC), tagname, null, null, XMLRelevanceConstants.R_JSP_ATTRIBUTE_VALUE); |
309 |
XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE); |
| 271 |
contentAssistRequest.addProposal(proposal); |
310 |
contentAssistRequest.addProposal(proposal); |
| 272 |
} |
311 |
} |
| 273 |
} |
312 |
} |
| 274 |
|
|
|
| 275 |
} |
313 |
} |
| 276 |
} |
314 |
} |
| 277 |
} |
315 |
} |
| 278 |
|
316 |
else if (contentAssistRequest.getRegion().getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) { |
| 279 |
if (contentAssistRequest.getRegion().getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) { |
|
|
| 280 |
try { |
317 |
try { |
| 281 |
// Create a new model for Content Assist to operate on. This |
318 |
// Create a new model for Content Assist to operate on. This |
| 282 |
// will simulate |
319 |
// will simulate |
|
Lines 400-407
Link Here
|
| 400 |
Logger.logException("Error in embedded JSP Content Assist", e); //$NON-NLS-1$ |
437 |
Logger.logException("Error in embedded JSP Content Assist", e); //$NON-NLS-1$ |
| 401 |
} |
438 |
} |
| 402 |
} |
439 |
} |
| 403 |
|
|
|
| 404 |
|
| 405 |
} |
440 |
} |
| 406 |
|
441 |
|
| 407 |
/** |
442 |
/** |
|
Lines 668-702
Link Here
|
| 668 |
} |
703 |
} |
| 669 |
} |
704 |
} |
| 670 |
|
705 |
|
| 671 |
// check if it's in an attribute value, if so, don't add CDATA |
706 |
//get the embedded results |
| 672 |
// proposal |
|
|
| 673 |
ITextRegion attrContainer = (fn != null) ? fn.getRegionAtCharacterOffset(documentPosition) : null; |
| 674 |
if (attrContainer != null && attrContainer instanceof ITextRegionContainer) { |
| 675 |
if (attrContainer.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) { |
| 676 |
// test location of the cursor |
| 677 |
// return null if it's in the middle of an open/close |
| 678 |
// delimeter |
| 679 |
Iterator attrRegions = ((ITextRegionContainer) attrContainer).getRegions().iterator(); |
| 680 |
ITextRegion testRegion = null; |
| 681 |
while (attrRegions.hasNext()) { |
| 682 |
testRegion = (ITextRegion) attrRegions.next(); |
| 683 |
// need to check for other valid attribute regions |
| 684 |
if (XMLContentAssistUtilities.isJSPOpenDelimiter(testRegion.getType())) { |
| 685 |
if (!(((ITextRegionContainer) attrContainer).getEndOffset(testRegion) <= documentPosition)) |
| 686 |
return EMPTY_PROPOSAL_SET; |
| 687 |
} |
| 688 |
else if (XMLContentAssistUtilities.isJSPCloseDelimiter(testRegion.getType())) { |
| 689 |
if (!(((ITextRegionContainer) attrContainer).getStartOffset(testRegion) >= documentPosition)) |
| 690 |
return EMPTY_PROPOSAL_SET; |
| 691 |
} |
| 692 |
} |
| 693 |
// TODO: handle non-Java code such as nested tags |
| 694 |
if (testRegion.getType().equals(DOMJSPRegionContexts.JSP_CONTENT)) |
| 695 |
return getJSPJavaCompletionProposals(viewer, documentPosition); |
| 696 |
return EMPTY_PROPOSAL_SET; |
| 697 |
} |
| 698 |
} |
| 699 |
|
| 700 |
IContentAssistProcessor p = (IContentAssistProcessor) fPartitionToProcessorMap.get(partitionType); |
707 |
IContentAssistProcessor p = (IContentAssistProcessor) fPartitionToProcessorMap.get(partitionType); |
| 701 |
if (p != null) { |
708 |
if (p != null) { |
| 702 |
embeddedResults = p.computeCompletionProposals(viewer, documentPosition); |
709 |
embeddedResults = p.computeCompletionProposals(viewer, documentPosition); |
|
Lines 721-741
Link Here
|
| 721 |
fTemplateContexts.clear(); |
728 |
fTemplateContexts.clear(); |
| 722 |
jspResults = super.computeCompletionProposals(viewer, documentPosition); |
729 |
jspResults = super.computeCompletionProposals(viewer, documentPosition); |
| 723 |
} |
730 |
} |
| 724 |
if (useEmbeddedResults) { |
731 |
|
| 725 |
if (embeddedResults != null && embeddedResults.length > 0) { |
732 |
//merge the embedded results |
| 726 |
List results = new ArrayList(); |
733 |
if (useEmbeddedResults && embeddedResults != null && embeddedResults.length > 0) { |
| 727 |
for (int i = 0; i < embeddedResults.length; i++) |
734 |
jspResults = merge(jspResults, embeddedResults); |
| 728 |
results.add(embeddedResults[i]); |
|
|
| 729 |
if (jspResults != null) { |
| 730 |
for (int i = 0; i < jspResults.length; i++) |
| 731 |
results.add(jspResults[i]); |
| 732 |
} |
| 733 |
jspResults = new ICompletionProposal[results.size()]; |
| 734 |
Collections.sort(results, new ProposalComparator()); |
| 735 |
for (int i = 0; i < results.size(); i++) |
| 736 |
jspResults[i] = (ICompletionProposal) results.get(i); |
| 737 |
|
| 738 |
} |
| 739 |
} |
735 |
} |
| 740 |
if (jspResults == null) |
736 |
if (jspResults == null) |
| 741 |
jspResults = EMPTY_PROPOSAL_SET; |
737 |
jspResults = EMPTY_PROPOSAL_SET; |
|
Lines 793-814
Link Here
|
| 793 |
} |
789 |
} |
| 794 |
|
790 |
|
| 795 |
/** |
791 |
/** |
| 796 |
* Adds 2 arrays of ICompletionProposals and sorts them with a |
792 |
* Adds 2 arrays of {@link ICompletionProposal}s to a {@link TreeSet} |
| 797 |
* ProposalComparator. |
793 |
* eliminating duplicates and sorting with a {@link ProposalComparator} |
|
|
794 |
* then returning the new merged, filtered, sorted, array of {@link ICompletionProposal}s. |
| 798 |
* |
795 |
* |
| 799 |
* @param jspResults |
796 |
* @param proposalsOne |
| 800 |
* @param htmlResults |
797 |
* @param proposalsTwo |
| 801 |
* @return |
798 |
* @return a new merged, filtered, sorted array of {@link ICompletionProposal}s created from |
|
|
799 |
* the two given arrays of {@link ICompletionProposal}s. |
| 802 |
*/ |
800 |
*/ |
| 803 |
private ICompletionProposal[] merge(ICompletionProposal[] jspResults, ICompletionProposal[] htmlResults) { |
801 |
private ICompletionProposal[] merge(ICompletionProposal[] proposalsOne, ICompletionProposal[] proposalsTwo) { |
| 804 |
List results = new ArrayList(); |
802 |
Set results = new TreeSet(new ProposalComparator()); |
| 805 |
List jsps = Arrays.asList(jspResults); |
803 |
List proposalsOneList = Arrays.asList(proposalsOne); |
| 806 |
List htmls = Arrays.asList(htmlResults); |
804 |
List proposalsTwoList = Arrays.asList(proposalsTwo); |
| 807 |
|
805 |
|
| 808 |
results.addAll(jsps); |
806 |
results.addAll(proposalsOneList); |
| 809 |
results.addAll(htmls); |
807 |
results.addAll(proposalsTwoList); |
| 810 |
|
808 |
|
| 811 |
Collections.sort(results, new ProposalComparator()); |
|
|
| 812 |
return (ICompletionProposal[]) results.toArray(new ICompletionProposal[results.size()]); |
809 |
return (ICompletionProposal[]) results.toArray(new ICompletionProposal[results.size()]); |
| 813 |
} |
810 |
} |
| 814 |
|
811 |
|
|
Lines 1135-1138
Link Here
|
| 1135 |
addTemplates(contentAssistRequest, TemplateContextTypeIdsJSP.TAG); |
1132 |
addTemplates(contentAssistRequest, TemplateContextTypeIdsJSP.TAG); |
| 1136 |
//don't need to call super here because otherwise we duplicate what the HTMLCOntentAssistProcessor that is running is already doing |
1133 |
//don't need to call super here because otherwise we duplicate what the HTMLCOntentAssistProcessor that is running is already doing |
| 1137 |
} |
1134 |
} |
|
|
1135 |
|
| 1136 |
/** |
| 1137 |
* Different behavior if in {@link DOMRegionContext#XML_TAG_ATTRIBUTE_VALUE} region |
| 1138 |
* otherwise calls {@link AbstractContentAssistProcessor#getMatchString(IStructuredDocumentRegion, ITextRegion, int)} |
| 1139 |
* |
| 1140 |
* @see org.eclipse.wst.xml.ui.internal.contentassist.AbstractContentAssistProcessor#getMatchString(org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion, org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion, int) |
| 1141 |
*/ |
| 1142 |
protected String getMatchString(IStructuredDocumentRegion parent, |
| 1143 |
ITextRegion aRegion, int offset) { |
| 1144 |
|
| 1145 |
String matchString = null; |
| 1146 |
|
| 1147 |
if ((aRegion == null) || isCloseRegion(aRegion)) { |
| 1148 |
matchString = ""; //$NON-NLS-1$ |
| 1149 |
} else { |
| 1150 |
String regionType = aRegion.getType(); |
| 1151 |
/* |
| 1152 |
* if attribute value then check to see if ' or " is in region and if so |
| 1153 |
* don't count it as part of match string |
| 1154 |
*/ |
| 1155 |
if(regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) { |
| 1156 |
if(aRegion instanceof ITextRegionContainer) { |
| 1157 |
ITextRegionContainer attrValueContainer = (ITextRegionContainer)aRegion; |
| 1158 |
int matchStartIndex = 0; |
| 1159 |
if(attrValueContainer.getFirstRegion().getType() == DOMJSPRegionContexts.XML_TAG_ATTRIBUTE_VALUE_DQUOTE || |
| 1160 |
attrValueContainer.getFirstRegion().getType() == DOMJSPRegionContexts.XML_TAG_ATTRIBUTE_VALUE_SQUOTE) { |
| 1161 |
|
| 1162 |
matchStartIndex = attrValueContainer.getRegions().get(1).getStart(); |
| 1163 |
} |
| 1164 |
|
| 1165 |
matchString = parent.getText(aRegion).substring(matchStartIndex, offset - parent.getStartOffset(aRegion)); |
| 1166 |
} else { |
| 1167 |
matchString = parent.getText(aRegion).substring(0, offset - parent.getStartOffset(aRegion)); |
| 1168 |
if(matchString.charAt(0) == '\'' || matchString.charAt(0) == '\"') { |
| 1169 |
matchString = matchString.substring(1); |
| 1170 |
} |
| 1171 |
} |
| 1172 |
} |
| 1173 |
} |
| 1174 |
|
| 1175 |
if(matchString == null) { |
| 1176 |
matchString = super.getMatchString(parent, aRegion, offset); |
| 1177 |
} |
| 1178 |
return matchString; |
| 1179 |
} |
| 1138 |
} |
1180 |
} |