diff options
Diffstat (limited to 'bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractContentAssistProcessor.java')
-rw-r--r-- | bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractContentAssistProcessor.java | 2332 |
1 files changed, 0 insertions, 2332 deletions
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractContentAssistProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractContentAssistProcessor.java deleted file mode 100644 index 4438385200..0000000000 --- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/contentassist/AbstractContentAssistProcessor.java +++ /dev/null @@ -1,2332 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2004 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.xml.ui.internal.contentassist; - -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.Properties; -import java.util.Vector; - -import org.eclipse.jface.text.ITextViewer; -import org.eclipse.jface.text.contentassist.ICompletionProposal; -import org.eclipse.jface.text.contentassist.IContentAssistProcessor; -import org.eclipse.jface.text.contentassist.IContextInformation; -import org.eclipse.jface.text.contentassist.IContextInformationValidator; -import org.eclipse.osgi.util.NLS; -import org.eclipse.swt.graphics.Image; -import org.eclipse.wst.sse.core.StructuredModelManager; -import org.eclipse.wst.sse.core.internal.encoding.ContentTypeEncodingPreferences; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList; -import org.eclipse.wst.sse.core.internal.util.Debug; -import org.eclipse.wst.sse.ui.internal.IReleasable; -import org.eclipse.wst.sse.ui.internal.StructuredTextViewer; -import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils; -import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal; -import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration; -import org.eclipse.wst.xml.core.internal.contentmodel.CMContent; -import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType; -import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument; -import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration; -import org.eclipse.wst.xml.core.internal.contentmodel.CMEntityDeclaration; -import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup; -import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap; -import org.eclipse.wst.xml.core.internal.contentmodel.CMNode; -import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList; -import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery; -import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryAction; -import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper; -import org.eclipse.wst.xml.core.internal.document.AttrImpl; -import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil; -import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; -import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext; -import org.eclipse.wst.xml.ui.internal.Logger; -import org.eclipse.wst.xml.ui.internal.XMLUIMessages; -import org.eclipse.wst.xml.ui.internal.XMLUIPlugin; -import org.eclipse.wst.xml.ui.internal.editor.CMImageUtil; -import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper; -import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages; -import org.eclipse.wst.xml.ui.internal.preferences.XMLUIPreferenceNames; -import org.eclipse.wst.xml.ui.internal.taginfo.MarkupTagInfoProvider; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.DocumentType; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -abstract public class AbstractContentAssistProcessor implements IContentAssistProcessor, IReleasable { - /** - * ISSUE: this is a bit of hidden JSP knowledge that was implemented this - * way for expedency. Should be evolved in future to depend on - * "nestedContext". - */ - private class DOMJSPRegionContextsPrivateCopy { - private static final String JSP_CLOSE = "JSP_CLOSE"; //$NON-NLS-1$ - private static final String JSP_COMMENT_CLOSE = "JSP_COMMENT_CLOSE"; //$NON-NLS-1$ - - private static final String JSP_COMMENT_OPEN = "JSP_COMMENT_OPEN"; //$NON-NLS-1$ - private static final String JSP_DECLARATION_OPEN = "JSP_DECLARATION_OPEN"; //$NON-NLS-1$ - private static final String JSP_DIRECTIVE_CLOSE = "JSP_DIRECTIVE_CLOSE"; //$NON-NLS-1$ - private static final String JSP_DIRECTIVE_NAME = "JSP_DIRECTIVE_NAME"; //$NON-NLS-1$ - - private static final String JSP_DIRECTIVE_OPEN = "JSP_DIRECTIVE_OPEN"; //$NON-NLS-1$ - private static final String JSP_EXPRESSION_OPEN = "JSP_EXPRESSION_OPEN"; //$NON-NLS-1$ - - private static final String JSP_ROOT_TAG_NAME = "JSP_ROOT_TAG_NAME"; //$NON-NLS-1$ - - private static final String JSP_SCRIPTLET_OPEN = "JSP_SCRIPTLET_OPEN"; //$NON-NLS-1$ - - } - - protected static final String INTERNALERROR = XMLUIMessages.SEVERE_internal_error_occu_UI_; - protected static final String UNKNOWN_ATTR = XMLUIMessages.No_known_attribute__UI_; - protected static final String UNKNOWN_CONTEXT = XMLUIMessages.Content_Assist_not_availab_UI_; - protected char completionProposalAutoActivationCharacters[] = null; - protected char contextInformationAutoActivationCharacters[] = null; - private AttributeContextInformationProvider fAttributeInfoProvider = null; - private AttributeContextInformationPresenter fContextInformationPresenter = null; - - protected String fErrorMessage = null; - protected XMLContentModelGenerator fGenerator; - // protected IResource resource = null; - protected MarkupTagInfoProvider fInfoProvider = null; - protected ITextViewer fTextViewer = null; - - private final boolean showValues = true; - - public AbstractContentAssistProcessor() { - init(); - } - - protected void addAttributeNameProposals(ContentAssistRequest contentAssistRequest) { - IDOMNode node = (IDOMNode) contentAssistRequest.getNode(); - IStructuredDocumentRegion sdRegion = contentAssistRequest.getDocumentRegion(); - // retrieve the list of attributes - CMElementDeclaration elementDecl = getCMElementDeclaration(node); - if (elementDecl != null) { - CMNamedNodeMap attributes = elementDecl.getAttributes(); - String matchString = contentAssistRequest.getMatchString(); - - // check whether an attribute really exists for the replacement - // offsets AND if it possesses a value - boolean attrAtLocationHasValue = false; - NamedNodeMap attrs = node.getAttributes(); - for (int i = 0; i < attrs.getLength(); i++) { - AttrImpl existingAttr = (AttrImpl) attrs.item(i); - ITextRegion name = existingAttr.getNameRegion(); - - if (sdRegion.getStartOffset(name) <= contentAssistRequest.getReplacementBeginPosition() && sdRegion.getStartOffset(name) + name.getLength() >= contentAssistRequest.getReplacementBeginPosition() + contentAssistRequest.getReplacementLength() && existingAttr.getValueRegion() != null) { - attrAtLocationHasValue = true; - break; - } - } - - // only add proposals for the attributes whose names begin with - // the matchstring - if (attributes != null) { - for (int i = 0; i < attributes.getLength(); i++) { - CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) attributes.item(i); - - int isRequired = 0; - if (attrDecl.getUsage() == CMAttributeDeclaration.REQUIRED) { - isRequired = XMLRelevanceConstants.R_REQUIRED; - } - - boolean showAttribute = true; - showAttribute = showAttribute && beginsWith(getRequiredName(node, attrDecl), matchString.trim()); - AttrImpl attr = (AttrImpl) node.getAttributes().getNamedItem(getRequiredName(node, attrDecl)); - ITextRegion nameRegion = attr != null ? attr.getNameRegion() : null; - // nameRegion.getEndOffset() + 1 is required to allow for - // matches against the full name of an existing Attr - showAttribute = showAttribute && ((attr == null) || (nameRegion != null && sdRegion.getStartOffset(nameRegion) <= contentAssistRequest.getReplacementBeginPosition() && sdRegion.getStartOffset(nameRegion) + nameRegion.getLength() >= contentAssistRequest.getReplacementBeginPosition() + contentAssistRequest.getReplacementLength())); - if (showAttribute) { - Image attrImage = CMImageUtil.getImage(attrDecl); - if (attrImage == null) { - if (isRequired > 0) { - attrImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATT_REQ_OBJ); - } - else { - attrImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE); - } - } - - String proposedText = null; - String proposedInfo = getAdditionalInfo(elementDecl, attrDecl); - CustomCompletionProposal proposal = null; - // attribute is at this location and already exists - if (attrAtLocationHasValue) { - // only propose the name - proposedText = getRequiredName(node, attrDecl); - proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), proposedText.length(), attrImage, proposedText, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_NAME + isRequired, true); - } - // no attribute exists or is elsewhere, generate - // minimally - else { - Attr existingAttrNode = (Attr) node.getAttributes().getNamedItem(getRequiredName(node, attrDecl)); - String value = null; - if (existingAttrNode != null) - value = existingAttrNode.getNodeValue(); - if (value != null && value.length() > 0) - proposedText = getRequiredName(node, attrDecl); - else { - proposedText = getRequiredText(node, attrDecl); - } - proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), attrDecl.getNodeName().length() + 2, attrImage, - // if the value isn't empty (no empty set of - // quotes), show it - (showValues && proposedText.indexOf("\"\"") < 0) ? proposedText : getRequiredName(node, attrDecl), //$NON-NLS-1$ - null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_NAME + isRequired); - } - contentAssistRequest.addProposal(proposal); - } - } - } - } - else { - setErrorMessage(NLS.bind(XMLUIMessages.Element__is_unknown, (new Object[]{node.getNodeName()}))); - } - } - - protected void addAttributeValueProposals(ContentAssistRequest contentAssistRequest) { - - IDOMNode node = (IDOMNode) contentAssistRequest.getNode(); - - // Find the attribute region and name for which this position should - // have a value proposed - IStructuredDocumentRegion open = node.getFirstStructuredDocumentRegion(); - ITextRegionList openRegions = open.getRegions(); - int i = openRegions.indexOf(contentAssistRequest.getRegion()); - if (i < 0) - return; - ITextRegion nameRegion = null; - while (i >= 0) { - nameRegion = openRegions.get(i--); - if (nameRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) - break; - } - - // the name region is REQUIRED to do anything useful - if (nameRegion != null) { - // Retrieve the declaration - CMElementDeclaration elementDecl = getCMElementDeclaration(node); - - // String attributeName = nameRegion.getText(); - String attributeName = open.getText(nameRegion); - - CMAttributeDeclaration attrDecl = null; - - // No CMElementDeclaration means no attribute metadata, but - // retrieve the - // declaration for the attribute otherwise - if (elementDecl != null) { - CMNamedNodeMap attributes = elementDecl.getAttributes(); - String noprefixName = DOMNamespaceHelper.getUnprefixedName(attributeName); - if (attributes != null) { - attrDecl = (CMAttributeDeclaration) attributes.getNamedItem(noprefixName); - if (attrDecl == null) { - attrDecl = (CMAttributeDeclaration) attributes.getNamedItem(attributeName); - } - } - if (attrDecl == null) { - setErrorMessage(UNKNOWN_ATTR, attributeName); - } - } - - String currentValue = node.getAttributes().getNamedItem(attributeName).getNodeValue(); - String proposedInfo = null; - Image image = CMImageUtil.getImage(attrDecl); - if (image == null) { - if (attrDecl != null && attrDecl.getUsage() == CMAttributeDeclaration.REQUIRED) { - image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATT_REQ_OBJ); - } - else { - image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE); - } - } - - if (attrDecl != null && attrDecl.getAttrType() != null) { - // attribute is known, prompt with values from the declaration - proposedInfo = getAdditionalInfo(elementDecl, attrDecl); - List possibleValues = getPossibleDataTypeValues(node, attrDecl); - if (possibleValues.size() > 0) { - // ENUMERATED VALUES - String matchString = contentAssistRequest.getMatchString(); - if (matchString == null) - matchString = ""; //$NON-NLS-1$ - if (matchString.length() > 0 && (matchString.startsWith("\"") || matchString.startsWith("'"))) //$NON-NLS-2$//$NON-NLS-1$ - matchString = matchString.substring(1); - boolean currentValid = false; - - // d210858, if the region's a container, don't suggest the - // enumerated values as they probably won't help - boolean existingComplicatedValue = contentAssistRequest.getRegion() != null && contentAssistRequest.getRegion() instanceof ITextRegionContainer; - if (!existingComplicatedValue) { - for (Iterator j = possibleValues.iterator(); j.hasNext();) { - String possibleValue = (String) j.next(); - currentValid = currentValid || possibleValue.equals(currentValue); - if (matchString.length() == 0 || possibleValue.startsWith(matchString)) { - - String rString = "\"" + possibleValue + "\""; //$NON-NLS-2$//$NON-NLS-1$ - int rOffset = contentAssistRequest.getReplacementBeginPosition(); - int rLength = contentAssistRequest.getReplacementLength(); - int cursorAfter = possibleValue.length() + 1; - String displayString = "\"" + possibleValue + "\""; //$NON-NLS-2$//$NON-NLS-1$ - - CustomCompletionProposal proposal = new CustomCompletionProposal(rString, rOffset, rLength, cursorAfter, image, displayString, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE); - contentAssistRequest.addProposal(proposal); - } - } - } - } - else if ((attrDecl.getUsage() == CMAttributeDeclaration.FIXED || attrDecl.getAttrType().getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED) && attrDecl.getAttrType().getImpliedValue() != null) { - // FIXED values - String value = attrDecl.getAttrType().getImpliedValue(); - if (value != null && value.length() > 0) { - String rValue = "\"" + value + "\"";//$NON-NLS-2$//$NON-NLS-1$ - CustomCompletionProposal proposal = new CustomCompletionProposal(rValue, - contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), rValue.length() + 1, image, rValue, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE); - contentAssistRequest.addProposal(proposal); - if (currentValue.length() > 0 && !value.equals(currentValue)) { - rValue = "\"" + currentValue + "\""; //$NON-NLS-2$//$NON-NLS-1$ - proposal = new CustomCompletionProposal(rValue, - contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), rValue.length() + 1, image, rValue, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE); - contentAssistRequest.addProposal(proposal); - } - } - } - } - else { - // unknown attribute, so supply nice empty values - proposedInfo = getAdditionalInfo(null, elementDecl); - CustomCompletionProposal proposal = null; - if (currentValue != null && currentValue.length() > 0) { - String rValue = "\"" + currentValue + "\""; //$NON-NLS-2$//$NON-NLS-1$ - proposal = new CustomCompletionProposal(rValue, - contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 1, image, rValue, //$NON-NLS-2$//$NON-NLS-1$ - null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE); - contentAssistRequest.addProposal(proposal); - } - } - } - else - setErrorMessage(UNKNOWN_CONTEXT); - } - - protected void addCommentProposal(ContentAssistRequest contentAssistRequest) { - contentAssistRequest.addProposal(new CustomCompletionProposal("<!-- -->", //$NON-NLS-1$ - contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 5, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_COMMENT), NLS.bind(XMLUIMessages.Comment__, (new Object[]{" <!-- -->"})), //$NON-NLS-1$ - null, null, XMLRelevanceConstants.R_COMMENT)); - } - - /** - * Add all of the element declarations int the CMContent object into one - * big list. - */ - protected void addContent(List contentList, CMContent content) { - if (content == null) - return; - if (content instanceof CMGroup) { - CMNodeList children = ((CMGroup) content).getChildNodes(); - if (children == null) - return; - for (int i = 0; i < children.getLength(); i++) { - CMNode child = children.item(i); - if (child.getNodeType() == CMNode.ELEMENT_DECLARATION) { - contentList.add(child); - } - else { - if (child.getNodeType() == CMNode.GROUP) { - addContent(contentList, (CMContent) child); - } - else { - throw new IllegalArgumentException("Unknown content child: " + child); //$NON-NLS-1$ - } - } - } - } - else { - contentList.add(content); - } - } - - protected void addDocTypeProposal(ContentAssistRequest contentAssistRequest) { - // if a DocumentElement exists, use that for the root Element name - String rootname = "unspecified"; //$NON-NLS-1$ - if (contentAssistRequest.getNode().getOwnerDocument().getDocumentElement() != null) - rootname = contentAssistRequest.getNode().getOwnerDocument().getDocumentElement().getNodeName(); - - String proposedText = "<!DOCTYPE " + rootname + " PUBLIC \"//UNKNOWN/\" \"unknown.dtd\">"; //$NON-NLS-1$ //$NON-NLS-2$ - ICompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 10, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_DOCTYPE), "<!DOCTYPE ... >", //$NON-NLS-1$ - null, null, XMLRelevanceConstants.R_DOCTYPE); - // TODO provide special documentation on doc type - contentAssistRequest.addProposal(proposal); - } - - /** - * Add the proposals for a completely empty document - */ - protected void addEmptyDocumentProposals(ContentAssistRequest contentAssistRequest) { - // nothing - } - - /** - * Add the proposals for the name in an end tag - */ - protected void addEndTagNameProposals(ContentAssistRequest contentAssistRequest) { - - if (contentAssistRequest.getStartOffset() + contentAssistRequest.getRegion().getTextLength() < contentAssistRequest.getReplacementBeginPosition()) { - CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$ - contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" '>'"})), //$NON-NLS-1$ - null, null, XMLRelevanceConstants.R_END_TAG_NAME); - contentAssistRequest.addProposal(proposal); - } - else { - IDOMNode node = (IDOMNode) contentAssistRequest.getNode(); - ModelQuery modelQuery = ModelQueryUtil.getModelQuery(node.getOwnerDocument()); - Node aNode = contentAssistRequest.getNode(); - String matchString = contentAssistRequest.getMatchString(); - if (matchString.startsWith("</")) //$NON-NLS-1$ - matchString = matchString.substring(2); - while (aNode != null) { - if (aNode.getNodeType() == Node.ELEMENT_NODE) { - if (aNode.getNodeName().startsWith(matchString)) { - IDOMNode aXMLNode = (IDOMNode) aNode; - CMElementDeclaration ed = modelQuery.getCMElementDeclaration((Element) aNode); - if ((aXMLNode.getEndStructuredDocumentRegion() == null) && (ed == null || (ed.getContentType() != CMElementDeclaration.EMPTY))) { - String proposedText = aNode.getNodeName(); - String proposedInfo = (ed != null) ? getAdditionalInfo(null, ed) : null; - if (node.getNodeType() == Node.TEXT_NODE && !contentAssistRequest.getDocumentRegion().isEnded()) - proposedText += ">"; //$NON-NLS-1$ - CustomCompletionProposal proposal = null; - // double check to see if the region acted upon is - // a tag name; replace it if so - Image image = CMImageUtil.getImage(ed); - if (image == null) { - image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC); - } - if (contentAssistRequest.getRegion().getType() == DOMRegionContext.XML_TAG_NAME) { - proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getStartOffset(), contentAssistRequest.getRegion().getTextLength(), proposedText.length(), image, proposedText, null, proposedInfo, XMLRelevanceConstants.R_END_TAG_NAME); - } - else { - proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), proposedText.length(), image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{"'" + proposedText + "'"})), //$NON-NLS-1$ //$NON-NLS-2$ - null, proposedInfo, XMLRelevanceConstants.R_END_TAG_NAME); - } - contentAssistRequest.addProposal(proposal); - } - } - } - aNode = aNode.getParentNode(); - } - } - } - - /** - * Prompt for end tags to a non-empty Node that hasn't ended Handles these - * cases: <br> - * <tagOpen>| <br> - * <tagOpen>< |<br> - * <tagOpen></ | - * - * @param contentAssistRequest - */ - protected void addEndTagProposals(ContentAssistRequest contentAssistRequest) { - IDOMNode node = (IDOMNode) contentAssistRequest.getParent(); - - if (isCommentNode(node)) { - // loop and find non comment node parent - while (node != null && isCommentNode(node)) { - node = (IDOMNode) node.getParentNode(); - } - } - - // node is already closed - if(node.isClosed()) { - // loop and find non comment unclose node parent - while (node != null && node.isClosed()) { - node = (IDOMNode) node.getParentNode(); - } - } - // there were no unclosed tags - if(node == null) - return; - - // data to create a CustomCompletionProposal - String replaceText = node.getNodeName() + ">"; //$NON-NLS-1$ - int replaceBegin = contentAssistRequest.getReplacementBeginPosition(); - int replaceLength = contentAssistRequest.getReplacementLength(); - int cursorOffset = node.getNodeName().length() + 1; - String displayString = ""; //$NON-NLS-1$ - String proposedInfo = ""; //$NON-NLS-1$ - Image image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC); - - setErrorMessage(null); - boolean addProposal = false; - - if (node.getNodeType() == Node.ELEMENT_NODE) { - // //////////////////////////////////////////////////////////////////////////////////// - IStructuredDocument sDoc = (IStructuredDocument) fTextViewer.getDocument(); - IStructuredDocumentRegion xmlEndTagOpen = sDoc.getRegionAtCharacterOffset(contentAssistRequest.getReplacementBeginPosition()); - // skip backward to "<", "</", or the (unclosed) start tag, null - // if not found - String type = ""; //$NON-NLS-1$ - while (xmlEndTagOpen != null && (type = xmlEndTagOpen.getType()) != DOMRegionContext.XML_END_TAG_OPEN && type != DOMRegionContext.XML_TAG_CLOSE && !needsEndTag(xmlEndTagOpen) && type != DOMRegionContext.XML_TAG_OPEN) { - xmlEndTagOpen = xmlEndTagOpen.getPrevious(); - } - - if (xmlEndTagOpen == null) - return; - - node = (IDOMNode) node.getModel().getIndexedRegion(xmlEndTagOpen.getStartOffset()); - node = (IDOMNode) node.getParentNode(); - - if (isStartTag(xmlEndTagOpen)) { - // this is the case for a start tag w/out end tag - // eg: - // <p> - // <% String test = "test"; %> - // | - if (needsEndTag(xmlEndTagOpen)) { - String tagName = getTagName(xmlEndTagOpen); - xmlEndTagOpen.getTextEndOffset(); - replaceLength = 0; - replaceText = "</" + tagName + ">"; //$NON-NLS-1$ //$NON-NLS-2$ $NON-NLS-2$ - // replaceText = "</" + node.getNodeName() + ">"; - // //$NON-NLS-1$ $NON-NLS-2$ - cursorOffset = tagName.length() + 3; - displayString = NLS.bind(XMLUIMessages.End_with__, (new Object[]{tagName})); - addProposal = true; - } - } - else if (type == DOMRegionContext.XML_END_TAG_OPEN) { - // this is the case for: <tag> </ | - // possibly <tag> </ |<anotherTag> - // should only be replacing white space... - replaceLength = (replaceBegin > xmlEndTagOpen.getTextEndOffset()) ? replaceBegin - xmlEndTagOpen.getTextEndOffset() : 0; - replaceText = node.getNodeName() + ">"; //$NON-NLS-1$ - cursorOffset = replaceText.length(); - replaceBegin = xmlEndTagOpen.getTextEndOffset(); - displayString = NLS.bind(XMLUIMessages.End_with_, (new Object[]{node.getNodeName()})); - addProposal = true; - } - else if (type == DOMRegionContext.XML_TAG_OPEN) { - // this is the case for: <tag> < | - replaceText = "/" + node.getNodeName() + ">"; //$NON-NLS-1$ //$NON-NLS-2$ $NON-NLS-2$ - cursorOffset = replaceText.length(); - // replaceText = "/" + node.getNodeName() + ">"; //$NON-NLS-1$ - // $NON-NLS-2$ - // should only be replacing white space... - replaceLength = (replaceBegin > xmlEndTagOpen.getTextEndOffset()) ? replaceBegin - xmlEndTagOpen.getTextEndOffset() : 0; - replaceBegin = xmlEndTagOpen.getTextEndOffset(); - displayString = NLS.bind(XMLUIMessages.End_with_, (new Object[]{"/" + node.getNodeName()})); //$NON-NLS-1$ - addProposal = true; - } - } - // //////////////////////////////////////////////////////////////////////////////////// - // sometimes the node is not null, but - // getNodeValue() is null, put in a null check - else if (node.getNodeValue() != null && node.getNodeValue().indexOf("</") != -1) { //$NON-NLS-1$ - // the case where "</" is started, but the nodes comes in as a - // text node (instead of element) - // like this: <tag> </| - Node parent = node.getParentNode(); - if (parent != null && parent.getNodeType() != Node.DOCUMENT_NODE) { - replaceText = parent.getNodeName() + ">"; //$NON-NLS-1$ - cursorOffset = replaceText.length(); - displayString = NLS.bind(XMLUIMessages.End_with__, (new Object[]{parent.getNodeName()})); - setErrorMessage(null); - addProposal = true; - } - } - // //////////////////////////////////////////////////////////////////////////////////// - else if (node.getNodeType() == Node.DOCUMENT_NODE) { - setErrorMessage(UNKNOWN_CONTEXT); - } - if (addProposal == true) { - CustomCompletionProposal proposal = new CustomCompletionProposal(replaceText, replaceBegin, replaceLength, cursorOffset, image, displayString, null, proposedInfo, XMLRelevanceConstants.R_END_TAG); - contentAssistRequest.addProposal(proposal); - } - } - - protected void addEntityProposals(ContentAssistRequest contentAssistRequest, int documentPosition, ITextRegion completionRegion, IDOMNode treeNode) { - ICompletionProposal[] eps = computeEntityReferenceProposals(documentPosition, completionRegion, treeNode); - for (int i = 0; eps != null && i < eps.length; i++) - contentAssistRequest.addProposal(eps[i]); - } - - protected void addEntityProposals(Vector proposals, Properties map, String key, int nodeOffset, IStructuredDocumentRegion sdRegion, ITextRegion completionRegion) { - if (map == null) - return; - String entityName = ""; //$NON-NLS-1$ - String entityValue = ""; //$NON-NLS-1$ - Image entityIcon = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ENTITY_REFERENCE); - String replacementText = ""; //$NON-NLS-1$ - String displayString = ""; //$NON-NLS-1$ - Enumeration keys = map.keys(); - - while (keys != null && keys.hasMoreElements()) { - entityName = (String) keys.nextElement(); - entityValue = map.getProperty(entityName); - // filter based on partial entity string... - if (entityName.toLowerCase().startsWith(key.toLowerCase()) || key.trim().equals("")) //$NON-NLS-1$ - { - // figure out selection...if text is selected, add it to - // selection length - int selectionLength = nodeOffset; - if (fTextViewer != null) { - selectionLength += fTextViewer.getSelectedRange().y; - } - // create a new proposal for entity string... - replacementText = "&" + entityName + ";"; //$NON-NLS-1$ //$NON-NLS-2$ - displayString = "&" + entityName + "; (" + entityValue + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - ICompletionProposal cp = new CustomCompletionProposal(replacementText, sdRegion.getStartOffset(completionRegion), selectionLength, replacementText.length(), entityIcon, displayString, null, null, XMLRelevanceConstants.R_ENTITY); - if (cp != null) { - proposals.add(cp); - } - } - } - } - - protected void addPCDATAProposal(String nodeName, ContentAssistRequest contentAssistRequest) { - CustomCompletionProposal proposal = new CustomCompletionProposal("<![CDATA[]]>", //$NON-NLS-1$ - contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 9, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_CDATASECTION), "CDATA Section", //$NON-NLS-1$ - null, null, XMLRelevanceConstants.R_CDATA); - contentAssistRequest.addProposal(proposal); - - proposal = new CustomCompletionProposal(nodeName, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), nodeName.length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TXTEXT), "#PCDATA", //$NON-NLS-1$ - null, null, XMLRelevanceConstants.R_CDATA); - contentAssistRequest.addProposal(proposal); - } - - protected void addStartDocumentProposals(ContentAssistRequest contentAssistRequest) { - Node aNode = contentAssistRequest.getNode(); - boolean xmlpiFound = false; - Document owningDocument = aNode.getOwnerDocument(); - // ==> // int xmlpiNodePosition = -1; - - // make sure xmlpi is root element - // don't want doctype proposal if XMLPI isn't first element... - Node first = owningDocument.getFirstChild(); - boolean xmlpiIsFirstElement = (first != null && first.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE); - boolean insertDoctype = xmlpiIsFirstElement; - - for (Node child = owningDocument.getFirstChild(); child != null; child = child.getNextSibling()) { - boolean xmlpi = (child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && child.getNodeName().equals("xml")); //$NON-NLS-1$ - xmlpiFound = xmlpiFound || xmlpi; - if (xmlpiFound) { - if (child instanceof IDOMNode) { - // ==> // int xmlpiNodePosition = - // ((XMLNode)child).getEndOffset(); - } - // skip white space and text - while ((child = child.getNextSibling()) != null && (child.getNodeType() == Node.TEXT_NODE)) { - // just skipping - } - // check if theres a node inbetween XMLPI and cursor position - if (child != null && child instanceof IDOMNode) { - if (contentAssistRequest.getReplacementBeginPosition() >= ((IDOMNode) child).getEndOffset() || !xmlpiIsFirstElement) { - insertDoctype = false; - } - } - break; - } - } - - if (xmlpiFound && owningDocument.getDoctype() == null && isCursorAfterXMLPI(contentAssistRequest) && insertDoctype) { - addDocTypeProposal(contentAssistRequest); - } - } - - /** - * Close an unclosed start tag - */ - protected void addTagCloseProposals(ContentAssistRequest contentAssistRequest) { - IDOMNode node = (IDOMNode) contentAssistRequest.getParent(); - if (node.getNodeType() == Node.ELEMENT_NODE) { - - CMElementDeclaration elementDecl = getCMElementDeclaration(node); - String proposedInfo = (elementDecl != null) ? getAdditionalInfo(null, elementDecl) : null; - int contentType = (elementDecl != null) ? elementDecl.getContentType() : CMElementDeclaration.ANY; - // if it's XML and content doesn't HAVE to be element, add "/>" - // proposal. - boolean endWithSlashBracket = (getXML(node) && contentType != CMElementDeclaration.ELEMENT); - - Image image = CMImageUtil.getImage(elementDecl); - if (image == null) { - image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC); - } - - // is the start tag ended properly? - if (contentAssistRequest.getDocumentRegion() == node.getFirstStructuredDocumentRegion() && !(node.getFirstStructuredDocumentRegion()).isEnded()) { - setErrorMessage(null); - // Is this supposed to be an empty tag? Note that if we can't - // tell, we assume it's not. - if (elementDecl != null && elementDecl.getContentType() == CMElementDeclaration.EMPTY) { - // prompt with a self-closing end character if needed - CustomCompletionProposal proposal = new CustomCompletionProposal(getContentGenerator().getStartTagClose(node, elementDecl), contentAssistRequest.getReplacementBeginPosition(), - // this is one of the few times to ignore the length -- - // always insert - // contentAssistRequest.getReplacementLength(), - 0, getContentGenerator().getStartTagClose(node, elementDecl).length(), image, NLS.bind(XMLUIMessages.Close_with___, (new Object[]{getContentGenerator().getStartTagClose(node, elementDecl)})), - null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG); - contentAssistRequest.addProposal(proposal); - } - else { - // prompt with a close for the start tag - CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$ - contentAssistRequest.getReplacementBeginPosition(), - // this is one of the few times to ignore the - // length -- always insert - // contentAssistRequest.getReplacementLength(), - 0, 1, image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" '>'"})), //$NON-NLS-1$ - null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG); - contentAssistRequest.addProposal(proposal); - - // prompt with the closer for the start tag and an end tag - // if one is not present - if (node.getEndStructuredDocumentRegion() == null) { - // make sure tag name is actually what it thinks it - // is...(eg. <%@ vs. <jsp:directive) - IStructuredDocumentRegion sdr = contentAssistRequest.getDocumentRegion(); - String openingTagText = (sdr != null) ? sdr.getFullText() : ""; //$NON-NLS-1$ - if (openingTagText != null && openingTagText.indexOf(node.getNodeName()) != -1) { - proposal = new CustomCompletionProposal("></" + node.getNodeName() + ">", //$NON-NLS-2$//$NON-NLS-1$ - contentAssistRequest.getReplacementBeginPosition(), - // this is one of the few times to - // ignore the length -- always insert - // contentAssistRequest.getReplacementLength(), - 0, 1, image, NLS.bind(XMLUIMessages.Close_with____, (new Object[]{node.getNodeName()})), - null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG); - contentAssistRequest.addProposal(proposal); - } - } - // prompt with slash bracket "/>" incase if it's a self - // ending tag - if (endWithSlashBracket) { - proposal = new CustomCompletionProposal("/>", //$NON-NLS-1$ - contentAssistRequest.getReplacementBeginPosition(), - // this is one of the few times to ignore - // the length -- always insert - // contentAssistRequest.getReplacementLength(), - 0, 2, image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" \"/>\""})), //$NON-NLS-1$ - null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG + 1); // +1 - // to - // bring - // to - // top - // of - // list - contentAssistRequest.addProposal(proposal); - } - } - } - else if (contentAssistRequest.getDocumentRegion() == node.getLastStructuredDocumentRegion() && !node.getLastStructuredDocumentRegion().isEnded()) { - setErrorMessage(null); - // prompt with a closing end character for the end tag - CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$ - contentAssistRequest.getReplacementBeginPosition(), - // this is one of the few times to ignore the - // length -- always insert - // contentAssistRequest.getReplacementLength(), - 0, 1, image, NLS.bind(XMLUIMessages.Close_with__, (new Object[]{" '>'"})), //$NON-NLS-1$ - null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG); - contentAssistRequest.addProposal(proposal); - } - } - else if (node.getNodeType() == Node.DOCUMENT_NODE) { - setErrorMessage(UNKNOWN_CONTEXT); - } - } - - protected void addTagInsertionProposals(ContentAssistRequest contentAssistRequest, int childPosition) { - List cmnodes = null; - Node parent = contentAssistRequest.getParent(); - String error = null; - - // (nsd) This is only valid at the document element level - // only valid if it's XML (check added 2/17/2004) - if (parent != null && parent.getNodeType() == Node.DOCUMENT_NODE && ((IDOMDocument) parent).isXMLType() && !isCursorAfterXMLPI(contentAssistRequest)) { - return; - } - // only want proposals if cursor is after doctype... - if (!isCursorAfterDoctype(contentAssistRequest)) - return; - - // fix for meta-info comment nodes.. they currently "hide" other - // proposals because the don't - // have a content model (so can't propose any children..) - if (parent != null && parent instanceof IDOMNode && isCommentNode((IDOMNode) parent)) { - // loop and find non comment node? - while (parent != null && isCommentNode((IDOMNode) parent)) { - parent = parent.getParentNode(); - } - } - - if (parent.getNodeType() == Node.ELEMENT_NODE) { - CMElementDeclaration parentDecl = getCMElementDeclaration(parent); - if (parentDecl != null) { - // XSD-specific ability - no filtering - CMDataType childType = parentDecl.getDataType(); - if (childType != null) { - String[] childStrings = childType.getEnumeratedValues(); - if (childStrings != null) { - // the content string is the sole valid child...so - // replace the rest - int begin = contentAssistRequest.getReplacementBeginPosition(); - int length = contentAssistRequest.getReplacementLength(); - if (parent instanceof IDOMNode) { - if (((IDOMNode) parent).getLastStructuredDocumentRegion() != ((IDOMNode) parent).getFirstStructuredDocumentRegion()) { - begin = ((IDOMNode) parent).getFirstStructuredDocumentRegion().getEndOffset(); - length = ((IDOMNode) parent).getLastStructuredDocumentRegion().getStartOffset() - begin; - } - } - String proposedInfo = getAdditionalInfo(parentDecl, childType); - for (int i = 0; i < childStrings.length; i++) { - CustomCompletionProposal textProposal = new CustomCompletionProposal(childStrings[i], begin, length, childStrings[i].length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ENUM), childStrings[i], null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION); - contentAssistRequest.addProposal(textProposal); - } - } - } - } - if (parentDecl != null && parentDecl.getContentType() == CMElementDeclaration.PCDATA) { - addPCDATAProposal(parentDecl.getNodeName(), contentAssistRequest); - } - else { - // retrieve the list of all possible children within this parent context - cmnodes = getAvailableChildElementDeclarations((Element)parent, childPosition, ModelQueryAction.INSERT); - - // retrieve the list of the possible children within this parent context and at this index - List strictCMNodeSuggestions = null; - if (XMLUIPreferenceNames.SUGGESTION_STRATEGY_VALUE_STRICT.equals(XMLUIPlugin.getInstance().getPreferenceStore().getString(XMLUIPreferenceNames.SUGGESTION_STRATEGY))) - { - strictCMNodeSuggestions = getValidChildElementDeclarations((Element)parent, childPosition, ModelQueryAction.INSERT); - } - Iterator nodeIterator = cmnodes.iterator(); - if (!nodeIterator.hasNext()) { - if (getCMElementDeclaration(parent) != null) - error = NLS.bind(XMLUIMessages._Has_no_available_child, (new Object[]{parent.getNodeName()})); - else - error = NLS.bind(XMLUIMessages.Element__is_unknown, (new Object[]{parent.getNodeName()})); - } - String matchString = contentAssistRequest.getMatchString(); - // chop off any leading <'s and whitespace from the - // matchstring - while ((matchString.length() > 0) && (Character.isWhitespace(matchString.charAt(0)) || beginsWith(matchString, "<"))) //$NON-NLS-1$ - //$NON-NLS-1$ - matchString = matchString.substring(1); - while (nodeIterator.hasNext()) { - Object o = nodeIterator.next(); - if (o instanceof CMElementDeclaration) { - CMElementDeclaration elementDecl = (CMElementDeclaration) o; - // only add proposals for the child element's that - // begin with the matchstring - String tagname = getRequiredName(parent, elementDecl); - boolean isStrictCMNodeSuggestion = strictCMNodeSuggestions != null ? strictCMNodeSuggestions.contains(elementDecl) : false; - - Image image = CMImageUtil.getImage(elementDecl); - - if (image == null) { - if (strictCMNodeSuggestions != null) { - image = isStrictCMNodeSuggestion ? - XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC_EMPHASIZED) : - XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC_DEEMPHASIZED); - } - else { - image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC); - } - - } - - //int markupAdjustment = getContentGenerator().getMinimalStartTagLength(parent, elementDecl); - if (beginsWith(tagname, matchString)) { - String proposedText = getRequiredText(parent, elementDecl); - - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=89811 - // place cursor in first empty quotes - int markupAdjustment = getCursorPositionForProposedText(proposedText); - - String proposedInfo = getAdditionalInfo(parentDecl, elementDecl); - int relevance = isStrictCMNodeSuggestion ? XMLRelevanceConstants.R_STRICTLY_VALID_TAG_INSERTION : XMLRelevanceConstants.R_TAG_INSERTION; - CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), markupAdjustment, image, tagname, null, proposedInfo, relevance); - contentAssistRequest.addProposal(proposal); - } - } - } - if (contentAssistRequest.getProposals().size() == 0) { - if (error != null) - setErrorMessage(error); - else if (contentAssistRequest.getMatchString() != null && contentAssistRequest.getMatchString().length() > 0) - setErrorMessage(NLS.bind(XMLUIMessages.No_known_child_tag, (new Object[]{parent.getNodeName(), contentAssistRequest.getMatchString()}))); - //$NON-NLS-1$ = "No known child tag names of <{0}> begin with \"{1}\"." - else - setErrorMessage(NLS.bind(XMLUIMessages.__Has_no_known_child, (new Object[]{parent.getNodeName()}))); - } - } - } - else if (parent.getNodeType() == Node.DOCUMENT_NODE) { - // Can only prompt with elements if the cursor position is past - // the XML processing - // instruction and DOCTYPE declaration - boolean xmlpiFound = false; - boolean doctypeFound = false; - int minimumOffset = -1; - - for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) { - - boolean xmlpi = (child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && child.getNodeName().equals("xml")); //$NON-NLS-1$ - boolean doctype = child.getNodeType() == Node.DOCUMENT_TYPE_NODE; - if (xmlpi || doctype && minimumOffset < 0) - minimumOffset = ((IDOMNode) child).getFirstStructuredDocumentRegion().getStartOffset() + ((IDOMNode) child).getFirstStructuredDocumentRegion().getTextLength(); - xmlpiFound = xmlpiFound || xmlpi; - doctypeFound = doctypeFound || doctype; - } - - if (contentAssistRequest.getReplacementBeginPosition() >= minimumOffset) { - List childDecls = getAvailableRootChildren((Document) parent, childPosition); - for (int i = 0; i < childDecls.size(); i++) { - CMElementDeclaration ed = (CMElementDeclaration) childDecls.get(i); - if (ed != null) { - Image image = CMImageUtil.getImage(ed); - if (image == null) { - image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC); - } - String proposedText = getRequiredText(parent, ed); - String tagname = getRequiredName(parent, ed); - // account for the < and > - int markupAdjustment = getContentGenerator().getMinimalStartTagLength(parent, ed); - String proposedInfo = getAdditionalInfo(null, ed); - CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), markupAdjustment, image, tagname, null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION); - contentAssistRequest.addProposal(proposal); - } - } - } - } - } - - protected void addTagNameProposals(ContentAssistRequest contentAssistRequest, int childPosition) { - List cmnodes = null; - Node parent = contentAssistRequest.getParent(); - IDOMNode node = (IDOMNode) contentAssistRequest.getNode(); - String error = null; - String matchString = contentAssistRequest.getMatchString(); - if (parent.getNodeType() == Node.ELEMENT_NODE) { - // retrieve the list of children - //validActions = getAvailableChildrenAtIndex((Element) parent, childPosition); - cmnodes = getAvailableChildElementDeclarations((Element)parent, childPosition, ModelQueryAction.INSERT); - Iterator nodeIterator = cmnodes.iterator(); - // chop off any leading <'s and whitespace from the matchstring - while ((matchString.length() > 0) && (Character.isWhitespace(matchString.charAt(0)) || beginsWith(matchString, "<"))) //$NON-NLS-1$ - //$NON-NLS-1$ - matchString = matchString.substring(1); - if (!nodeIterator.hasNext()) - error = NLS.bind(XMLUIMessages.__Has_no_known_child, (new Object[]{parent.getNodeName()})); - while (nodeIterator.hasNext()) { - CMNode elementDecl = (CMNode) nodeIterator.next(); - if (elementDecl != null) { - // only add proposals for the child element's that begin - // with the matchstring - String proposedText = null; - int cursorAdjustment = 0; - - // do a check to see if partial attributes of partial tag - // names are in list - if ((node != null && node.getAttributes() != null && node.getAttributes().getLength() > 0 && attributeInList(node, parent, elementDecl)) || ((node.getNodeType() != Node.TEXT_NODE) && node.getFirstStructuredDocumentRegion().isEnded())) { - - proposedText = getRequiredName(parent, elementDecl); - cursorAdjustment = proposedText.length(); - } - else { - proposedText = getRequiredName(parent, elementDecl); - cursorAdjustment = proposedText.length(); - if (elementDecl instanceof CMElementDeclaration) { - CMElementDeclaration ed = (CMElementDeclaration) elementDecl; - if (ed.getContentType() == CMElementDeclaration.EMPTY) { - proposedText += getContentGenerator().getStartTagClose(parent, ed); - cursorAdjustment = proposedText.length(); - } - else { - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=89811 - StringBuffer sb = new StringBuffer(); - getContentGenerator().generateTag(parent, ed, sb); - // since it's a name proposal, assume '<' is already there - // only return the rest of the tag - proposedText = sb.toString().substring(1); - cursorAdjustment = getCursorPositionForProposedText(proposedText); - - //cursorAdjustment = proposedText.length() + 1; - //proposedText += "></" + getRequiredName(parent, elementDecl) + ">"; //$NON-NLS-2$//$NON-NLS-1$ - } - } - } - if (beginsWith(proposedText, matchString)) { - Image image = CMImageUtil.getImage(elementDecl); - if (image == null) { - image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC); - } - String proposedInfo = getAdditionalInfo(getCMElementDeclaration(parent), elementDecl); - CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), cursorAdjustment, image, getRequiredName(parent, elementDecl), null, proposedInfo, XMLRelevanceConstants.R_TAG_NAME); - contentAssistRequest.addProposal(proposal); - } - } - } - if (contentAssistRequest.getProposals().size() == 0) { - if (error != null) - setErrorMessage(error); - else if (contentAssistRequest.getMatchString() != null && contentAssistRequest.getMatchString().length() > 0) - setErrorMessage(NLS.bind(XMLUIMessages.No_known_child_tag_names, (new Object[]{parent.getNodeName(), contentAssistRequest.getMatchString()}))); - //$NON-NLS-1$ = "No known child tag names of <{0}> begin with \"{1}\"" - else - setErrorMessage(NLS.bind(XMLUIMessages.__Has_no_known_child, (new Object[]{parent.getNodeName()}))); - } - } - else if (parent.getNodeType() == Node.DOCUMENT_NODE) { - List childElements = getAvailableRootChildren((Document) parent, childPosition); - for (int i = 0; i < childElements.size(); i++) { - CMNode ed = (CMNode) childElements.get(i); - if (ed == null) - continue; - String proposedText = null; - int cursorAdjustment = 0; - if(ed instanceof CMElementDeclaration) { - // proposedText = getRequiredName(parent, ed); - StringBuffer sb = new StringBuffer(); - getContentGenerator().generateTag(parent, (CMElementDeclaration)ed, sb); - // tag starts w/ '<', but we want to compare to name - proposedText = sb.toString().substring(1); - - if (!beginsWith(proposedText, matchString)) - continue; - - cursorAdjustment = getCursorPositionForProposedText(proposedText); - - if (ed instanceof CMElementDeclaration) { - CMElementDeclaration elementDecl = (CMElementDeclaration) ed; - if (elementDecl.getContentType() == CMElementDeclaration.EMPTY) { - proposedText += getContentGenerator().getStartTagClose(parent, elementDecl); - cursorAdjustment = proposedText.length(); - } - } - - String proposedInfo = getAdditionalInfo(null, ed); - Image image = CMImageUtil.getImage(ed); - if (image == null) { - image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC); - } - CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), cursorAdjustment, image, getRequiredName(parent, ed), null, proposedInfo, XMLRelevanceConstants.R_TAG_NAME); - contentAssistRequest.addProposal(proposal); - } - } - } - } - /** - * this is the position the cursor should be in after the proposal is applied - * @param proposedText - * @return the position the cursor should be in after the proposal is applied - */ - private int getCursorPositionForProposedText(String proposedText) { - int cursorAdjustment; - cursorAdjustment = proposedText.indexOf("\"\"") + 1; //$NON-NLS-1$ - // otherwise, after the first tag - if(cursorAdjustment==0) - cursorAdjustment = proposedText.indexOf('>') + 1; - if(cursorAdjustment==0) - cursorAdjustment = proposedText.length() + 1; - - return cursorAdjustment; - } - - /** - * @deprecated XML proposal is added via xml declaration template instead - */ - protected void addXMLProposal(ContentAssistRequest contentAssistRequest) { - String proposedText = "<?xml version=\"1.0\" encoding=\"" + ContentTypeEncodingPreferences.getUserPreferredCharsetName(ContentTypeIdForXML.ContentTypeID_XML) + "\"?>"; //$NON-NLS-2$//$NON-NLS-1$ - ICompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), proposedText.length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_PROCESSINGINSTRUCTION), proposedText, null, null, XMLRelevanceConstants.R_XML_DECLARATION); - // TODO add special XML proposal info - contentAssistRequest.addProposal(proposal); - } - - /** - * This method determines if any of the attributes in the proposed XMLNode - * node, are possible values of attributes from possible Elements at this - * point in the document according to the Content Model. - * - * @param node - * the element with attributes that you would like to test if - * are possible for possible Elements at this point - * @param cmnode - * possible element at this point in the document (depending on - * what 'node' is) true if any attributes of 'node' match any - * possible attributes from 'cmnodes' list. - */ - protected boolean attributeInList(IDOMNode node, Node parent, CMNode cmnode) { - if (node == null || parent == null || cmnode == null) - return false; - String elementMatchString = node.getNodeName(); - String cmnodeName = getRequiredName(parent, cmnode);// cmnode.getNodeName(); - if (node instanceof Element) { - NamedNodeMap map = ((Element) node).getAttributes(); - String attrMatchString = ""; //$NON-NLS-1$ - CMNamedNodeMap cmattrMap = null; - // iterate attribute possibilities for partially started node - for (int i = 0; map != null && i < map.getLength(); i++) { - attrMatchString = map.item(i).getNodeName(); - // filter on whatever user typed for element name already - if (beginsWith(cmnodeName, elementMatchString)) { - if (cmnode.getNodeType() == CMNode.ELEMENT_DECLARATION) { - cmattrMap = ((CMElementDeclaration) cmnode).getAttributes(); - // iterate possible attributes from a cmnode in - // proposal list - for (int k = 0; cmattrMap != null && k < cmattrMap.getLength(); k++) { - // check if name matches - if (cmattrMap.item(k).getNodeName().equals(attrMatchString)) { - return true; - } - } - } - } - } - } - return false; - } - - protected boolean beginsWith(String aString, String prefix) { - if (aString == null || prefix == null) - return true; - // (pa) matching independent of case to be consistant with Java - // editor CA - return aString.toLowerCase().startsWith(prefix.toLowerCase()); - } - - protected ContentAssistRequest computeAttributeProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) { - ContentAssistRequest contentAssistRequest = null; - IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition); - if (documentPosition < sdRegion.getStartOffset(completionRegion)) { - // setup to insert new attributes - contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString); - } - else { - // Setup to replace an existing attribute name - contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString); - } - addAttributeNameProposals(contentAssistRequest); - contentAssistRequest.setReplacementBeginPosition(documentPosition); - contentAssistRequest.setReplacementLength(0); - if (node.getFirstStructuredDocumentRegion() != null && (!node.getFirstStructuredDocumentRegion().isEnded())) { - addTagCloseProposals(contentAssistRequest); - } - return contentAssistRequest; - } - - protected ContentAssistRequest computeAttributeValueProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) { - ContentAssistRequest contentAssistRequest = null; - IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition); - if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength() && sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength() != sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) { - // setup to add a new attribute at the documentPosition - IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion)); - contentAssistRequest = newContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString); - addAttributeNameProposals(contentAssistRequest); - if (actualNode.getFirstStructuredDocumentRegion() != null && !actualNode.getFirstStructuredDocumentRegion().isEnded()) { - addTagCloseProposals(contentAssistRequest); - } - } - else { - // setup to replace the existing value - if (!nodeAtOffset.getFirstStructuredDocumentRegion().isEnded() && documentPosition < sdRegion.getStartOffset(completionRegion)) { - // if the IStructuredDocumentRegion isn't closed and the - // cursor is in front of the value, add - contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString); - addAttributeNameProposals(contentAssistRequest); - } - else { - contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString); - addAttributeValueProposals(contentAssistRequest); - } - } - return contentAssistRequest; - } - - protected ContentAssistRequest computeCompletionProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode treeNode, IDOMNode xmlnode) { - ContentAssistRequest contentAssistRequest = null; - String regionType = completionRegion.getType(); - IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition); - - // Handle the most common and best supported cases - if (xmlnode.getNodeType() == Node.ELEMENT_NODE || xmlnode.getNodeType() == Node.DOCUMENT_NODE) { - if (regionType == DOMRegionContext.XML_TAG_OPEN) { - contentAssistRequest = computeTagOpenProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode); - } - else if (regionType == DOMRegionContext.XML_TAG_NAME) { - contentAssistRequest = computeTagNameProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode); - } - else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) { - contentAssistRequest = computeAttributeProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode); - } - else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) { - contentAssistRequest = computeEqualsProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode); - } - else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE && documentPosition == sdRegion.getTextEndOffset() && (sdRegion.getText(completionRegion).endsWith("\"") || sdRegion.getText(completionRegion).endsWith("\'"))) //$NON-NLS-1$ //$NON-NLS-2$ - { - // this is for when the cursor is at the end of the closing - // quote for an attribute.. - IDOMNode actualNode = (IDOMNode) xmlnode.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion)); - contentAssistRequest = newContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString); - addTagCloseProposals(contentAssistRequest); - } - else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) { - contentAssistRequest = computeAttributeValueProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode); - } - else if ((regionType == DOMRegionContext.XML_TAG_CLOSE) || (regionType == DOMRegionContext.XML_EMPTY_TAG_CLOSE) || (regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_CLOSE))) { - contentAssistRequest = computeTagCloseProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode); - } - else if (regionType == DOMRegionContext.XML_END_TAG_OPEN) { - contentAssistRequest = computeEndTagOpenProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode); - } - else if (regionType == DOMRegionContext.XML_CONTENT || regionType == DOMRegionContext.XML_CHAR_REFERENCE || regionType == DOMRegionContext.XML_ENTITY_REFERENCE || regionType == DOMRegionContext.XML_PE_REFERENCE) { - contentAssistRequest = computeContentProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode); - } - - // These ITextRegion types begin DOM Elements as well and although - // internally harder to assist, - // text insertions directly before them can be made - else if (documentPosition == sdRegion.getStartOffset(completionRegion) && (regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_COMMENT_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DECLARATION_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_EXPRESSION_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_SCRIPTLET_OPEN) || regionType == DOMRegionContext.XML_DECLARATION_OPEN || regionType == DOMRegionContext.XML_PI_OPEN || regionType == DOMRegionContext.XML_COMMENT_OPEN || regionType == DOMRegionContext.XML_CDATA_OPEN)) { - contentAssistRequest = newContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString); - addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(treeNode)); - addStartDocumentProposals(contentAssistRequest); - } - } - // Not a Document or Element? (odd cases go here for now) - else if (isCloseRegion(completionRegion)) { - contentAssistRequest = newContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion) + completionRegion.getLength(), 0, matchString); - addStartDocumentProposals(contentAssistRequest); - if (documentPosition >= sdRegion.getTextEndOffset(completionRegion)) - addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(treeNode) + 1); - } - else if (documentPosition == sdRegion.getStartOffset(completionRegion) && (regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_COMMENT_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DECLARATION_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_EXPRESSION_OPEN) || regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_SCRIPTLET_OPEN) || regionType == DOMRegionContext.XML_DECLARATION_OPEN || regionType == DOMRegionContext.XML_PI_OPEN || regionType == DOMRegionContext.XML_COMMENT_OPEN || regionType == DOMRegionContext.XML_CDATA_OPEN)) { - contentAssistRequest = newContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString); - addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(treeNode)); - addStartDocumentProposals(contentAssistRequest); - } - return contentAssistRequest; - } - - /** - * CONTENT ASSIST STARTS HERE - * - * Return a list of proposed code completions based on the specified - * location within the document that corresponds to the current cursor - * position within the text-editor control. - * - * @param textViewer - * @param documentPosition - - * the cursor location within the document - * - * an array of ICompletionProposals - */ - public ICompletionProposal[] computeCompletionProposals(ITextViewer textViewer, int documentPosition) { - - setErrorMessage(null); - - fTextViewer = textViewer; - - IndexedRegion treeNode = ContentAssistUtils.getNodeAt((StructuredTextViewer) textViewer, documentPosition); - - Node node = (Node) treeNode; - while (node != null && node.getNodeType() == Node.TEXT_NODE && node.getParentNode() != null) - node = node.getParentNode(); - IDOMNode xmlnode = (IDOMNode) node; - - ContentAssistRequest contentAssistRequest = null; - - IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition); - ITextRegion completionRegion = getCompletionRegion(documentPosition, node); - - String matchString = getMatchString(sdRegion, completionRegion, documentPosition); - - // Handle empty Documents - if (completionRegion == null) { - if (((treeNode == null) || ((Node) treeNode).getNodeType() == Node.DOCUMENT_NODE) && completionRegion == null && (xmlnode == null || xmlnode.getChildNodes() == null || xmlnode.getChildNodes().getLength() == 0)) { - IStructuredModel sModel = StructuredModelManager.getModelManager().getExistingModelForRead(textViewer.getDocument()); - try { - if (sModel != null) { - IDOMDocument docNode = ((IDOMModel) sModel).getDocument(); - contentAssistRequest = newContentAssistRequest(docNode, docNode, sdRegion, completionRegion, documentPosition, 0, null); - addEmptyDocumentProposals(contentAssistRequest); - } - } - finally { - if (sModel != null) - sModel.releaseFromRead(); - } - if (contentAssistRequest == null) { - Logger.logException(new IllegalStateException("problem getting model")); //$NON-NLS-1$ - return new ICompletionProposal[0]; - } - return contentAssistRequest.getCompletionProposals(); - } - // MASSIVE ERROR CONDITION - Logger.logException(new IllegalStateException("completion region was null")); //$NON-NLS-1$ - setErrorMessage(INTERNALERROR); - contentAssistRequest = newContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$ - return contentAssistRequest.getCompletionProposals(); - } - - - // catch documents where no region can be determined - if (xmlnode.getNodeType() == Node.DOCUMENT_NODE && (completionRegion == null || xmlnode.getChildNodes() == null || xmlnode.getChildNodes().getLength() == 0)) { - contentAssistRequest = computeStartDocumentProposals(documentPosition, matchString, completionRegion, (IDOMNode) treeNode, xmlnode); - return contentAssistRequest.getCompletionProposals(); - } - - // compute normal proposals - contentAssistRequest = computeCompletionProposals(documentPosition, matchString, completionRegion, (IDOMNode) treeNode, xmlnode); - if (contentAssistRequest == null) { - contentAssistRequest = newContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$ - if (Debug.displayWarnings) - System.out.println(UNKNOWN_CONTEXT + " " + completionRegion.getType() + "@" + documentPosition); //$NON-NLS-2$//$NON-NLS-1$ - setErrorMessage(UNKNOWN_CONTEXT); - } - - if (contentAssistRequest.getProposals().size() == 0) - setErrorMessage(UNKNOWN_CONTEXT); - - return contentAssistRequest.getCompletionProposals(); - } - - protected ContentAssistRequest computeContentProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) { - ContentAssistRequest contentAssistRequest = null; - - // setup to add children at the content node's position - contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, getStructuredDocumentRegion(documentPosition), completionRegion, documentPosition, 0, matchString); - if (node != null && node.getNodeType() == Node.DOCUMENT_NODE && ((Document) node).getDoctype() == null) - addStartDocumentProposals(contentAssistRequest); - addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset)); - if (node.getNodeType() != Node.DOCUMENT_NODE) { - addEndTagProposals(contentAssistRequest); - } - // entities? - addEntityProposals(contentAssistRequest, documentPosition, completionRegion, node); - // addEntityProposals(contentAssistRequest); - return contentAssistRequest; - } - - /** - * Returns information about possible contexts based on the specified - * location within the document that corresponds to the current cursor - * position within the text viewer. - * - * @param viewer - * the viewer whose document is used to compute the possible - * contexts an array of context information objects or - * <code>null</code> if no context could be found - */ - public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) { - if (fAttributeInfoProvider == null) - fAttributeInfoProvider = new AttributeContextInformationProvider((IStructuredDocument) viewer.getDocument(), (AttributeContextInformationPresenter) getContextInformationValidator()); - return fAttributeInfoProvider.getAttributeInformation(documentOffset); - } - - protected ContentAssistRequest computeEndTagOpenProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) { - ContentAssistRequest contentAssistRequest = null; - IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition); - int completionRegionStart = sdRegion.getStartOffset(completionRegion); - int completionRegionLength = completionRegion.getLength(); - IStructuredDocumentRegion sdRegionAtCompletionOffset = node.getStructuredDocument().getRegionAtCharacterOffset(completionRegionStart + completionRegionLength); - ITextRegion regionAtEndOfCompletion = sdRegionAtCompletionOffset.getRegionAtCharacterOffset(completionRegionStart + completionRegionLength); - - if (documentPosition != completionRegionStart && regionAtEndOfCompletion != null && regionAtEndOfCompletion.getType() == DOMRegionContext.XML_TAG_NAME) { - ITextRegion nameRegion = regionAtEndOfCompletion; - contentAssistRequest = newContentAssistRequest(nodeAtOffset, nodeAtOffset.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(nameRegion), nameRegion.getTextLength(), matchString); - } - else { - if (nodeAtOffset.getFirstStructuredDocumentRegion() == sdRegion) { - // abnormal case, this unmatched end tag will be a sibling - contentAssistRequest = newContentAssistRequest(nodeAtOffset, nodeAtOffset.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString); - } - else { - // normal case, this end tag is the parent - contentAssistRequest = newContentAssistRequest(nodeAtOffset, nodeAtOffset, sdRegion, completionRegion, documentPosition, 0, matchString); - } - } - // if (documentPosition >= sdRegion.getStartOffset(completionRegion) + - // completionRegion.getTextLength()) - addEndTagProposals(contentAssistRequest); - // else - if (completionRegionStart == documentPosition) { - // positioned at start of end tag - addTagInsertionProposals(contentAssistRequest, node.getChildNodes().getLength()); - } - return contentAssistRequest; - } - - /** - * return all possible EntityReferenceProposals (according to current - * position in doc) - */ - protected ICompletionProposal[] computeEntityReferenceProposals(int documentPosition, ITextRegion completionRegion, IDOMNode treeNode) { - // only handle XML content for now - Vector proposals = new Vector(); // ICompletionProposals - IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition); - if (completionRegion != null && completionRegion.getType() == DOMRegionContext.XML_CONTENT) { - int nodeOffset = documentPosition - sdRegion.getStartOffset(completionRegion); - String regionText = sdRegion.getFullText(completionRegion); - - // if directly to the right of a &, region will be null, need to - // move to - // the previous region...there might be a better way to do this - if (regionText != null && regionText.trim().equals("") && documentPosition > 0) { //$NON-NLS-1$ - IStructuredDocumentRegion prev = treeNode.getStructuredDocument().getRegionAtCharacterOffset(documentPosition - 1); - if (prev != null && prev.getFullText().trim().equals("&")) { //$NON-NLS-1$ - completionRegion = prev; - regionText = prev.getFullText(); - nodeOffset = 1; - } - } - - // string must start w/ & - if (regionText != null && regionText.startsWith("&")) { //$NON-NLS-1$ - String key = (nodeOffset > 0) ? regionText.substring(1, nodeOffset) : ""; //$NON-NLS-1$ - - // get entity proposals, passing in the appropriate start - // string - ModelQuery mq = ModelQueryUtil.getModelQuery(((Node) treeNode).getOwnerDocument()); - if (mq != null) { - CMDocument xmlDoc = mq.getCorrespondingCMDocument(treeNode); - CMNamedNodeMap cmmap = null; - Properties entities = null; - if (xmlDoc != null) { - cmmap = xmlDoc.getEntities(); - } - if (cmmap != null) { - entities = mapToProperties(cmmap); - } - else // 224787 in absence of content model, just use - // minimal 5 entities - { - entities = new Properties(); - entities.put("quot", "\""); //$NON-NLS-1$ //$NON-NLS-2$ - entities.put("apos", "'"); //$NON-NLS-1$ //$NON-NLS-2$ - entities.put("amp", "&"); //$NON-NLS-1$ //$NON-NLS-2$ - entities.put("lt", "<"); //$NON-NLS-1$ //$NON-NLS-2$ - entities.put("gt", ">"); //$NON-NLS-1$ //$NON-NLS-2$ - entities.put("nbsp", " "); //$NON-NLS-1$ //$NON-NLS-2$ - } - addEntityProposals(proposals, entities, key, nodeOffset, sdRegion, completionRegion); //$NON-NLS-1$ - } - } - } - return (ICompletionProposal[]) ((proposals.size() > 0) ? proposals.toArray(new ICompletionProposal[proposals.size()]) : null); - } - - protected ContentAssistRequest computeEqualsProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) { - ContentAssistRequest contentAssistRequest = null; - IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition); - ITextRegion valueRegion = node.getStartStructuredDocumentRegion().getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()); - if (valueRegion != null && valueRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE && sdRegion.getStartOffset(valueRegion) <= documentPosition) { - // replace the adjacent attribute value - contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, valueRegion, sdRegion.getStartOffset(valueRegion), valueRegion.getTextLength(), matchString); - } - else { - // append an attribute value after the '=' - contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString); - } - addAttributeValueProposals(contentAssistRequest); - return contentAssistRequest; - } - - protected ContentAssistRequest computeStartDocumentProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) { - // setup for a non-empty document, but one that hasn't been formally - // started - ContentAssistRequest contentAssistRequest = null; - contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, getStructuredDocumentRegion(documentPosition), completionRegion, documentPosition, 0, matchString); - addStartDocumentProposals(contentAssistRequest); - return contentAssistRequest; - } - - protected ContentAssistRequest computeTagCloseProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) { - ContentAssistRequest contentAssistRequest = null; - IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition); - - if ((node.getNodeType() == Node.DOCUMENT_NODE) || (documentPosition >= sdRegion.getEndOffset())) { - // this is a content request as the documentPosition is AFTER the - // end of the closing region - if (node == nodeAtOffset && node.getParentNode() != null) - node = (IDOMNode) node.getParentNode(); - contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString); - addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset)); - if (node.getNodeType() != Node.DOCUMENT_NODE && node.getEndStructuredDocumentRegion() == null) { - addEndTagProposals(contentAssistRequest); - } - } - else { - // at the start of the tag's close or within it - ITextRegion closeRegion = sdRegion.getLastRegion(); - boolean insideTag = !sdRegion.isEnded() || documentPosition <= sdRegion.getStartOffset(closeRegion); - if (insideTag) { - // this is a request for completions within a tag - contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString); - if (node.getNodeType() != Node.DOCUMENT_NODE && node.getEndStructuredDocumentRegion() != null) { - addTagCloseProposals(contentAssistRequest); - } - if (sdRegion == nodeAtOffset.getFirstStructuredDocumentRegion()) { - contentAssistRequest.setReplacementBeginPosition(documentPosition); - contentAssistRequest.setReplacementLength(0); - addAttributeNameProposals(contentAssistRequest); - } - } - } - return contentAssistRequest; - } - - protected ContentAssistRequest computeTagNameProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) { - ContentAssistRequest contentAssistRequest = null; - IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition); - - if (sdRegion != nodeAtOffset.getFirstStructuredDocumentRegion()) { - // completing the *first* tag in "<tagname1 |<tagname2" - IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion)); - if (actualNode != null) { - if (actualNode.getFirstStructuredDocumentRegion() == sdRegion) { - // start tag - if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) { - // it's attributes - contentAssistRequest = newContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), matchString); - if (node.getStructuredDocument().getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) - 1).getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) - 1).getType() == DOMRegionContext.XML_TAG_OPEN) - addAttributeNameProposals(contentAssistRequest); - addTagCloseProposals(contentAssistRequest); - } - else { - // it's name - contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), matchString); - addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(actualNode)); - } - } - else { - if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) { - // insert name - contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString); - } - else { - // replace name - contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString); - } - addEndTagNameProposals(contentAssistRequest); - } - } - } - else { - if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) { - // unclosed tag with only a name; should prompt for attributes - // and a close instead - contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), matchString); - addAttributeNameProposals(contentAssistRequest); - addTagCloseProposals(contentAssistRequest); - } - else { - if (sdRegion.getRegions().get(0).getType() != DOMRegionContext.XML_END_TAG_OPEN) { - int replaceLength = documentPosition - sdRegion.getStartOffset(completionRegion); - contentAssistRequest = newContentAssistRequest(node, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), replaceLength, matchString); - addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset)); - } - else { - IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(documentPosition); - if (actualNode != null) { - if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) { - contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString); - } - else { - contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString); - } - addEndTagNameProposals(contentAssistRequest); - } - } - } - } - return contentAssistRequest; - } - - protected ContentAssistRequest computeTagOpenProposals(int documentPosition, String matchString, ITextRegion completionRegion, IDOMNode nodeAtOffset, IDOMNode node) { - ContentAssistRequest contentAssistRequest = null; - IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition); - if (sdRegion != nodeAtOffset.getFirstStructuredDocumentRegion()) { - // completing the *first* XML_TAG_OPEN in "<<tagname" - IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion)); - if (actualNode != null) { - contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString); - addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(actualNode)); - addEndTagProposals(contentAssistRequest); // (pa) 220850 - } - } - else { - if (documentPosition == sdRegion.getStartOffset(completionRegion)) { - if (node.getNodeType() == Node.ELEMENT_NODE) { - // at the start of an existing tag, right before the '<' - contentAssistRequest = newContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString); - addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset)); - addEndTagProposals(contentAssistRequest); - } - else if (node.getNodeType() == Node.DOCUMENT_NODE) { - // at the opening of the VERY first tag with a '<' - contentAssistRequest = newContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString); - addStartDocumentProposals(contentAssistRequest); - } - } - else { - // within the white space - ITextRegion name = getNameRegion(node.getStartStructuredDocumentRegion()); - // (pa) ITextRegion refactor - // if (name != null && name.containsOffset(documentPosition)) - // { - if (name != null && (sdRegion.getStartOffset(name) <= documentPosition && sdRegion.getEndOffset(name) >= documentPosition)) { - // replace the existing name - contentAssistRequest = newContentAssistRequest(node, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(name), name.getTextLength(), matchString); - } - else { - // insert a valid new name, or possibly an end tag - contentAssistRequest = newContentAssistRequest(nodeAtOffset, ((Node) nodeAtOffset).getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString); - addEndTagProposals(contentAssistRequest); - contentAssistRequest.setReplacementBeginPosition(documentPosition); - contentAssistRequest.setReplacementLength(0); - } - addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset)); - } - } - return contentAssistRequest; - } - - /** - * Retreives cmnode's documentation to display in the completion - * proposal's additional info. If no documentation exists for cmnode, try - * displaying parentOrOwner's documentation - * - * String any documentation information to display for cmnode. - * <code>null</code> if there is nothing to display. - */ - protected String getAdditionalInfo(CMNode parentOrOwner, CMNode cmnode) { - String addlInfo = null; - - if (cmnode == null) { - if (Debug.displayWarnings) { - new IllegalArgumentException("Null declaration!").printStackTrace(); //$NON-NLS-1$ - } - return null; - } - - addlInfo = getInfoProvider().getInfo(cmnode); - if (addlInfo == null && parentOrOwner != null) - addlInfo = getInfoProvider().getInfo(parentOrOwner); - return addlInfo; - } - - // returns a list of ModelQueryActions - protected List getAvailableChildrenAtIndex(Element parent, int index, int validityChecking) { - List list = new ArrayList(); - CMElementDeclaration parentDecl = getCMElementDeclaration(parent); - if (parentDecl != null) { - ModelQuery modelQuery = ModelQueryUtil.getModelQuery(parent.getOwnerDocument()); - // taken from ActionManagers - // int editMode = modelQuery.getEditMode(); - int editMode = ModelQuery.EDIT_MODE_UNCONSTRAINED; - int ic = (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) ? ModelQuery.INCLUDE_CHILD_NODES | ModelQuery.INCLUDE_SEQUENCE_GROUPS : ModelQuery.INCLUDE_CHILD_NODES; - modelQuery.getInsertActions(parent, parentDecl, index, ic, validityChecking, list); - } - return list; - } - - // returns a list of CMElementDeclarations - protected List getAvailableRootChildren(Document document, int childIndex) { - List list = null; - - // extract the valid 'root' node name from the DocumentType Node - DocumentType docType = document.getDoctype(); - String rootName = null; - if (docType != null) { - rootName = docType.getNodeName(); - } - if (rootName == null) - return new ArrayList(0); - - for (Node child = document.getFirstChild(); child != null; child = child.getNextSibling()) { - // make sure the "root" Element isn't already present - // is it required to be an Element? - if (child.getNodeType() == Node.ELEMENT_NODE && stringsEqual(child.getNodeName(), rootName)) { - // if the node is missing either the start or end tag, don't - // count it as present - if (child instanceof IDOMNode && (((IDOMNode) child).getStartStructuredDocumentRegion() == null || ((IDOMNode) child).getEndStructuredDocumentRegion() == null)) - continue; - if (Debug.displayInfo) - System.out.println(rootName + " already present!"); //$NON-NLS-1$ - setErrorMessage(NLS.bind(XMLUIMessages.The_document_element__, (new Object[]{rootName}))); - return new ArrayList(0); - } - } - - list = new ArrayList(1); - ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document); - if (modelQuery != null) { - CMDocument cmdoc = modelQuery.getCorrespondingCMDocument(document); - if (cmdoc != null) { - if (rootName != null) { - CMElementDeclaration rootDecl = (CMElementDeclaration) cmdoc.getElements().getNamedItem(rootName); - if (rootDecl != null) { - list.add(rootDecl); - } - else { - // supply the given document name anyway, even if it - // is an error - list.add(new SimpleCMElementDeclaration(rootName)); - if (Debug.displayInfo || Debug.displayWarnings) - System.out.println("No definition found for " + rootName + " in " + docType.getPublicId() + "/" + docType.getSystemId()); //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$ - String location = "" + (docType.getPublicId() != null ? docType.getPublicId() + "/" : "") + (docType.getSystemId() != null ? docType.getSystemId() : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$ - //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$ - if (location.length() > 0) - setErrorMessage(NLS.bind(XMLUIMessages.No_definition_for_in, (new Object[]{rootName, location}))); - else - setErrorMessage(NLS.bind(XMLUIMessages.No_definition_for, (new Object[]{rootName}))); - } - } - } - else { - if (Debug.displayInfo || Debug.displayWarnings) - System.out.println("No content model found."); //$NON-NLS-1$ - //$NON-NLS-1$ - //$NON-NLS-1$ - String location = "" + (docType.getPublicId() != null ? docType.getPublicId() + "/" : "") + (docType.getSystemId() != null ? docType.getSystemId() : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$ - //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$ - if (location.length() > 0) - setErrorMessage(NLS.bind(XMLUIMessages.No_content_model_for, (new Object[]{location}))); - else - setErrorMessage(XMLUIMessages.No_content_model_found_UI_); - } - } - - return list; - } - - protected CMElementDeclaration getCMElementDeclaration(Node node) { - CMElementDeclaration result = null; - if (node.getNodeType() == Node.ELEMENT_NODE) { - ModelQuery modelQuery = ModelQueryUtil.getModelQuery(node.getOwnerDocument()); - if (modelQuery != null) - result = modelQuery.getCMElementDeclaration((Element) node); - } - return result; - } - - /** - * Returns the characters which when entered by the user should - * automatically trigger the presentation of possible completions. - * - * the auto activation characters for completion proposal or - * <code>null</code> if no auto activation is desired - */ - public char[] getCompletionProposalAutoActivationCharacters() { - return completionProposalAutoActivationCharacters; - } - - protected ITextRegion getCompletionRegion(int offset, IStructuredDocumentRegion sdRegion) { - ITextRegion region = sdRegion.getRegionAtCharacterOffset(offset); - if (region == null) - return null; - - if (sdRegion.getStartOffset(region) == offset) { - // The offset is at the beginning of the region - if ((sdRegion.getStartOffset(region) == sdRegion.getStartOffset()) && (sdRegion.getPrevious() != null) && (!sdRegion.getPrevious().isEnded())) { - // Is the region also the start of the node? If so, the - // previous IStructuredDocumentRegion is - // where to look for a useful region. - region = sdRegion.getPrevious().getRegionAtCharacterOffset(offset - 1); - } - else { - // Is there no separating whitespace from the previous region? - // If not, - // then that region is the important one - ITextRegion previousRegion = sdRegion.getRegionAtCharacterOffset(offset - 1); - if ((previousRegion != null) && (previousRegion != region) && (previousRegion.getTextLength() == previousRegion.getLength())) { - region = previousRegion; - } - } - } - else { - // The offset is NOT at the beginning of the region - if (offset > sdRegion.getStartOffset(region) + region.getTextLength()) { - // Is the offset within the whitespace after the text in this - // region? - // If so, use the next region - ITextRegion nextRegion = sdRegion.getRegionAtCharacterOffset(sdRegion.getStartOffset(region) + region.getLength()); - if (nextRegion != null) - region = nextRegion; - } - else { - // Is the offset within the important text for this region? - // If so, then we've already got the right one. - } - } - - // valid WHITE_SPACE region handler (#179924) - if (region != null && region.getType() == DOMRegionContext.WHITE_SPACE) { - ITextRegion previousRegion = sdRegion.getRegionAtCharacterOffset(sdRegion.getStartOffset(region) - 1); - if (previousRegion != null) - region = previousRegion; - } - - return region; - } - - /** - * Return the region whose content's require completion. This is something - * of a misnomer as sometimes the user wants to be prompted for contents - * of a non-existant ITextRegion, such as for enumerated attribute values - * following an '=' sign. - */ - protected ITextRegion getCompletionRegion(int documentPosition, Node domnode) { - if (domnode == null) - return null; - - ITextRegion region = null; - int offset = documentPosition; - IStructuredDocumentRegion flatNode = null; - IDOMNode node = (IDOMNode) domnode; - - if (node.getNodeType() == Node.DOCUMENT_NODE) { - if (node.getStructuredDocument().getLength() == 0) - return null; - ITextRegion result = node.getStructuredDocument().getRegionAtCharacterOffset(offset).getRegionAtCharacterOffset(offset); - while (result == null) { - offset--; - result = node.getStructuredDocument().getRegionAtCharacterOffset(offset).getRegionAtCharacterOffset(offset); - } - return result; - } - - IStructuredDocumentRegion startTag = node.getStartStructuredDocumentRegion(); - IStructuredDocumentRegion endTag = node.getEndStructuredDocumentRegion(); - - // Determine if the offset is within the start - // IStructuredDocumentRegion, end IStructuredDocumentRegion, or - // somewhere within the Node's XML content. - if ((startTag != null) && (startTag.getStartOffset() <= offset) && (offset < startTag.getStartOffset() + startTag.getLength())) - flatNode = startTag; - else if ((endTag != null) && (endTag.getStartOffset() <= offset) && (offset < endTag.getStartOffset() + endTag.getLength())) - flatNode = endTag; - - if (flatNode != null) { - // the offset is definitely within the start or end tag, continue - // on and find the region - region = getCompletionRegion(offset, flatNode); - } - else { - // the docPosition is neither within the start nor the end, so it - // must be content - flatNode = node.getStructuredDocument().getRegionAtCharacterOffset(offset); - // (pa) ITextRegion refactor - // if (flatNode.contains(documentPosition)) { - if (flatNode.getStartOffset() <= documentPosition && flatNode.getEndOffset() >= documentPosition) { - // we're interesting in completing/extending the previous - // IStructuredDocumentRegion if the current - // IStructuredDocumentRegion isn't plain content or if it's - // preceded by an orphan '<' - if ((offset == flatNode.getStartOffset()) && (flatNode.getPrevious() != null) && (flatNode.getRegionAtCharacterOffset(documentPosition) != null && flatNode.getRegionAtCharacterOffset(documentPosition).getType() != DOMRegionContext.XML_CONTENT || flatNode.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_TAG_OPEN || flatNode.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_END_TAG_OPEN)) { - // Is the region also the start of the node? If so, the - // previous IStructuredDocumentRegion is - // where to look for a useful region. - region = flatNode.getPrevious().getLastRegion(); - } - else if (flatNode.getEndOffset() == documentPosition) { - region = flatNode.getLastRegion(); - } - else - region = flatNode.getFirstRegion(); - } - else { - // catch end of document positions where the docPosition isn't - // in a IStructuredDocumentRegion - region = flatNode.getLastRegion(); - } - } - - return region; - } - - /** - * Provided by default. Subclasses may override with their own - * implementations. - * - * @see AbstractContentAssistProcessor#getContentGenerator() - */ - public XMLContentModelGenerator getContentGenerator() { - if (fGenerator == null) - fGenerator = new XMLContentModelGenerator(); - return fGenerator; - } - - /** - * Returns the characters which when entered by the user should - * automatically trigger the presentation of context information. - * - * the auto activation characters for presenting context information or - * <code>null</code> if no auto activation is desired - */ - public char[] getContextInformationAutoActivationCharacters() { - return contextInformationAutoActivationCharacters; - } - - /** - * Returns a validator used to determine when displayed context - * information should be dismissed. May only return <code>null</code> if - * the processor is incapable of computing context information. - * - * a context information validator, or <code>null</code> if the - * processor is incapable of computing context information - */ - public IContextInformationValidator getContextInformationValidator() { - if (fContextInformationPresenter == null) - fContextInformationPresenter = new AttributeContextInformationPresenter(); - return fContextInformationPresenter; - } - - protected int getElementPosition(Node child) { - Node parent = child.getParentNode(); - if (parent == null) - return 0; - - NodeList children = parent.getChildNodes(); - if (children == null) - return 0; - int count = 0; - - for (int i = 0; i < children.getLength(); i++) { - if (children.item(i) == child) - return count; - else - // if (children.item(i).getNodeType() == Node.ELEMENT_NODE) - count++; - } - return 0; - } - - private int getElementPositionForModelQuery(Node child) { - return getElementPosition(child); - // return -1; - } - - /** - * Return the reason why computeProposals was not able to find any - * completions. - * - * an error message or null if no error occurred - */ - public String getErrorMessage() { - return fErrorMessage; - } - - /** - * @param iResource - */ - // public void initialize(IResource iResource) { - // this.resource = iResource; - // } - /** - * Gets the infoProvider. - * - * fInfoProvider and if fInfoProvider was <code>null</code> create a new - * instance - */ - public MarkupTagInfoProvider getInfoProvider() { - if (fInfoProvider == null) { - fInfoProvider = new MarkupTagInfoProvider(); - } - return fInfoProvider; - } - - protected String getMatchString(IStructuredDocumentRegion parent, ITextRegion aRegion, int offset) { - if (aRegion == null || isCloseRegion(aRegion)) - return ""; //$NON-NLS-1$ - String matchString = null; - String regionType = aRegion.getType(); - if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS || regionType == DOMRegionContext.XML_TAG_OPEN || (offset > parent.getStartOffset(aRegion) + aRegion.getTextLength())) { - matchString = ""; //$NON-NLS-1$ - } - else if (regionType == DOMRegionContext.XML_CONTENT) { - matchString = ""; //$NON-NLS-1$ - } - else { - if (parent.getText(aRegion).length() > 0 && parent.getStartOffset(aRegion) < offset) - matchString = parent.getText(aRegion).substring(0, offset - parent.getStartOffset(aRegion)); - else - matchString = ""; //$NON-NLS-1$ - } - return matchString; - } - - protected ITextRegion getNameRegion(IStructuredDocumentRegion flatNode) { - if (flatNode == null) - return null; - Iterator regionList = flatNode.getRegions().iterator(); - while (regionList.hasNext()) { - ITextRegion region = (ITextRegion) regionList.next(); - if (isNameRegion(region)) - return region; - } - return null; - } - - /** - * Retrieves all of the possible valid values for this attribute - * declaration - */ - protected List getPossibleDataTypeValues(Node node, CMAttributeDeclaration ad) { - List list = null; - if (node.getNodeType() == Node.ELEMENT_NODE) { - Element element = (Element) node; - String[] dataTypeValues = null; - // The ModelQuery may not be available if the corresponding - // adapter - // is absent - ModelQuery modelQuery = ModelQueryUtil.getModelQuery(element.getOwnerDocument()); - if (modelQuery != null) { - dataTypeValues = modelQuery.getPossibleDataTypeValues(element, ad); - } - else { - if (ad.getAttrType() != null) - dataTypeValues = ad.getAttrType().getEnumeratedValues(); - } - if (dataTypeValues != null) { - list = new ArrayList(dataTypeValues.length); - for (int i = 0; i < dataTypeValues.length; i++) { - list.add(dataTypeValues[i]); - } - } - } - if (list == null) { - list = new ArrayList(0); - } - return list; - } - - protected String getRequiredName(Node parentOrOwner, CMNode cmnode) { - if (cmnode == null || parentOrOwner == null) { - if (Debug.displayWarnings) { - new IllegalArgumentException("Null declaration!").printStackTrace(); //$NON-NLS-1$ - } - return ""; //$NON-NLS-1$ - } - return getContentGenerator().getRequiredName(parentOrOwner, cmnode); - } - - protected String getRequiredText(Node parentOrOwner, CMAttributeDeclaration attrDecl) { - if (attrDecl == null) { - if (Debug.displayWarnings) { - new IllegalArgumentException("Null attribute declaration!").printStackTrace(); //$NON-NLS-1$ - } - return ""; //$NON-NLS-1$ - } - StringBuffer buff = new StringBuffer(); - getContentGenerator().generateRequiredAttribute(parentOrOwner, attrDecl, buff); - return buff.toString(); - } - - protected String getRequiredText(Node parentOrOwner, CMElementDeclaration elementDecl) { - if (elementDecl == null) { - if (Debug.displayWarnings) { - new IllegalArgumentException("Null attribute declaration!").printStackTrace(); //$NON-NLS-1$ - } - return ""; //$NON-NLS-1$ - } - StringBuffer buff = new StringBuffer(); - getContentGenerator().generateTag(parentOrOwner, elementDecl, buff); - return buff.toString(); - } - - /** - * StructuredTextViewer must be set before using this. - */ - public IStructuredDocumentRegion getStructuredDocumentRegion(int pos) { - // (pa) ITextRegion refactor defect 245190 - // return - // (IStructuredDocumentRegion)ContentAssistUtils.getNodeAt((StructuredTextViewer)fTextViewer, - // pos); - return ContentAssistUtils.getStructuredDocumentRegion((StructuredTextViewer) fTextViewer, pos); - } - - private String getTagName(IStructuredDocumentRegion sdRegion) { - ITextRegionList regions = sdRegion.getRegions(); - ITextRegion region = null; - String name = ""; //$NON-NLS-1$ - for (int i = 0; i < regions.size(); i++) { - region = regions.get(i); - if (region.getType() == DOMRegionContext.XML_TAG_NAME) { - name = sdRegion.getText(region); - break; - } - } - return name; - } - - // returns a list of CMNodes that are available within this parent context - // Given the grammar shown below and a snippet of XML code (where the '|' indicated the cursor position) - // the list would return all of the element declarations that are potential child elements of Foo. - // - // grammar : Foo -> (A, B, C) - // snippet : <Foo><A>| - // result : {A, B, C} - // - // TODO cs... do we need to pass in the 'kindOfAction'? Seems to me we could assume it's always an insert. - protected List getAvailableChildElementDeclarations(Element parent, int childPosition, int kindOfAction) - { - List modelQueryActions = getAvailableChildrenAtIndex(parent, childPosition, ModelQuery.VALIDITY_NONE); - Iterator iterator = modelQueryActions.iterator(); - List cmnodes = new Vector(); - while (iterator.hasNext()) { - ModelQueryAction action = (ModelQueryAction) iterator.next(); - if (childPosition < 0 || (action.getStartIndex() <= childPosition && childPosition <= action.getEndIndex()) && action.getKind() == kindOfAction) { - CMNode actionCMNode = action.getCMNode(); - if (actionCMNode != null && !cmnodes.contains(actionCMNode)) - cmnodes.add(actionCMNode); - } - } - return cmnodes; - } - - // returns a list of CMNodes that can be validly inserted at this childPosition - // Given the grammar shown below and a snippet of XML code (where the '|' indicated the cursor position) - // the list would return only the element declarations can be inserted while maintaing validity of the content. - // - // grammar : Foo -> (A, B, C) - // snippet : <Foo><A>| - // result : {B} - // - protected List getValidChildElementDeclarations(Element parent, int childPosition, int kindOfAction) - { - List modelQueryActions = getAvailableChildrenAtIndex(parent, childPosition, ModelQuery.VALIDITY_STRICT); - Iterator iterator = modelQueryActions.iterator(); - List cmnodes = new Vector(); - while (iterator.hasNext()) { - ModelQueryAction action = (ModelQueryAction) iterator.next(); - if (childPosition < 0 || (action.getStartIndex() <= childPosition && childPosition <= action.getEndIndex()) && action.getKind() == kindOfAction) { - CMNode actionCMNode = action.getCMNode(); - if (actionCMNode != null && !cmnodes.contains(actionCMNode)) - cmnodes.add(actionCMNode); - } - } - return cmnodes; - } - - /** - * Similar to the call in HTMLContentAssistProcessor. Pass in a node, it - * tells you if the document is XML type. - * - * @param node - * - */ - protected boolean getXML(Node node) { - if (node == null) - return false; - - Document doc = null; - doc = (node.getNodeType() != Node.DOCUMENT_NODE) ? node.getOwnerDocument() : ((Document) node); - - return (doc instanceof IDOMDocument) && ((IDOMDocument) doc).isXMLType(); - } - - // Initialize local settings - protected void init() { - // implement in subclasses - } - - protected boolean isCloseRegion(ITextRegion region) { - String type = region.getType(); - return ((type == DOMRegionContext.XML_PI_CLOSE) || (type == DOMRegionContext.XML_TAG_CLOSE) || (type == DOMRegionContext.XML_EMPTY_TAG_CLOSE) || (type == DOMRegionContext.XML_CDATA_CLOSE) || (type == DOMRegionContext.XML_COMMENT_CLOSE) || (type == DOMRegionContext.XML_ATTLIST_DECL_CLOSE) || (type == DOMRegionContext.XML_ELEMENT_DECL_CLOSE) || (type == DOMRegionContext.XML_DOCTYPE_DECLARATION_CLOSE) || (type == DOMJSPRegionContextsPrivateCopy.JSP_CLOSE) || (type == DOMJSPRegionContextsPrivateCopy.JSP_COMMENT_CLOSE) || (type.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_CLOSE)) || (type == DOMRegionContext.XML_DECLARATION_CLOSE)); - } - - /* - * This is to determine if a tag is a special meta-info comment tag that - * shows up as an ELEMENT - */ - private boolean isCommentNode(IDOMNode node) { - return (node != null && node instanceof IDOMElement && ((IDOMElement) node).isCommentTag()); - } - - /** - * Checks if cursor position is after doctype tag... - * - * @param car - * - */ - protected boolean isCursorAfterDoctype(ContentAssistRequest car) { - Node aNode = car.getNode(); - Document parent = aNode.getOwnerDocument(); - int xmldoctypeNodePosition = -1; - boolean isAfterDoctype = true; - - if (parent == null) - return true; // blank document case - - for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) { - if (child instanceof IDOMNode) { - if (child.getNodeType() == Node.DOCUMENT_TYPE_NODE) { - xmldoctypeNodePosition = ((IDOMNode) child).getEndOffset(); - isAfterDoctype = (car.getReplacementBeginPosition() >= xmldoctypeNodePosition); - break; - } - } - } - return isAfterDoctype; - } - - /** - * This method can check if the cursor is after the XMLPI - * - * @param car - * - */ - protected boolean isCursorAfterXMLPI(ContentAssistRequest car) { - Node aNode = car.getNode(); - boolean xmlpiFound = false; - Document parent = aNode.getOwnerDocument(); - int xmlpiNodePosition = -1; - boolean isAfterXMLPI = false; - - if (parent == null) - return true; // blank document case - - for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) { - boolean xmlpi = (child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && child.getNodeName().equals("xml")); //$NON-NLS-1$ - xmlpiFound = xmlpiFound || xmlpi; - if (xmlpiFound) { - if (child instanceof IDOMNode) { - xmlpiNodePosition = ((IDOMNode) child).getEndOffset(); - isAfterXMLPI = (car.getReplacementBeginPosition() >= xmlpiNodePosition); - } - break; - } - } - return isAfterXMLPI; - } - - protected boolean isNameRegion(ITextRegion region) { - String type = region.getType(); - return ((type == DOMRegionContext.XML_TAG_NAME) || (type == DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_NAME) || (type == DOMRegionContext.XML_ELEMENT_DECL_NAME) || (type == DOMRegionContext.XML_DOCTYPE_NAME) || (type == DOMRegionContext.XML_ATTLIST_DECL_NAME) || (type == DOMJSPRegionContextsPrivateCopy.JSP_ROOT_TAG_NAME) || type.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_NAME)); - } - - protected boolean isQuote(String string) { - String trimmed = string.trim(); - if (trimmed.length() > 0) { - return trimmed.charAt(0) == '\'' || trimmed.charAt(0) == '"'; - } - return false; - } - - private boolean isSelfClosed(IStructuredDocumentRegion startTag) { - ITextRegionList regions = startTag.getRegions(); - return regions.get(regions.size() - 1).getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE; - } - - private boolean isStartTag(IStructuredDocumentRegion sdRegion) { - boolean result = false; - if (sdRegion.getRegions().size() > 0) { - ITextRegion r = sdRegion.getRegions().get(0); - result = r.getType() == DOMRegionContext.XML_TAG_OPEN && sdRegion.isEnded(); - } - return result; - } - - protected Properties mapToProperties(CMNamedNodeMap map) { - Properties p = new Properties(); - for (int i = 0; i < map.getLength(); i++) { - CMEntityDeclaration decl = (CMEntityDeclaration) map.item(i); - p.put(decl.getName(), decl.getValue()); - } - return p; - } - - /** - * Gets the corresponding XMLNode, and checks if it's closed. - * - * @param startTag - * - */ - private boolean needsEndTag(IStructuredDocumentRegion startTag) { - boolean result = false; - IStructuredModel sModel = StructuredModelManager.getModelManager().getExistingModelForRead(fTextViewer.getDocument()); - try { - if (sModel != null) { - IDOMNode xmlNode = (IDOMNode) sModel.getIndexedRegion(startTag.getStart()); - if (!isStartTag(startTag)) - result = false; - else if (isSelfClosed(startTag)) - result = false; - else if (!xmlNode.isContainer()) - result = false; - else - result = xmlNode.getEndStructuredDocumentRegion() == null; - } - } - finally { - if (sModel != null) - sModel.releaseFromRead(); - } - return result; - } - - protected ContentAssistRequest newContentAssistRequest(Node node, Node possibleParent, IStructuredDocumentRegion documentRegion, ITextRegion completionRegion, int begin, int length, String filter) { - return new ContentAssistRequest(node, possibleParent, documentRegion, completionRegion, begin, length, filter); - } - - public void release() { - fGenerator = null; - } - - /** - * Set the reason why computeProposals was not able to find any - * completions. - */ - public void setErrorMessage(String errorMessage) { - fErrorMessage = errorMessage; - } - - /** - * Set the reason why computeProposals was not able to find any - * completions. - */ - protected void setErrorMessage(String errorMessage, String append) { - setErrorMessage(errorMessage + append); - } - - /** - * Set the reason why computeProposals was not able to find any - * completions. - */ - protected void setErrorMessage(String errorMessage, String prepend, String append) { - setErrorMessage(prepend + errorMessage + append); - } - - protected boolean stringsEqual(String a, String b) { - // (pa) 221190 matching independent of case to be consistant with Java - // editor CA - return a.equalsIgnoreCase(b); - } -} |