/******************************************************************************* * Copyright (c) 2009 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 * Zend Technologies *******************************************************************************/ package org.eclipse.php.internal.ui.editor.contentassist; import org.eclipse.core.runtime.Platform; import org.eclipse.dltk.core.*; import org.eclipse.dltk.internal.ui.text.hover.CompletionHoverControlCreator; import org.eclipse.dltk.ui.PreferenceConstants; import org.eclipse.dltk.ui.text.ScriptTextTools; import org.eclipse.dltk.ui.text.completion.ScriptOverrideCompletionProposal; import org.eclipse.jface.internal.text.html.BrowserInformationControl; import org.eclipse.jface.text.*; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.contentassist.ContextInformation; import org.eclipse.jface.text.contentassist.ICompletionProposalExtension4; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.viewers.StyledString; import org.eclipse.php.core.compiler.PHPFlags; import org.eclipse.php.core.compiler.ast.nodes.NamespaceReference; import org.eclipse.php.internal.core.PHPCoreConstants; import org.eclipse.php.internal.core.PHPCorePlugin; import org.eclipse.php.internal.ui.PHPUiPlugin; import org.eclipse.swt.widgets.Shell; public class PHPOverrideCompletionProposal extends ScriptOverrideCompletionProposal implements ICompletionProposalExtension4 { /** * The control creator. */ private IInformationControlCreator fCreator; public PHPOverrideCompletionProposal(IScriptProject jproject, ISourceModule cu, String methodName, String[] paramTypes, int start, int length, StyledString displayName, String completionProposal) { super(jproject, cu, methodName, paramTypes, start, length, displayName.toString(), completionProposal); setStyledDisplayString(displayName); } @Override public void apply(IDocument document, char trigger, int offset) { UseStatementInjector injector = new UseStatementInjector(this); offset = injector.inject(document, getTextViewer(), offset); super.apply(document, trigger, offset); calculateCursorPosition(document, offset); } @Override public boolean isAutoInsertable() { return Platform.getPreferencesService().getBoolean(PHPCorePlugin.ID, PHPCoreConstants.CODEASSIST_AUTOINSERT, false, null); } @Override protected boolean insertCompletion() { return Platform.getPreferencesService().getBoolean(PHPCorePlugin.ID, PHPCoreConstants.CODEASSIST_INSERT_COMPLETION, true, null); } protected void calculateCursorPosition(IDocument document, int offset) { try { while (Character.isJavaIdentifierPart(document.getChar(offset)) || document.getChar(offset) == NamespaceReference.NAMESPACE_SEPARATOR) { ++offset; } if (document.getChar(offset) == '(') { boolean hasArguments = false; IModelElement modelElement = getModelElement(); if (modelElement.getElementType() == IModelElement.METHOD) { IMethod method = (IMethod) modelElement; try { String[] parameters = method.getParameterNames(); if (parameters != null && parameters.length > 0) { hasArguments = true; } } catch (ModelException e) { } } if (!hasArguments) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=459377 // Check if we have some parameters inside of parentheses, // even if they shouldn't be there. // In this case, place cursor after left parenthesis, // otherwise place cursor after right parenthesis. IRegion line = document.getLineInformationOfOffset(offset); int lineEnd = line.getOffset() + line.getLength(); int pos = offset + 1; while (pos < lineEnd) { if (Character.isWhitespace(document.getChar(pos))) { pos++; continue; } if (document.getChar(pos) == ')') { pos++; break; } pos = offset + 1; break; } setCursorPosition(pos - getReplacementOffset()); } else { setCursorPosition(offset - getReplacementOffset() + 1); } } } catch (BadLocationException e) { } } @Override public IContextInformation getContextInformation() { String displayString = getDisplayString(); // * ZSTD-335 IModelElement modelElement = getModelElement(); if (modelElement instanceof IMethod) { IMethod method = (IMethod) modelElement; IParameter[] parameters; try { parameters = method.getParameters(); if (parameters != null) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < parameters.length; i++) { IParameter parameter = parameters[i]; if (parameter.getType() != null) { if (PHPFlags.isNullable(parameter.getFlags())) { sb.append('?'); } sb.append(parameter.getType()).append(" "); //$NON-NLS-1$ } sb.append(parameter.getName()); if (parameter.getDefaultValue() != null) { sb.append("=").append(parameter.getDefaultValue()); //$NON-NLS-1$ } sb.append(", "); //$NON-NLS-1$ } String infoDisplayString = sb.toString(); if (infoDisplayString.length() > 0) { infoDisplayString = infoDisplayString.substring(0, infoDisplayString.length() - 2); return new ContextInformation(displayString, infoDisplayString); } } } catch (ModelException e) { PHPUiPlugin.log(e); } } String infoDisplayString = displayString; int i = infoDisplayString.indexOf('('); if (i != -1) { infoDisplayString = infoDisplayString.substring(i + 1); } i = infoDisplayString.indexOf(')'); if (i != -1) { infoDisplayString = infoDisplayString.substring(0, i); } if (infoDisplayString.length() == 0) { return null; } return new ContextInformation(displayString, infoDisplayString); } @Override protected boolean isCamelCaseMatching() { return true; } @Override protected ScriptTextTools getTextTools() { return PHPUiPlugin.getDefault().getTextTools(); } @Override public IInformationControlCreator getInformationControlCreator() { if (fCreator == null) { fCreator = new CompletionHoverControlCreator(new IInformationControlCreator() { @Override public IInformationControl createInformationControl(Shell parent) { if (BrowserInformationControl.isAvailable(parent)) { return new BrowserInformationControl(parent, PreferenceConstants.APPEARANCE_DOCUMENTATION_FONT, true); } else { return new DefaultInformationControl(parent, true); } } }, true); } return fCreator; } }