blob: f26277b7bb1eb612fd24189e172c8b296ed21e18 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2007 IBM Corporation and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
*******************************************************************************/
package org.eclipse.dltk.javascript.internal.ui.text.completion;
import java.util.concurrent.Callable;
import org.eclipse.dltk.core.CompletionProposal;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.internal.javascript.ti.IReferenceAttributes;
import org.eclipse.dltk.internal.javascript.ti.TypeSystemImpl;
import org.eclipse.dltk.javascript.core.JavaScriptNature;
import org.eclipse.dltk.javascript.internal.ui.JavaScriptUI;
import org.eclipse.dltk.javascript.typeinference.IValueReference;
import org.eclipse.dltk.javascript.typeinfo.IRMethod;
import org.eclipse.dltk.javascript.typeinfo.IRParameter;
import org.eclipse.dltk.javascript.typeinfo.IRType;
import org.eclipse.dltk.javascript.typeinfo.ITypeSystem;
import org.eclipse.dltk.javascript.typeinfo.RTypes;
import org.eclipse.dltk.javascript.typeinfo.TypeMode;
import org.eclipse.dltk.javascript.typeinfo.model.GenericType;
import org.eclipse.dltk.javascript.typeinfo.model.Method;
import org.eclipse.dltk.javascript.typeinfo.model.Parameter;
import org.eclipse.dltk.javascript.typeinfo.model.ParameterKind;
import org.eclipse.dltk.ui.text.completion.AbstractScriptCompletionProposal;
import org.eclipse.dltk.ui.text.completion.IScriptCompletionProposal;
import org.eclipse.dltk.ui.text.completion.LazyScriptCompletionProposal;
import org.eclipse.dltk.ui.text.completion.ProposalContextInformation;
import org.eclipse.dltk.ui.text.completion.ScriptCompletionProposal;
import org.eclipse.dltk.ui.text.completion.ScriptCompletionProposalCollector;
import org.eclipse.emf.common.util.EList;
import org.eclipse.swt.graphics.Image;
@SuppressWarnings("restriction")
public class JavaScriptCompletionProposalCollector extends
ScriptCompletionProposalCollector {
protected final static char[] VAR_TRIGGER = new char[] { '\t', ' ', '=',
';', '.' };
@Override
protected char[] getVarTrigger() {
return VAR_TRIGGER;
}
public JavaScriptCompletionProposalCollector(ISourceModule module) {
super(module);
}
/**
* Checks if the specified proposal has ProposalInfo set.
*
* @param proposal
* @return
*/
private boolean hasProposalInfo(AbstractScriptCompletionProposal proposal) {
if (proposal instanceof LazyScriptCompletionProposal) {
// lazy objects are supposed to create ProposalInfo on demand.
return true;
} else {
return proposal.getProposalInfo() != null;
}
}
@Override
protected IScriptCompletionProposal createScriptCompletionProposal(
CompletionProposal proposal) {
AbstractScriptCompletionProposal outProposal = (AbstractScriptCompletionProposal) super
.createScriptCompletionProposal(proposal);
if (outProposal != null && !hasProposalInfo(outProposal)
&& proposal.getExtraInfo() != null) {
outProposal.setProposalInfo(new JavaScriptProposalInfo(proposal
.getExtraInfo()));
}
return outProposal;
}
@Override
protected IScriptCompletionProposal createTypeProposal(
CompletionProposal typeProposal) {
if (getAttribute(TypeMode.JSDOC) != null
&& typeProposal.getExtraInfo() instanceof GenericType) {
return new GenericTypeCompletionProposal(typeProposal,
getInvocationContext());
}
return super.createTypeProposal(typeProposal);
}
@Override
protected IScriptCompletionProposal createMethodReferenceProposal(
CompletionProposal methodProposal) {
AbstractScriptCompletionProposal methodReferenceProposal = (AbstractScriptCompletionProposal) super
.createMethodReferenceProposal(methodProposal);
final Object extraInfo = methodProposal.getExtraInfo();
if (extraInfo != null) {
methodReferenceProposal.setProposalInfo(new JavaScriptProposalInfo(
extraInfo));
}
StringBuilder sb = null;
final Integer paramLimit = (Integer) methodProposal
.getAttribute(ScriptCompletionProposalCollector.ATTR_PARAM_LIMIT);
if (extraInfo instanceof Method) {
final Method method = (Method) extraInfo;
final EList<Parameter> parameters = method.getParameters();
if (parameters.size() > 0) {
sb = new StringBuilder();
int index = 0;
for (final Parameter parameter : parameters) {
if (sb.length() > 0)
sb.append(", ");
if (parameter.getKind() == ParameterKind.OPTIONAL)
sb.append('[');
if (parameter.getType() != null) {
try {
final ITypeSystem ts = getTypeSystem();
final IRType type = ITypeSystem.CURRENT.runWith(ts,
new Callable<IRType>() {
public IRType call() {
return RTypes.create(ts,
parameter.getType());
}
});
sb.append(type.getName());
} catch (Exception e) {
// shouldn't happen
JavaScriptUI.log(e);
}
if (parameter.getKind() == ParameterKind.VARARGS)
sb.append("...");
sb.append(' ');
}
sb.append(parameter.getName());
if (parameter.getKind() == ParameterKind.VARARGS
&& parameter.getType() == null)
sb.append("...");
if (parameter.getKind() == ParameterKind.OPTIONAL)
sb.append(']');
if (paramLimit != null && ++index >= paramLimit.intValue())
break;
}
}
} else if (extraInfo instanceof IValueReference) {
final IRMethod method = (IRMethod) ((IValueReference) extraInfo)
.getAttribute(IReferenceAttributes.R_METHOD);
if (method != null && method.getParameterCount() > 0) {
sb = new StringBuilder();
int index = 0;
for (IRParameter parameter : method.getParameters()) {
if (sb.length() > 0)
sb.append(", ");
if (parameter.isOptional())
sb.append('[');
if (parameter.getType() != null) {
sb.append(parameter.getType().getName());
if (parameter.isVarargs())
sb.append("...");
sb.append(' ');
}
sb.append(parameter.getName());
if (parameter.isVarargs() && parameter.getType() == null)
sb.append("...");
if (parameter.isOptional())
sb.append(']');
if (paramLimit != null && ++index >= paramLimit.intValue())
break;
}
}
}
if (sb != null) {
final ProposalContextInformation contextInformation = new JavaScriptProposalContextInformation(
methodProposal, sb.toString());
final int pos = methodProposal.getCompletion().indexOf('(');
if (pos >= 0) {
contextInformation.setContextInformationPosition(methodProposal
.getReplaceStart() + pos + 1);
methodReferenceProposal
.setContextInformation(contextInformation);
}
}
return methodReferenceProposal;
}
private ITypeSystem typeSystem;
private ITypeSystem getTypeSystem() {
if (typeSystem == null) {
typeSystem = ITypeSystem.CURRENT.get();
if (typeSystem == null) {
typeSystem = new TypeSystemImpl();
}
}
return typeSystem;
}
@Override
protected IScriptCompletionProposal createFieldProposal(
CompletionProposal proposal) {
final IScriptCompletionProposal fieldProposal = super
.createFieldProposal(proposal);
if (proposal.getExtraInfo() != null) {
((AbstractScriptCompletionProposal) fieldProposal)
.setProposalInfo(new JavaScriptProposalInfo(proposal
.getExtraInfo()));
}
return fieldProposal;
}
@Override
protected ScriptCompletionProposal createScriptCompletionProposal(
String completion, int replaceStart, int length, Image image,
String displayString, int i, boolean isInDoc) {
// PATCH JOHAN, do check for the JSDOC attribute and overwrite the
// isInDoc boolean if that is set.
if (getAttribute(TypeMode.JSDOC) instanceof Boolean)
isInDoc = ((Boolean) getAttribute(TypeMode.JSDOC)).booleanValue();
JavaScriptCompletionProposal javaScriptCompletionProposal = new JavaScriptCompletionProposal(
completion, replaceStart, length, image, displayString, i,
isInDoc);
return javaScriptCompletionProposal;
}
@Override
protected IScriptCompletionProposal createKeywordProposal(
CompletionProposal proposal) {
String completion = String.valueOf(proposal.getCompletion());
int start = proposal.getReplaceStart();
int length = getLength(proposal);
String label = getLabelProvider().createSimpleLabel(proposal);
Image img = getImage(getLabelProvider().createImageDescriptor(proposal));
int relevance = computeRelevance(proposal);
return createScriptCompletionProposal(completion, start, length, img,
label, relevance, false);
}
@Override
protected String getNatureId() {
return JavaScriptNature.NATURE_ID;
}
private static final class JavaScriptProposalContextInformation extends
ProposalContextInformation {
private final String informationDisplayString;
public JavaScriptProposalContextInformation(
CompletionProposal proposal, String informationDisplayString) {
super(proposal);
this.informationDisplayString = informationDisplayString;
}
@Override
public String getInformationDisplayString() {
return informationDisplayString;
}
}
}