blob: 3e19c10fe2a8c5940256e5ff5a24cb2b82307fe2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2022 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.wst.xml.ui.internal.contentassist;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.wst.sse.core.StructuredModelManager;
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.ui.contentassist.CompletionProposalInvocationContext;
import org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer;
import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
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.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* <p>Implements the framework for making proposals in XML type documents. Deals with
* all the nastiness needed to figure out where in an XML type document the content
* assist was invoked and then calls one of many abstract methods depending on the
* area the content assist was invoked. In this way implementers only have to worry about
* implementing what to do in each situation while not having to deal with figuring out
* which situation the content assist was invoked in.</p>
*
* @base org.eclipse.wst.xml.ui.internal.contentassist.AbstractContentAssistProcessor
* @see DefaultXMLCompletionProposalComputer
*/
public abstract class AbstractXMLCompletionProposalComputer implements ICompletionProposalComputer {
/**
* ISSUE: this is a bit of hidden JSP knowledge that was implemented this
* way for expediency. 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$
}
private String fErrorMessage;
private ITextViewer fTextViewer;
public AbstractXMLCompletionProposalComputer() {
fErrorMessage = null;
fTextViewer = null;
}
/**
* <p>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.</p>
*
* @see org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer#computeCompletionProposals(org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
*/
public List computeCompletionProposals(
CompletionProposalInvocationContext context,
IProgressMonitor monitor) {
ITextViewer textViewer = context.getViewer();
int documentPosition = context.getInvocationOffset();
setErrorMessage(null);
fTextViewer = textViewer;
IndexedRegion treeNode = ContentAssistUtils.getNodeAt(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 = null;
try {
if(textViewer.getDocument() instanceof IStructuredDocument) {
sModel = StructuredModelManager.getModelManager().getModelForRead((IStructuredDocument)textViewer.getDocument());
}
if (sModel != null) {
IDOMDocument docNode = ((IDOMModel) sModel).getDocument();
contentAssistRequest = new ContentAssistRequest(docNode, docNode, sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), null);
addEmptyDocumentProposals(contentAssistRequest, context);
}
}
finally {
if (sModel != null) {
sModel.releaseFromRead();
}
}
if (contentAssistRequest == null) {
Logger.logException(new IllegalStateException("problem getting model")); //$NON-NLS-1$
return new ArrayList(0);
}
ICompletionProposal[] props = contentAssistRequest.getCompletionProposals();
return (props != null) ? Arrays.asList(props) : new ArrayList(0);
}
// MASSIVE ERROR CONDITION
Logger.logException(new IllegalStateException("completion region was null")); //$NON-NLS-1$
setErrorMessage(XMLUIMessages.SEVERE_internal_error_occu_UI_);
contentAssistRequest = new ContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$
ICompletionProposal[] props = contentAssistRequest.getCompletionProposals();
return (props != null) ? Arrays.asList(props) : new ArrayList(0);
}
// 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(matchString, completionRegion,
(IDOMNode) treeNode,xmlnode, context);
ICompletionProposal[] props = contentAssistRequest.getCompletionProposals();
return (props != null) ? Arrays.asList(props) : new ArrayList(0);
}
// compute normal proposals
contentAssistRequest = computeCompletionProposals(matchString, completionRegion, (IDOMNode) treeNode, xmlnode, context);
if (contentAssistRequest == null) {
contentAssistRequest = new ContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$
setErrorMessage(XMLUIMessages.Content_Assist_not_availab_UI_);
}
/*
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=123892
* Only set this error message if nothing else was already set
**/
if (contentAssistRequest.getProposals().size() == 0 && getErrorMessage() == null) {
setErrorMessage(XMLUIMessages.Content_Assist_not_availab_UI_);
}
ICompletionProposal[] props = contentAssistRequest.getCompletionProposals();
return (props != null) ? Arrays.asList(props) : new ArrayList(0);
}
/**
* <p>Returns information about possible contexts based on the specified
* location within the document that corresponds to the current cursor
* position within the text viewer.</p>
*
* @see org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer#computeContextInformation(org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
*/
public List computeContextInformation(
CompletionProposalInvocationContext context,
IProgressMonitor monitor) {
//no default context info
return Collections.EMPTY_LIST;
}
/**
* @see org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer#getErrorMessage()
*/
public String getErrorMessage() {
return fErrorMessage;
}
/**
* Add proposals for attribute names
*
* @param contentAssistRequest
* @param context
*/
protected abstract void addAttributeNameProposals(ContentAssistRequest contentAssistRequest,
CompletionProposalInvocationContext context);
/**
* Add proposals for attribute values
*
* @param contentAssistRequest
* @param context
*/
protected abstract void addAttributeValueProposals(ContentAssistRequest contentAssistRequest,
CompletionProposalInvocationContext context);
/**
* Add comment proposals
*
* @param contentAssistRequest
* @param context
*/
protected abstract void addCommentProposal(ContentAssistRequest contentAssistRequest,
CompletionProposalInvocationContext context);
/**
* Add the proposals for a completely empty document
*
* @param contentAssistRequest
* @param context
*/
protected abstract void addEmptyDocumentProposals(ContentAssistRequest contentAssistRequest,
CompletionProposalInvocationContext context);
/**
* Add the proposals for the name in an end tag
*
* @param contentAssistRequest
* @param context
*/
protected abstract void addEndTagNameProposals(ContentAssistRequest contentAssistRequest,
CompletionProposalInvocationContext context);
/**
* Prompt for end tags to a non-empty Node that hasn't ended Handles these
* cases: <br>
* <tagOpen>| <br>
* <tagOpen>< |<br>
* <tagOpen></ |
*
* @param contentAssistRequest
* @param context
*/
protected abstract void addEndTagProposals(ContentAssistRequest contentAssistRequest,
CompletionProposalInvocationContext context);
/**
* Add entity proposals
*
* @param contentAssistRequest
* @param completionRegion
* @param treeNode
* @param context
*/
protected abstract void addEntityProposals(ContentAssistRequest contentAssistRequest,
ITextRegion completionRegion, IDOMNode treeNode, CompletionProposalInvocationContext context);
/**
* add entity proposals
*
* @param proposals
* @param map
* @param key
* @param nodeOffset
* @param sdRegion
* @param completionRegion
* @param context
*/
protected abstract void addEntityProposals(Vector proposals, Properties map, String key,
int nodeOffset, IStructuredDocumentRegion sdRegion, ITextRegion completionRegion,
CompletionProposalInvocationContext context);
/**
* Add PCData proposals
*
* @param nodeName
* @param contentAssistRequest
* @param context
*/
protected abstract void addPCDATAProposal(String nodeName, ContentAssistRequest contentAssistRequest,
CompletionProposalInvocationContext context);
/**
* Add start document proposals
*
* @param contentAssistRequest
* @param context
*/
protected abstract void addStartDocumentProposals(ContentAssistRequest contentAssistRequest,
CompletionProposalInvocationContext context);
/**
* Close an unclosed start tag
*
* @param contentAssistRequest
* @param context
*/
protected abstract void addTagCloseProposals(ContentAssistRequest contentAssistRequest,
CompletionProposalInvocationContext context);
/**
* Add tag insertion proposals
*
* @param contentAssistRequest
* @param childPosition
* @param context
*/
protected abstract void addTagInsertionProposals(ContentAssistRequest contentAssistRequest,
int childPosition, CompletionProposalInvocationContext context);
/**
* Add tag name proposals
*
* @param contentAssistRequest
* @param childPosition
* @param context
*/
protected abstract void addTagNameProposals(ContentAssistRequest contentAssistRequest,
int childPosition, CompletionProposalInvocationContext context);
/**
* @param errorMessage the reason why computeProposals was not able to find any
* completions.
*/
protected void setErrorMessage(String errorMessage) {
fErrorMessage = errorMessage;
}
/**
* <p>This does all the magic of figuring out where in the XML type document
* the content assist was invoked and then calling the corresponding method
* to add the correct proposals</p>
*
* <p><b>NOTE: </b>if overriding be sure to make super call back to this method otherwise
* you will loose all of the proposals generated by this method</p>
*
* @param matchString
* @param completionRegion
* @param treeNode
* @param xmlnode
* @param context
*
* @return {@link ContentAssistRequest} that now has all the proposals in it
*/
protected ContentAssistRequest computeCompletionProposals(String matchString, ITextRegion completionRegion,
IDOMNode treeNode, IDOMNode xmlnode, CompletionProposalInvocationContext context) {
int documentPosition = context.getInvocationOffset();
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(matchString, completionRegion, treeNode, xmlnode, context);
}
else if (regionType == DOMRegionContext.XML_TAG_NAME) {
contentAssistRequest = computeTagNameProposals(matchString, completionRegion,
treeNode, xmlnode, context);
}
else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
contentAssistRequest = computeAttributeProposals(matchString, completionRegion, treeNode, xmlnode, context);
}
else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
contentAssistRequest = computeEqualsProposals(matchString, completionRegion,
treeNode, xmlnode, context);
}
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 = new ContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
addTagCloseProposals(contentAssistRequest, context);
}
else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
contentAssistRequest = computeAttributeValueProposals(matchString, completionRegion, treeNode, xmlnode, context);
}
else if ((regionType == DOMRegionContext.XML_TAG_CLOSE) || (regionType == DOMRegionContext.XML_EMPTY_TAG_CLOSE) ||
(regionType.equals(DOMJSPRegionContextsPrivateCopy.JSP_DIRECTIVE_CLOSE))) {
contentAssistRequest = computeTagCloseProposals(matchString, completionRegion, treeNode, xmlnode, context);
}
else if (regionType == DOMRegionContext.XML_END_TAG_OPEN) {
contentAssistRequest = computeEndTagOpenProposals(matchString, completionRegion,
treeNode, xmlnode, context);
}
else if ((regionType == DOMRegionContext.XML_CONTENT) || (regionType == DOMRegionContext.XML_CHAR_REFERENCE) ||
(regionType == DOMRegionContext.XML_ENTITY_REFERENCE) || (regionType == DOMRegionContext.XML_PE_REFERENCE)) {
contentAssistRequest = computeContentProposals(matchString, completionRegion,
treeNode, xmlnode, context);
}
// 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 = new ContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
addTagInsertionProposals(contentAssistRequest, getElementPosition(treeNode), context);
addStartDocumentProposals(contentAssistRequest, context);
}
}
// Not a Document or Element? (odd cases go here for now)
else if (isCloseRegion(completionRegion)) {
contentAssistRequest = new ContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion) + completionRegion.getLength(), 0, matchString);
addStartDocumentProposals(contentAssistRequest, context);
if (documentPosition >= sdRegion.getTextEndOffset(completionRegion)) {
addTagInsertionProposals(contentAssistRequest, getElementPosition(treeNode) + 1, context);
}
}
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 = new ContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
addTagInsertionProposals(contentAssistRequest, getElementPosition(treeNode), context);
addStartDocumentProposals(contentAssistRequest, context);
}
return contentAssistRequest;
}
/**
* <p>Similar to {@link #computeCompletionProposals(CompletionProposalInvocationContext, IProgressMonitor)} only specificly for
* attribute proposals</p>
*
* <p>Implementers should not override this method, it is made available to implementers so that if they override
* {@link #computeCompletionProposals(String, ITextRegion, IDOMNode, IDOMNode, CompletionProposalInvocationContext)}
* they can call this method if needed</p>
*
* @param matchString
* @param completionRegion
* @param nodeAtOffset
* @param node
* @param context
* @return
*/
protected final ContentAssistRequest computeAttributeProposals(String matchString, ITextRegion completionRegion,
IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
int documentPosition = context.getInvocationOffset();
ITextViewer viewer = context.getViewer();
ContentAssistRequest contentAssistRequest = null;
IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
// if the attribute name is selected, replace it instead of creating a new attribute
if (documentPosition <= sdRegion.getStartOffset(completionRegion) && (viewer != null && viewer.getSelectedRange().y != (sdRegion.getEndOffset(completionRegion) - sdRegion.getStartOffset(completionRegion)))) {
// setup to insert new attributes
contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
}
else {
// Setup to replace an existing attribute name
contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
}
addAttributeNameProposals(contentAssistRequest, context);
contentAssistRequest.setReplacementBeginPosition(documentPosition);
contentAssistRequest.setReplacementLength(0);
if ((node.getFirstStructuredDocumentRegion() != null) && (!node.getFirstStructuredDocumentRegion().isEnded())) {
addTagCloseProposals(contentAssistRequest, context);
}
return contentAssistRequest;
}
/**
* <p>this is the position the cursor should be in after the proposal is
* applied</p>
*
* @param proposedText
* @return the position the cursor should be in after the proposal is
* applied
*/
protected static 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;
}
/**
* <p>helpful utility method for determining if one string starts with another one.
* This is case insensitive. If either are null then result is <code>true</code></p>
*
* @param aString the string to check to see if it starts with the given prefix
* @param prefix check that the given string starts with this prefix
*
* @return <code>true</code> if the given string starts with the given prefix,
* <code>false</code> otherwise
*/
protected static boolean beginsWith(String aString, String prefix) {
if ((aString == null) || (prefix == null)) {
return true;
}
return aString.toLowerCase().startsWith(prefix.toLowerCase());
}
private ContentAssistRequest computeAttributeValueProposals(String matchString, ITextRegion completionRegion,
IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
int documentPosition = context.getInvocationOffset();
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 = new ContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
addAttributeNameProposals(contentAssistRequest, context);
if ((actualNode.getFirstStructuredDocumentRegion() != null) && !actualNode.getFirstStructuredDocumentRegion().isEnded()) {
addTagCloseProposals(contentAssistRequest, context);
}
}
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 = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
addAttributeNameProposals(contentAssistRequest, context);
}
else {
int replaceLength = completionRegion.getTextLength();
//if container region, be sure replace length is only the attribute value region not the entire container
if(completionRegion instanceof ITextRegionContainer){
ITextRegion openRegion = ((ITextRegionContainer) completionRegion).getFirstRegion();
ITextRegion closeRegion = ((ITextRegionContainer) completionRegion).getLastRegion();
/*
* check to see if the container is opened the same way its closed.
* Such as:
* <img src=' '
* But not:
* <img src='
*
* </body>
* </html>
* In the latter case we only want to replace the opening text of the container
* Admittedly crude test, but effective.
*/
if(openRegion.getType() != closeRegion.getType()) {
replaceLength = openRegion.getTextLength();
}
}
contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion,
completionRegion, sdRegion.getStartOffset(completionRegion),
replaceLength, matchString);
addAttributeValueProposals(contentAssistRequest, context);
}
}
return contentAssistRequest;
}
private ContentAssistRequest computeContentProposals(String matchString, ITextRegion completionRegion,
IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
int documentPosition = context.getInvocationOffset();
ContentAssistRequest contentAssistRequest = null;
// setup to add children at the content node's position
contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, getStructuredDocumentRegion(documentPosition), completionRegion, documentPosition - matchString.length(), matchString.length(), matchString);
if ((node != null) && (node.getNodeType() == Node.DOCUMENT_NODE) && (((Document) node).getDoctype() == null)) {
addStartDocumentProposals(contentAssistRequest, context);
}
addTagInsertionProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
if (node.getNodeType() != Node.DOCUMENT_NODE) {
addEndTagProposals(contentAssistRequest, context);
}
// entities?
addEntityProposals(contentAssistRequest, completionRegion, node, context);
// addEntityProposals(contentAssistRequest);
return contentAssistRequest;
}
private ContentAssistRequest computeEndTagOpenProposals(String matchString, ITextRegion completionRegion,
IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
int documentPosition = context.getInvocationOffset();
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 = new ContentAssistRequest(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 = new ContentAssistRequest(nodeAtOffset, nodeAtOffset.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
}
else {
// normal case, this end tag is the parent
contentAssistRequest = new ContentAssistRequest(nodeAtOffset, nodeAtOffset, sdRegion, completionRegion, documentPosition, 0, matchString);
}
}
// if (documentPosition >= sdRegion.getStartOffset(completionRegion) +
// completionRegion.getTextLength())
addEndTagProposals(contentAssistRequest, context);
// else
if (completionRegionStart == documentPosition) {
// positioned at start of end tag
addTagInsertionProposals(contentAssistRequest, node.getChildNodes().getLength(), context);
}
return contentAssistRequest;
}
private ContentAssistRequest computeEqualsProposals(String matchString, ITextRegion completionRegion,
IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
int documentPosition = context.getInvocationOffset();
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 = new ContentAssistRequest(nodeAtOffset, node, sdRegion, valueRegion, sdRegion.getStartOffset(valueRegion), valueRegion.getTextLength(), matchString);
}
else {
// append an attribute value after the '='
contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
}
addAttributeValueProposals(contentAssistRequest, context);
return contentAssistRequest;
}
private ContentAssistRequest computeStartDocumentProposals(String matchString, ITextRegion completionRegion,
IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
int documentPosition = context.getInvocationOffset();
// setup for a non-empty document, but one that hasn't been formally
// started
ContentAssistRequest contentAssistRequest = null;
contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node,
getStructuredDocumentRegion(documentPosition), completionRegion,
documentPosition, 0, matchString);
addStartDocumentProposals(contentAssistRequest, context);
return contentAssistRequest;
}
private ContentAssistRequest computeTagCloseProposals(String matchString, ITextRegion completionRegion,
IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
int documentPosition = context.getInvocationOffset();
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 = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
addTagInsertionProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
if ((node.getNodeType() != Node.DOCUMENT_NODE) && (node.getEndStructuredDocumentRegion() == null)) {
addEndTagProposals(contentAssistRequest, context);
}
}
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 = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
if ((node.getNodeType() != Node.DOCUMENT_NODE) && (node.getEndStructuredDocumentRegion() != null)) {
addTagCloseProposals(contentAssistRequest, context);
}
if (sdRegion == nodeAtOffset.getFirstStructuredDocumentRegion()) {
contentAssistRequest.setReplacementBeginPosition(documentPosition);
contentAssistRequest.setReplacementLength(0);
addAttributeNameProposals(contentAssistRequest, context);
}
}
}
return contentAssistRequest;
}
private ContentAssistRequest computeTagNameProposals(String matchString, ITextRegion completionRegion,
IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
int documentPosition = context.getInvocationOffset();
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 = new ContentAssistRequest(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, context);
}
addTagCloseProposals(contentAssistRequest, context);
}
else {
// it's name
contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
sdRegion, completionRegion, documentPosition - matchString.length(),
matchString.length(), matchString);
addTagNameProposals(contentAssistRequest, getElementPosition(actualNode),
context);
}
}
else {
if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) {
// insert name
contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
sdRegion, completionRegion, documentPosition, 0, matchString);
}
else {
// replace name
contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion),
completionRegion.getTextLength(), matchString);
}
addEndTagNameProposals(contentAssistRequest, context);
}
}
}
else {
if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) {
// unclosed tag with only a name; should prompt for attributes
// and a close instead
contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion,
documentPosition - matchString.length(), matchString.length(), matchString);
addAttributeNameProposals(contentAssistRequest, context);
addTagCloseProposals(contentAssistRequest, context);
}
else {
if (sdRegion.getRegions().get(0).getType() != DOMRegionContext.XML_END_TAG_OPEN) {
int replaceLength = documentPosition - sdRegion.getStartOffset(completionRegion);
contentAssistRequest = new ContentAssistRequest(node, node.getParentNode(), sdRegion,
completionRegion, sdRegion.getStartOffset(completionRegion), replaceLength, matchString);
addTagNameProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
}
else {
IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(documentPosition);
if (actualNode != null) {
if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) {
contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
sdRegion, completionRegion, documentPosition, 0, matchString);
}
else {
contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(),
sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion),
completionRegion.getTextLength(), matchString);
}
addEndTagNameProposals(contentAssistRequest, context);
}
}
}
}
return contentAssistRequest;
}
private ContentAssistRequest computeTagOpenProposals(String matchString, ITextRegion completionRegion,
IDOMNode nodeAtOffset, IDOMNode node, CompletionProposalInvocationContext context) {
int documentPosition = context.getInvocationOffset();
ContentAssistRequest contentAssistRequest = null;
IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
if (sdRegion != nodeAtOffset.getFirstStructuredDocumentRegion() || sdRegion.getPrevious() != null && sdRegion.getPrevious().getLastRegion().getType() == DOMRegionContext.XML_TAG_OPEN) {
// completing the *first* XML_TAG_OPEN in "<<tagname"
IDOMNode actualNode = (IDOMNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
if (actualNode != null) {
if(sdRegion.getFirstRegion().getType() == DOMRegionContext.XML_END_TAG_OPEN) {
contentAssistRequest = new ContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
if(actualNode.hasChildNodes())
addTagNameProposals(contentAssistRequest,
getElementPosition(actualNode.getLastChild()), context);
else
addTagNameProposals(contentAssistRequest, 0, context);
}
else {
contentAssistRequest = new ContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
addTagNameProposals(contentAssistRequest, getElementPosition(actualNode), context);
}
addEndTagProposals(contentAssistRequest, context); // (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 = new ContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion,
completionRegion, documentPosition, 0, matchString);
addTagInsertionProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
addEndTagProposals(contentAssistRequest, context);
}
else if (node.getNodeType() == Node.DOCUMENT_NODE) {
// at the opening of the VERY first tag with a '<'
contentAssistRequest = new ContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion,
completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
addStartDocumentProposals(contentAssistRequest, context);
}
}
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)) &&
(sdRegion.getLastRegion().getType() == DOMRegionContext.XML_TAG_CLOSE || sdRegion.getLastRegion().getType() == DOMRegionContext.XML_EMPTY_TAG_CLOSE)){
// replace the existing name
contentAssistRequest = new ContentAssistRequest(node, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(name), name.getTextLength(), matchString);
}
else {
// insert a valid new name, or possibly an end tag
contentAssistRequest = new ContentAssistRequest(nodeAtOffset, ((Node) nodeAtOffset).getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
addEndTagProposals(contentAssistRequest, context);
contentAssistRequest.setReplacementBeginPosition(documentPosition);
contentAssistRequest.setReplacementLength(0);
}
addTagNameProposals(contentAssistRequest, getElementPosition(nodeAtOffset), context);
}
}
return contentAssistRequest;
}
private 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 ((region.getType() != DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) &&(offset > sdRegion.getStartOffset(region) + region.getTextLength())) { //attached XML_TAG_ATTRIBUTE_EQUALS filter due to #bug219992
// 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.
*/
private 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;
}
private 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 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) {
int start = offset;
int end = offset;
IDocument document = parent.getParentDocument();
try {
// rewind to break the "word"
while (start > 0 && !Character.isWhitespace(document.getChar(start - 1)) && document.getChar(start - 1) != '>') {
start--;
}
matchString = document.get(start, end - start);
}
catch (BadLocationException e) {
matchString = ""; //$NON-NLS-1$
Logger.logException(e);
}
}
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;
}
private 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;
}
private 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));
}
private 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));
}
/**
* StructuredTextViewer must be set before using this.
*/
private IStructuredDocumentRegion getStructuredDocumentRegion(int pos) {
return ContentAssistUtils.getStructuredDocumentRegion(fTextViewer, pos);
}
}