### Eclipse Workspace Patch 1.0 #P org.eclipse.wst.xsl.ui.tests Index: src/org/eclipse/wst/xsl/ui/tests/contentassist/TestTemplateModeCompletionProposal.java =================================================================== RCS file: /cvsroot/webtools/sourceediting/tests/org.eclipse.wst.xsl.ui.tests/src/org/eclipse/wst/xsl/ui/tests/contentassist/TestTemplateModeCompletionProposal.java,v retrieving revision 1.7 diff -u -r1.7 TestTemplateModeCompletionProposal.java --- src/org/eclipse/wst/xsl/ui/tests/contentassist/TestTemplateModeCompletionProposal.java 28 Apr 2009 17:55:51 -0000 1.7 +++ src/org/eclipse/wst/xsl/ui/tests/contentassist/TestTemplateModeCompletionProposal.java 21 Sep 2009 22:37:16 -0000 @@ -42,10 +42,13 @@ // assertEquals("Wrong offset returned", 471, offset); ICompletionProposal[] proposals = getProposals(offset); - assertProposalExists("\"#all\"", proposals); assertProposalExists("mode1", proposals); assertProposalExists("mode2", proposals); assertProposalExists("mode3", proposals); + + proposals = getXMLProposals(offset); + assertProposalExists("\"#all\"", proposals); + } finally { model.releaseFromEdit(); } Index: src/org/eclipse/wst/xsl/ui/tests/contentassist/XSLCompletionTest.java =================================================================== RCS file: /cvsroot/webtools/sourceediting/tests/org.eclipse.wst.xsl.ui.tests/src/org/eclipse/wst/xsl/ui/tests/contentassist/XSLCompletionTest.java,v retrieving revision 1.6 diff -u -r1.6 XSLCompletionTest.java --- src/org/eclipse/wst/xsl/ui/tests/contentassist/XSLCompletionTest.java 21 Aug 2009 23:43:19 -0000 1.6 +++ src/org/eclipse/wst/xsl/ui/tests/contentassist/XSLCompletionTest.java 21 Sep 2009 22:37:16 -0000 @@ -146,7 +146,7 @@ loadFileForTesting(xslFilePath); try { - ICompletionProposal[] proposals = getProposals(37,18); + ICompletionProposal[] proposals = getXMLProposals(37,18); assertTrue(proposals.length >= 1); ICompletionProposal proposal = proposals[0]; assertTrue("Wrong attribute proposal returned:", proposal @@ -162,7 +162,7 @@ loadFileForTesting(xslFilePath); try { - ICompletionProposal[] proposals = getProposals(31,58); + ICompletionProposal[] proposals = getXMLProposals(31,58); assertTrue(proposals.length >= 2); ICompletionProposal proposal = proposals[1]; Index: src/org/eclipse/wst/xsl/ui/tests/AbstractSourceViewerTest.java =================================================================== RCS file: /cvsroot/webtools/sourceediting/tests/org.eclipse.wst.xsl.ui.tests/src/org/eclipse/wst/xsl/ui/tests/AbstractSourceViewerTest.java,v retrieving revision 1.1 diff -u -r1.1 AbstractSourceViewerTest.java --- src/org/eclipse/wst/xsl/ui/tests/AbstractSourceViewerTest.java 28 Apr 2009 17:55:52 -0000 1.1 +++ src/org/eclipse/wst/xsl/ui/tests/AbstractSourceViewerTest.java 21 Sep 2009 22:37:16 -0000 @@ -39,6 +39,7 @@ import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; import org.eclipse.wst.sse.ui.internal.StructuredTextViewer; import org.eclipse.wst.xml.core.internal.encoding.XMLDocumentLoader; +import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentAssistProcessor; import org.eclipse.wst.xsl.ui.internal.StructuredTextViewerConfigurationXSL; import org.eclipse.wst.xsl.ui.internal.contentassist.XSLContentAssistProcessor; @@ -135,6 +136,11 @@ sourceViewer, offset); } + protected ICompletionProposal[] getXMLProposals(int offset) throws Exception { + return new XMLContentAssistProcessor().computeCompletionProposals( + sourceViewer, offset); + } + /** * Get the content completion proposals at lineNumber, numberOfCharacters. * Number of characters refers to how many total characters from the starting offset of the line. This is @@ -150,6 +156,12 @@ int offset = calculateOffset(lineNumber, numberOfCharacters); return new XSLContentAssistProcessor().computeCompletionProposals(sourceViewer, offset); } + + protected ICompletionProposal[] getXMLProposals(int lineNumber, int numberOfCharacters) throws BadLocationException { + int offset = calculateOffset(lineNumber, numberOfCharacters); + return new XMLContentAssistProcessor().computeCompletionProposals(sourceViewer, offset); + } + protected int calculateOffset(int lineNumber, int columnNumber) throws BadLocationException { #P org.eclipse.wst.xsl.ui Index: plugin.xml =================================================================== RCS file: /cvsroot/webtools/sourceediting/plugins/org.eclipse.wst.xsl.ui/plugin.xml,v retrieving revision 1.50 diff -u -r1.50 plugin.xml --- plugin.xml 30 Apr 2009 07:08:04 -0000 1.50 +++ plugin.xml 21 Sep 2009 22:37:19 -0000 @@ -1,6 +1,7 @@ + + + + + + Index: src/org/eclipse/wst/xsl/ui/internal/contentassist/XSLContentAssistProcessor.java =================================================================== RCS file: /cvsroot/webtools/sourceediting/plugins/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/internal/contentassist/XSLContentAssistProcessor.java,v retrieving revision 1.36 diff -u -r1.36 XSLContentAssistProcessor.java --- src/org/eclipse/wst/xsl/ui/internal/contentassist/XSLContentAssistProcessor.java 10 Apr 2009 22:04:43 -0000 1.36 +++ src/org/eclipse/wst/xsl/ui/internal/contentassist/XSLContentAssistProcessor.java 21 Sep 2009 22:37:19 -0000 @@ -22,17 +22,10 @@ import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.text.contentassist.IContextInformationValidator; -import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -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.ui.internal.contentassist.ContentAssistUtils; -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.contentassist.AbstractContentAssistProcessor; import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentAssistProcessor; import org.eclipse.wst.xsl.core.XSLCore; import org.eclipse.wst.xsl.ui.internal.Messages; -import org.w3c.dom.Node; /** * The XSL Content Assist Processor provides content assistance for various @@ -42,20 +35,11 @@ * @author David Carver * @since 1.0 */ -public class XSLContentAssistProcessor implements IContentAssistProcessor { +public class XSLContentAssistProcessor extends AbstractXSLContentAssistProcessor implements IContentAssistProcessor { - private String errorMessage = ""; //$NON-NLS-1$ - private ITextViewer textViewer = null; private ArrayList xslProposals; private ArrayList additionalProposals; - private IndexedRegion treeNode; - private Node node; - private IDOMNode xmlNode; - private IStructuredDocumentRegion sdRegion; - private ITextRegion completionRegion; - private String matchString; - private int cursorPosition; - + private ArrayList namespaces; /** * Provides an XSL Content Assist Processor class that is XSL aware and XML * aware. @@ -64,6 +48,8 @@ super(); xslProposals = new ArrayList(); additionalProposals = new ArrayList(); + namespaces = new ArrayList(); + namespaces.add(XSLCore.XSL_NAMESPACE_URI); } /** @@ -83,14 +69,14 @@ ITextViewer textViewer, int documentPosition) { initializeProposalVariables(textViewer, documentPosition); - ICompletionProposal[] xmlProposals = getXMLProposals(); + //ICompletionProposal[] xmlProposals = getXMLProposals(); additionalProposals = getAdditionalXSLElementProposals(); xslProposals = getXSLNamespaceProposals(); ArrayList proposalList = new ArrayList(); - addProposals(xmlProposals, proposalList); +// addProposals(xmlProposals, proposalList); proposalList.addAll(additionalProposals); proposalList.addAll(xslProposals); @@ -103,22 +89,6 @@ return combinedProposals; } - /** - * @param textViewer - * @param documentPosition - */ - private void initializeProposalVariables(ITextViewer textViewer, - int documentPosition) { - this.textViewer = textViewer; - cursorPosition = documentPosition; - treeNode = ContentAssistUtils.getNodeAt(textViewer, cursorPosition); - node = getActualDOMNode((Node) treeNode); - xmlNode = (IDOMNode) node; - sdRegion = getStructuredDocumentRegion(); - completionRegion = getCompletionRegion(cursorPosition, node); - matchString = getMatchString(sdRegion, completionRegion, cursorPosition); - } - private ArrayList getXSLNamespaceProposals() { if (XSLCore.isXSLNamespace(xmlNode)) { XSLContentAssistRequestFactory requestFactory = new XSLContentAssistRequestFactory( @@ -167,228 +137,6 @@ } /** - * @param node - * @return - */ - private Node getActualDOMNode(Node node) { - while ((node != null) && (node.getNodeType() == Node.TEXT_NODE) - && (node.getParentNode() != null)) { - node = node.getParentNode(); - } - return node; - } - - /** - * StructuredTextViewer must be set before using this. - * - * @param pos - * @return - */ - private IStructuredDocumentRegion getStructuredDocumentRegion() { - return ContentAssistUtils.getStructuredDocumentRegion(textViewer, - cursorPosition); - } - - /** - * 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-existent ITextRegion, such as for enumerated attribute values - * following an '=' sign. - * - * Copied from AbstractContentAssist Processor. - */ - 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(); - - 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) { - region = getCompletionRegion(offset, flatNode); - } else { - flatNode = node.getStructuredDocument().getRegionAtCharacterOffset( - offset); - if ((flatNode.getStartOffset() <= documentPosition) - && (flatNode.getEndOffset() >= documentPosition)) { - 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))) { - region = flatNode.getPrevious().getLastRegion(); - } else if (flatNode.getEndOffset() == documentPosition) { - region = flatNode.getLastRegion(); - } else { - region = flatNode.getFirstRegion(); - } - } else { - region = flatNode.getLastRegion(); - } - } - - return region; - } - - 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())) { - 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; - } - - private String getMatchString(IStructuredDocumentRegion parent, - ITextRegion aRegion, int offset) { - String matchString = ""; //$NON-NLS-1$ - - if (isNotMatchStringRegion(parent, aRegion, offset)) { - return matchString; - } - - if (hasMatchString(parent, aRegion, offset)) { - matchString = extractMatchString(parent, aRegion, offset); - } - return matchString; - } - - private boolean isNotMatchStringRegion(IStructuredDocumentRegion parent, ITextRegion aRegion, int offset) { - if (aRegion == null || parent == null) - return true; - - String regionType = aRegion.getType(); - int totalRegionOffset = parent.getStartOffset(aRegion) - + aRegion.getTextLength(); - return (isCloseRegion(aRegion) - || hasNoMatchString(offset, regionType, totalRegionOffset)); - } - - 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 == DOMRegionContext.XML_DECLARATION_CLOSE)); - } - - private boolean hasMatchString(IStructuredDocumentRegion parent, - ITextRegion aRegion, int offset) { - return (parent.getText(aRegion).length() > 0) - && (parent.getStartOffset(aRegion) < offset); - } - - private boolean hasNoMatchString(int offset, String regionType, - int totalRegionOffset) { - return regionType.equals(DOMRegionContext.XML_CONTENT) - || regionType.equals(DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) - || regionType.equals(DOMRegionContext.XML_TAG_OPEN) - || offset > totalRegionOffset; - } - - private String extractMatchString(IStructuredDocumentRegion parent, - ITextRegion aRegion, int offset) { - String matchString; - matchString = parent.getText(aRegion).substring(0, - offset - parent.getStartOffset(aRegion)); - if (matchString.startsWith("\"")) { //$NON-NLS-1$ - matchString = matchString.substring(1); - } - return matchString; - } - - /** * (non-Javadoc) * * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer, @@ -432,22 +180,16 @@ return null; } - /** - * (non-Javadoc) - * - * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage() - */ - public String getErrorMessage() { - return errorMessage; + public String getMaximumVersion() { + return "2.0"; //$NON-NLS-1$ } - /** - * Sets the error message for why content assistance didn't complete. - * - * @param errorMessage - */ - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; + public String getMinimumVersion() { + return "1.0"; //$NON-NLS-1$ + } + + public ArrayList getNamespaces() { + return null; } } Index: src/org/eclipse/wst/xsl/ui/internal/StructuredTextViewerConfigurationXSL.java =================================================================== RCS file: /cvsroot/webtools/sourceediting/plugins/org.eclipse.wst.xsl.ui/src/org/eclipse/wst/xsl/ui/internal/StructuredTextViewerConfigurationXSL.java,v retrieving revision 1.9 diff -u -r1.9 StructuredTextViewerConfigurationXSL.java --- src/org/eclipse/wst/xsl/ui/internal/StructuredTextViewerConfigurationXSL.java 10 Feb 2009 00:46:36 -0000 1.9 +++ src/org/eclipse/wst/xsl/ui/internal/StructuredTextViewerConfigurationXSL.java 21 Sep 2009 22:37:19 -0000 @@ -11,6 +11,11 @@ package org.eclipse.wst.xsl.ui.internal; +import java.util.ArrayList; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Platform; import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; import org.eclipse.jface.text.source.ISourceViewer; @@ -59,7 +64,22 @@ if ((partitionType.equals(IStructuredPartitions.DEFAULT_PARTITION)) || (partitionType.equals(IXMLPartitions.XML_DEFAULT)) || (partitionType.equals(IXSLPartitions.XSL_XPATH))) { - processors = new IContentAssistProcessor[] { new XSLContentAssistProcessor() }; + + IConfigurationElement[] config = Platform.getExtensionRegistry() + .getConfigurationElementsFor("org.eclipse.wst.xsl.ui.contentassit.processor"); //$NON-NLS-1$ + ArrayList eprocessors = new ArrayList(); + for (IConfigurationElement processor : config) { + try { + final Object o = processor.createExecutableExtension("class"); //$NON-NLS-1$ + eprocessors.add(o); + } catch (CoreException ex) { + + } + } + if (!eprocessors.isEmpty()) { + eprocessors.toArray(processors); + } + //processors = new IContentAssistProcessor[] { new XSLContentAssistProcessor() }; } else if (partitionType.equals(IStructuredPartitions.UNKNOWN_PARTITION)) { processors = new IContentAssistProcessor[] { new NoRegionContentAssistProcessor() }; } Index: schema/contentassitProcessor.exsd =================================================================== RCS file: schema/contentassitProcessor.exsd diff -N schema/contentassitProcessor.exsd --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ schema/contentassitProcessor.exsd 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,107 @@ + + + + + + + + + [Enter description of this extension point.] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The XSLT Processor implementation to use + + + + + + + + + + + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + Index: src/org/eclipse/wst/xsl/ui/internal/contentassist/AbstractXSLContentAssistProcessor.java =================================================================== RCS file: src/org/eclipse/wst/xsl/ui/internal/contentassist/AbstractXSLContentAssistProcessor.java diff -N src/org/eclipse/wst/xsl/ui/internal/contentassist/AbstractXSLContentAssistProcessor.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/wst/xsl/ui/internal/contentassist/AbstractXSLContentAssistProcessor.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,274 @@ +package org.eclipse.wst.xsl.ui.internal.contentassist; + +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; +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.ui.internal.contentassist.ContentAssistUtils; +import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; +import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext; +import org.w3c.dom.Node; + +public abstract class AbstractXSLContentAssistProcessor implements IXSLContentAssistProcessor { + + protected String errorMessage = ""; //$NON-NLS-1$ + protected ITextViewer textViewer = null; + private IndexedRegion treeNode; + private Node node; + protected IDOMNode xmlNode; + protected IStructuredDocumentRegion sdRegion; + protected ITextRegion completionRegion; + protected String matchString; + protected int cursorPosition; + + /** + * @param textViewer + * @param documentPosition + */ + protected void initializeProposalVariables(ITextViewer textViewer, int documentPosition) { + this.textViewer = textViewer; + cursorPosition = documentPosition; + treeNode = ContentAssistUtils.getNodeAt(textViewer, cursorPosition); + node = getActualDOMNode((Node) treeNode); + xmlNode = (IDOMNode) node; + sdRegion = getStructuredDocumentRegion(); + completionRegion = getCompletionRegion(cursorPosition, node); + matchString = getMatchString(sdRegion, completionRegion, cursorPosition); + } + + /** + * @param node + * @return + */ + private Node getActualDOMNode(Node node) { + while ((node != null) && (node.getNodeType() == Node.TEXT_NODE) + && (node.getParentNode() != null)) { + node = node.getParentNode(); + } + return node; + } + + /** + * StructuredTextViewer must be set before using this. + * + * @param pos + * @return + */ + private IStructuredDocumentRegion getStructuredDocumentRegion() { + return ContentAssistUtils.getStructuredDocumentRegion(textViewer, + cursorPosition); + } + + /** + * 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-existent ITextRegion, such as for enumerated attribute values + * following an '=' sign. + * + * Copied from AbstractContentAssist Processor. + */ + 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(); + + 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) { + region = getCompletionRegion(offset, flatNode); + } else { + flatNode = node.getStructuredDocument().getRegionAtCharacterOffset( + offset); + if ((flatNode.getStartOffset() <= documentPosition) + && (flatNode.getEndOffset() >= documentPosition)) { + 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))) { + region = flatNode.getPrevious().getLastRegion(); + } else if (flatNode.getEndOffset() == documentPosition) { + region = flatNode.getLastRegion(); + } else { + region = flatNode.getFirstRegion(); + } + } else { + region = flatNode.getLastRegion(); + } + } + + return region; + } + + 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())) { + 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; + } + + private String getMatchString(IStructuredDocumentRegion parent, ITextRegion aRegion, int offset) { + String matchString = ""; //$NON-NLS-1$ + + if (isNotMatchStringRegion(parent, aRegion, offset)) { + return matchString; + } + + if (hasMatchString(parent, aRegion, offset)) { + matchString = extractMatchString(parent, aRegion, offset); + } + return matchString; + } + + private boolean isNotMatchStringRegion(IStructuredDocumentRegion parent, ITextRegion aRegion, int offset) { + if (aRegion == null || parent == null) + return true; + + String regionType = aRegion.getType(); + int totalRegionOffset = parent.getStartOffset(aRegion) + + aRegion.getTextLength(); + return (isCloseRegion(aRegion) + || hasNoMatchString(offset, regionType, totalRegionOffset)); + } + + 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 == DOMRegionContext.XML_DECLARATION_CLOSE)); + } + + private boolean hasMatchString(IStructuredDocumentRegion parent, ITextRegion aRegion, int offset) { + return (parent.getText(aRegion).length() > 0) + && (parent.getStartOffset(aRegion) < offset); + } + + private boolean hasNoMatchString(int offset, String regionType, int totalRegionOffset) { + return regionType.equals(DOMRegionContext.XML_CONTENT) + || regionType.equals(DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) + || regionType.equals(DOMRegionContext.XML_TAG_OPEN) + || offset > totalRegionOffset; + } + + private String extractMatchString(IStructuredDocumentRegion parent, ITextRegion aRegion, int offset) { + String matchString; + matchString = parent.getText(aRegion).substring(0, + offset - parent.getStartOffset(aRegion)); + if (matchString.startsWith("\"")) { //$NON-NLS-1$ + matchString = matchString.substring(1); + } + return matchString; + } + + /** + * (non-Javadoc) + * + * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage() + */ + public String getErrorMessage() { + return errorMessage; + } + + /** + * Sets the error message for why content assistance didn't complete. + * + * @param errorMessage + */ + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + +} Index: src/org/eclipse/wst/xsl/ui/internal/contentassist/IXSLContentAssistProcessor.java =================================================================== RCS file: src/org/eclipse/wst/xsl/ui/internal/contentassist/IXSLContentAssistProcessor.java diff -N src/org/eclipse/wst/xsl/ui/internal/contentassist/IXSLContentAssistProcessor.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/wst/xsl/ui/internal/contentassist/IXSLContentAssistProcessor.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,17 @@ +package org.eclipse.wst.xsl.ui.internal.contentassist; + +import java.util.ArrayList; + +public interface IXSLContentAssistProcessor { + + /** + * ArrayList of Strings for the namespaces this processor activates against. + * @return + */ + public ArrayList getNamespaces(); + + public String getMinimumVersion(); + + public String getMaximumVersion(); + +}