blob: f76c2071195a18d2baa0bde05d135f3c2e708ca3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 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
*******************************************************************************/
package org.eclipse.jst.jsp.ui.internal.contentassist;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IDocumentPartitioner;
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.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
import org.eclipse.jst.jsp.core.text.IJSPPartitions;
import org.eclipse.jst.jsp.ui.internal.JSPUIMessages;
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.IStructuredPartitioning;
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.ui.internal.IReleasable;
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.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.eclipse.wst.xml.ui.internal.contentassist.XMLRelevanceConstants;
import org.eclipse.wst.xml.ui.internal.util.SharedXMLEditorPluginImageHelper;
/**
* @plannedfor 1.0
*/
public class JSPJavaContentAssistProcessor implements IContentAssistProcessor, IReleasable {
protected char completionProposalAutoActivationCharacters[] = new char[]{'.'};
protected char contextInformationAutoActivationCharacters[] = null;
protected static final String UNKNOWN_CONTEXT = JSPUIMessages.Content_Assist_not_availab_UI_;
protected String fErrorMessage = null;
protected JSPCompletionProcessor fJspCompletionProcessor = null;
public JSPJavaContentAssistProcessor() {
super();
}
/**
* 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 documentPosition a location within the document
* @return an array of code-assist items
*/
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentPosition) {
IndexedRegion treeNode = ContentAssistUtils.getNodeAt(viewer, documentPosition);
// get results from JSP completion processor
fJspCompletionProcessor = getJspCompletionProcessor();
ICompletionProposal[] results = fJspCompletionProcessor.computeCompletionProposals(viewer, documentPosition);
fErrorMessage = fJspCompletionProcessor.getErrorMessage();
if (results.length == 0 && (fErrorMessage == null || fErrorMessage.length() == 0)) {
fErrorMessage = UNKNOWN_CONTEXT;
}
IDOMNode xNode = null;
IStructuredDocumentRegion flat = null;
if (treeNode instanceof IDOMNode) {
xNode = (IDOMNode) treeNode;
flat = xNode.getFirstStructuredDocumentRegion();
if (flat != null && flat.getType() == DOMJSPRegionContexts.JSP_CONTENT) {
flat = flat.getPrevious();
}
}
// this is in case it's a <%@, it will be a region container...
ITextRegion openRegion = null;
if (flat != null && flat instanceof ITextRegionContainer) {
ITextRegionList v = ((ITextRegionContainer) flat).getRegions();
if (v.size() > 0)
openRegion = v.get(0);
}
// ADD CDATA PROPOSAL IF IT'S AN XML-JSP TAG
if (flat != null && flat.getType() != DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN && flat.getType() != DOMJSPRegionContexts.JSP_DECLARATION_OPEN && flat.getType() != DOMJSPRegionContexts.JSP_EXPRESSION_OPEN && flat.getType() != DOMRegionContext.BLOCK_TEXT && (openRegion != null && openRegion.getType() != DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN) && !inAttributeRegion(flat, documentPosition)) {
// determine if cursor is before or after selected range
int adjustedDocPosition = documentPosition;
int realCaretPosition = viewer.getTextWidget().getCaretOffset();
int selectionLength = viewer.getSelectedRange().y;
if (documentPosition > realCaretPosition) {
adjustedDocPosition -= selectionLength;
}
CustomCompletionProposal cdataProposal = createCDATAProposal(adjustedDocPosition, selectionLength);
ICompletionProposal[] newResults = new ICompletionProposal[results.length + 1];
System.arraycopy(results, 0, newResults, 0, results.length);
newResults[results.length] = cdataProposal;
results = newResults;
}
// (pa) ** this is code in progress...
// add ending %> proposal for non closed JSP tags
// String tagText = flat.getText();
// // TODO need a much better compare (using constants?)
// if(tagText.equals("<%") || tagText.equals("<%=") || tagText.equals("<%!"));
// {
// ICompletionProposal testah = ContentAssistUtils.computeJSPEndTagProposal(viewer,documentPosition, treeNode, "<%" , SharedXMLEditorPluginImageHelper.IMG_OBJ_TAG_GENERIC);
// if(testah != null)
// {
// ICompletionProposal[] newResults = new ICompletionProposal[results.length + 1];
// System.arraycopy( results, 0, newResults, 0, results.length);
// newResults[results.length] = testah;
// results = newResults;
// }
// }
return results;
}
private CustomCompletionProposal createCDATAProposal(int adjustedDocPosition, int selectionLength) {
return new CustomCompletionProposal("<![CDATA[]]>", //$NON-NLS-1$
adjustedDocPosition, selectionLength, // should be the selection length
9, SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_CDATASECTION),
"CDATA Section", //$NON-NLS-1$
null, null, XMLRelevanceConstants.R_CDATA);
}
private boolean inAttributeRegion(IStructuredDocumentRegion flat, int documentPosition) {
ITextRegion attrContainer = flat.getRegionAtCharacterOffset(documentPosition);
if (attrContainer != null && attrContainer instanceof ITextRegionContainer) {
if (attrContainer.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
return true;
}
}
return false;
}
/**
* Returns the characters which when entered by the user should
* automatically trigger the presentation of possible completions.
*
* @return the auto activation characters for completion proposal or <code>null</code>
* if no auto activation is desired
*/
public char[] getCompletionProposalAutoActivationCharacters() {
return completionProposalAutoActivationCharacters;
}
/**
* Returns the characters which when entered by the user should
* automatically trigger the presentation of context information.
*
* @return the auto activation characters for presenting context information
* or <code>null</code> if no auto activation is desired
*/
public char[] getContextInformationAutoActivationCharacters() {
return contextInformationAutoActivationCharacters;
}
/**
* Return the reason why computeProposals was not able to find any completions.
*
* @return an error message
* or null if no error occurred
*/
public String getErrorMessage() {
return fErrorMessage;
}
/**
* @see ContentAssistAdapter#release()
*/
public void release() {
if (fJspCompletionProcessor != null) {
fJspCompletionProcessor.release();
fJspCompletionProcessor = null;
}
}
/**
*
*/
protected JSPCompletionProcessor getJspCompletionProcessor() {
if (fJspCompletionProcessor == null) {
fJspCompletionProcessor = new JSPCompletionProcessor();
}
return fJspCompletionProcessor;
}
/**
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer, int)
*/
public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) {
List results = new ArrayList();
// need to compute context info here, if it's JSP, call java computer
IDocument doc = viewer.getDocument();
IDocumentPartitioner dp = null;
if(doc instanceof IDocumentExtension3) {
dp = ((IDocumentExtension3)doc).getDocumentPartitioner(IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING);
}
if(dp != null) {
//IDocumentPartitioner dp = viewer.getDocument().getDocumentPartitioner();
String type = dp.getPartition(documentOffset).getType();
if (type == IJSPPartitions.JSP_DEFAULT || type == IJSPPartitions.JSP_CONTENT_JAVA) {
// get context info from completion results...
ICompletionProposal[] proposals = computeCompletionProposals(viewer, documentOffset);
for (int i = 0; i < proposals.length; i++) {
IContextInformation ci = proposals[i].getContextInformation();
if (ci != null)
results.add(ci);
}
}
}
return (IContextInformation[]) results.toArray(new IContextInformation[results.size()]);
}
/**
* 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.
*
* @return a context information validator, or <code>null</code> if the processor
* is incapable of computing context information
*/
public IContextInformationValidator getContextInformationValidator() {
return new JavaParameterListValidator();
}
}