/********************************************************************** Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html Contributors: IBM Corporation - Initial implementation Klaus Hartlage - www.eclipseproject.de **********************************************************************/ package net.sourceforge.phpeclipse.phpeditor.php; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import net.sourceforge.phpdt.internal.corext.template.ContextType; import net.sourceforge.phpdt.internal.corext.template.ContextTypeRegistry; import net.sourceforge.phpdt.internal.ui.text.java.IPHPCompletionProposal; import net.sourceforge.phpdt.internal.ui.text.java.PHPCompletionProposalComparator; import net.sourceforge.phpdt.internal.ui.text.template.BuiltInEngine; import net.sourceforge.phpdt.internal.ui.text.template.IdentifierEngine; import net.sourceforge.phpdt.internal.ui.text.template.TemplateEngine; import net.sourceforge.phpeclipse.PHPeclipsePlugin; import net.sourceforge.phpeclipse.phpeditor.PHPContentOutlinePage; import net.sourceforge.phpeclipse.phpeditor.PHPEditor; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.TextPresentation; 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.IContextInformationExtension; import org.eclipse.jface.text.contentassist.IContextInformationPresenter; import org.eclipse.jface.text.contentassist.IContextInformationValidator; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.IEditorPart; /** * Example PHP completion processor. */ public class PHPCompletionProcessor implements IContentAssistProcessor { /** * Simple content assist tip closer. The tip is valid in a range * of 5 characters around its popup location. */ protected static class Validator implements IContextInformationValidator, IContextInformationPresenter { protected int fInstallOffset; /* * @see IContextInformationValidator#isContextInformationValid(int) */ public boolean isContextInformationValid(int offset) { return Math.abs(fInstallOffset - offset) < 5; } /* * @see IContextInformationValidator#install(IContextInformation, ITextViewer, int) */ public void install(IContextInformation info, ITextViewer viewer, int offset) { fInstallOffset = offset; } /* * @see org.eclipse.jface.text.contentassist.IContextInformationPresenter#updatePresentation(int, TextPresentation) */ public boolean updatePresentation(int documentPosition, TextPresentation presentation) { return false; } }; private static class ContextInformationWrapper implements IContextInformation, IContextInformationExtension { private final IContextInformation fContextInformation; private int fPosition; public ContextInformationWrapper(IContextInformation contextInformation) { fContextInformation = contextInformation; } /* * @see IContextInformation#getContextDisplayString() */ public String getContextDisplayString() { return fContextInformation.getContextDisplayString(); } /* * @see IContextInformation#getImage() */ public Image getImage() { return fContextInformation.getImage(); } /* * @see IContextInformation#getInformationDisplayString() */ public String getInformationDisplayString() { return fContextInformation.getInformationDisplayString(); } /* * @see IContextInformationExtension#getContextInformationPosition() */ public int getContextInformationPosition() { return fPosition; } public void setContextInformationPosition(int position) { fPosition = position; } }; // public final class VariablesCompletionProposal implements IJavaCompletionProposal { // private String fDisplayString; // private String fReplacementString; // private int fReplacementOffset; // private int fReplacementLength; // private int fCursorPosition; // private Image fImage; // private IContextInformation fContextInformation; // private String fAdditionalProposalInfo; // // /** // * Creates a new completion proposal based on the provided information. The replacement string is // * considered being the display string too. All remaining fields are set to null. // * // * @param replacementString the actual string to be inserted into the document // * @param replacementOffset the offset of the text to be replaced // * @param replacementLength the length of the text to be replaced // * @param cursorPosition the position of the cursor following the insert relative to replacementOffset // */ // public VariablesCompletionProposal( // String replacementString, // int replacementOffset, // int replacementLength, // int cursorPosition) { // this(replacementString, replacementOffset, replacementLength, cursorPosition, null, null, null, null); // } // // /** // * Creates a new completion proposal. All fields are initialized based on the provided information. // * // * @param replacementString the actual string to be inserted into the document // * @param replacementOffset the offset of the text to be replaced // * @param replacementLength the length of the text to be replaced // * @param cursorPosition the position of the cursor following the insert relative to replacementOffset // * @param image the image to display for this proposal // * @param displayString the string to be displayed for the proposal // * @param contentInformation the context information associated with this proposal // * @param additionalProposalInfo the additional information associated with this proposal // */ // public VariablesCompletionProposal( // String replacementString, // int replacementOffset, // int replacementLength, // int cursorPosition, // Image image, // String displayString, // IContextInformation contextInformation, // String additionalProposalInfo) { // // Assert.isNotNull(replacementString); // // Assert.isTrue(replacementOffset >= 0); // // Assert.isTrue(replacementLength >= 0); // // Assert.isTrue(cursorPosition >= 0); // // fReplacementString = replacementString; // fReplacementOffset = replacementOffset; // fReplacementLength = replacementLength; // fCursorPosition = cursorPosition; // fImage = image; // fDisplayString = displayString; // fContextInformation = contextInformation; // fAdditionalProposalInfo = additionalProposalInfo; // } // // /* // * @see ICompletionProposal#apply // */ // public void apply(IDocument document) { // try { // document.replace(fReplacementOffset, fReplacementLength, fReplacementString); // } catch (BadLocationException x) { // // ignore // } // } // // /* // * @see ICompletionProposal#getSelection // */ // public Point getSelection(IDocument document) { // return new Point(fReplacementOffset + fCursorPosition, 0); // } // // /* // * @see ICompletionProposal#getContextInformation() // */ // public IContextInformation getContextInformation() { // return fContextInformation; // } // // /* // * @see ICompletionProposal#getImage() // */ // public Image getImage() { // return fImage; // } // // /* // * @see ICompletionProposal#getDisplayString() // */ // public String getDisplayString() { // if (fDisplayString != null) // return fDisplayString; // return fReplacementString; // } // // /* // * @see ICompletionProposal#getAdditionalProposalInfo() // */ // public String getAdditionalProposalInfo() { // return fAdditionalProposalInfo; // } // /** // * Returns the relevance of the proposal. // */ // public int getRelevance() { // return 0; // } // } protected final static String[] fgProposals = PHPFunctionNames.FUNCTION_NAMES; private char[] fProposalAutoActivationSet; protected IContextInformationValidator fValidator = new Validator(); private TemplateEngine fTemplateEngine; private PHPCompletionProposalComparator fComparator; private int fNumberOfComputedResults = 0; public PHPCompletionProcessor() { ContextType contextType = ContextTypeRegistry.getInstance().getContextType("php"); //$NON-NLS-1$ if (contextType != null) fTemplateEngine = new TemplateEngine(contextType); fComparator = new PHPCompletionProposalComparator(); } /** * Sets this processor's set of characters triggering the activation of the * completion proposal computation. * * @param activationSet the activation set */ public void setCompletionProposalAutoActivationCharacters(char[] activationSet) { fProposalAutoActivationSet= activationSet; } /* (non-Javadoc) * Method declared on IContentAssistProcessor */ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) { // IDocument document = viewer.getDocument(); // if (documentOffset > 0) { // try { // ICompletionProposal[] result; // char character = document.getChar(documentOffset - 1); // if (character == '$') { ////viewer. .getActivePage().getActiveEditor(); // result = new ICompletionProposal[fgProposals.length]; // for (int i = 0; i < fgProposals.length; i++) { // IContextInformation info = new ContextInformation(fgProposals[i], MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.Proposal.ContextInfo.pattern"), new Object[] { fgProposals[i] })); //$NON-NLS-1$ // result[i] = new CompletionProposal(fgProposals[i], documentOffset, 0, fgProposals[i].length(), null, fgProposals[i], info, MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.Proposal.hoverinfo.pattern"), new Object[] { fgProposals[i] })); //$NON-NLS-1$ // } // return result; // } // } catch (BadLocationException e) { // return new ICompletionProposal[0]; // } // } // // ICompletionProposal[] result = new ICompletionProposal[fgProposals.length]; // for (int i = 0; i < fgProposals.length; i++) { // IContextInformation info = new ContextInformation(fgProposals[i], MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.Proposal.ContextInfo.pattern"), new Object[] { fgProposals[i] })); //$NON-NLS-1$ // result[i] = new CompletionProposal(fgProposals[i], documentOffset, 0, fgProposals[i].length(), null, fgProposals[i], info, MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.Proposal.hoverinfo.pattern"), new Object[] { fgProposals[i] })); //$NON-NLS-1$ // } // return result; int contextInformationPosition = guessContextInformationPosition(viewer, documentOffset); return internalComputeCompletionProposals(viewer, documentOffset, contextInformationPosition); } private ICompletionProposal[] internalComputeCompletionProposals(ITextViewer viewer, int offset, int contextOffset) { IDocument document = viewer.getDocument(); Object[] identifiers = null; if (offset > 0) { PHPEditor editor = null; PHPContentOutlinePage outlinePage = null; IEditorPart targetEditor = PHPeclipsePlugin.getActiveWorkbenchWindow().getActivePage().getActiveEditor(); if (targetEditor != null && (targetEditor instanceof PHPEditor)) { editor = (PHPEditor) targetEditor; outlinePage = editor.getfOutlinePage(); identifiers = outlinePage.getVariables(); } } if (fTemplateEngine != null) { ICompletionProposal[] results; // try { fTemplateEngine.reset(); fTemplateEngine.complete(viewer, offset); //, unit); // } catch (JavaModelException x) { // Shell shell= viewer.getTextWidget().getShell(); // ErrorDialog.openError(shell, JavaTextMessages.getString("CompletionProcessor.error.accessing.title"), JavaTextMessages.getString("CompletionProcessor.error.accessing.message"), x.getStatus()); //$NON-NLS-2$ //$NON-NLS-1$ // } IPHPCompletionProposal[] templateResults = fTemplateEngine.getResults(); IPHPCompletionProposal[] identifierResults = new IPHPCompletionProposal[0]; if (identifiers != null) { IdentifierEngine identifierEngine; String proposal; // int j = 0; // for (int i = templateResults.length; i < templateResults.length + variables.length; i++) { // proposal = (String) variables[j++]; // IContextInformation info = new ContextInformation(proposal, MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.Proposal.ContextInfo.pattern"), new Object[] { proposal })); //$NON-NLS-1$ // results[i] = new VariablesCompletionProposal(proposal, offset, 0, proposal.length(), null, proposal, info, MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.Proposal.hoverinfo.pattern"), new Object[] { proposal })); //$NON-NLS-1$ // } ContextType contextType = ContextTypeRegistry.getInstance().getContextType("php"); //$NON-NLS-1$ if (contextType != null) { identifierEngine = new IdentifierEngine(contextType); identifierEngine.complete(viewer, offset, identifiers); identifierResults = identifierEngine.getResults(); } } IPHPCompletionProposal[] builtinResults = new IPHPCompletionProposal[0]; if (PHPFunctionNames.FUNCTION_NAMES != null) { BuiltInEngine builtinEngine; String proposal; ContextType contextType = ContextTypeRegistry.getInstance().getContextType("php"); //$NON-NLS-1$ if (contextType != null) { builtinEngine = new BuiltInEngine(contextType); builtinEngine.complete(viewer, offset, PHPFunctionNames.FUNCTION_NAMES); builtinResults = builtinEngine.getResults(); } } // concatenate arrays IPHPCompletionProposal[] total; total = new IPHPCompletionProposal[templateResults.length + identifierResults.length + builtinResults.length]; System.arraycopy(templateResults, 0, total, 0, templateResults.length); System.arraycopy(identifierResults, 0, total, templateResults.length, identifierResults.length); System.arraycopy(builtinResults, 0, total, templateResults.length + identifierResults.length, builtinResults.length); results = total; fNumberOfComputedResults = (results == null ? 0 : results.length); /* * Order here and not in result collector to make sure that the order * applies to all proposals and not just those of the compilation unit. */ return order(results); } return new IPHPCompletionProposal[0]; } private int guessContextInformationPosition(ITextViewer viewer, int offset) { int contextPosition = offset; IDocument document = viewer.getDocument(); // try { // // PHPCodeReader reader= new PHPCodeReader(); // reader.configureBackwardReader(document, offset, true, true); // // int nestingLevel= 0; // // int curr= reader.read(); // while (curr != PHPCodeReader.EOF) { // // if (')' == (char) curr) // ++ nestingLevel; // // else if ('(' == (char) curr) { // -- nestingLevel; // // if (nestingLevel < 0) { // int start= reader.getOffset(); // if (looksLikeMethod(reader)) // return start + 1; // } // } // // curr= reader.read(); // } // } catch (IOException e) { // } return contextPosition; } /* (non-Javadoc) * Method declared on IContentAssistProcessor */ // public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) { // IContextInformation[] result = new IContextInformation[5]; // for (int i = 0; i < result.length; i++) // result[i] = new ContextInformation(MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.ContextInfo.display.pattern"), new Object[] { new Integer(i), new Integer(documentOffset)}), //$NON-NLS-1$ // MessageFormat.format(PHPEditorMessages.getString("CompletionProcessor.ContextInfo.value.pattern"), new Object[] { new Integer(i), new Integer(documentOffset - 5), new Integer(documentOffset + 5)})); //$NON-NLS-1$ // return result; // } /** * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int) */ public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { int contextInformationPosition = guessContextInformationPosition(viewer, offset); List result = addContextInformations(viewer, contextInformationPosition); return (IContextInformation[]) result.toArray(new IContextInformation[result.size()]); } private List addContextInformations(ITextViewer viewer, int offset) { ICompletionProposal[] proposals = internalComputeCompletionProposals(viewer, offset, -1); List result = new ArrayList(); for (int i = 0; i < proposals.length; i++) { IContextInformation contextInformation = proposals[i].getContextInformation(); if (contextInformation != null) { ContextInformationWrapper wrapper = new ContextInformationWrapper(contextInformation); wrapper.setContextInformationPosition(offset); result.add(wrapper); } } return result; } /** * Order the given proposals. */ private ICompletionProposal[] order(ICompletionProposal[] proposals) { Arrays.sort(proposals, fComparator); return proposals; } /* (non-Javadoc) * Method declared on IContentAssistProcessor */ public char[] getCompletionProposalAutoActivationCharacters() { return fProposalAutoActivationSet; // return null; // new char[] { '$' }; } /* (non-Javadoc) * Method declared on IContentAssistProcessor */ public char[] getContextInformationAutoActivationCharacters() { return new char[] { }; } /* (non-Javadoc) * Method declared on IContentAssistProcessor */ public IContextInformationValidator getContextInformationValidator() { return fValidator; } /* (non-Javadoc) * Method declared on IContentAssistProcessor */ public String getErrorMessage() { return null; } }