blob: 4a22eda0c40365bb6ce1efd6eb1ffa814edbd489 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2011 Tasktop Technologies 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:
* Tasktop Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.internal.cdt.ui.contentassist;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTCompletionContext;
import org.eclipse.cdt.core.dom.ast.IASTCompletionNode;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionStyleMacroParameter;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorFunctionStyleMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.ICompositeType;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IEnumerator;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.c.ICFunctionScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.CoreModelUtil;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.c.ICInternalBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitMethod;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitTypedef;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
import org.eclipse.cdt.internal.ui.text.contentassist.CContentAssistInvocationContext;
import org.eclipse.cdt.internal.ui.text.contentassist.CProposalContextInformation;
import org.eclipse.cdt.internal.ui.text.contentassist.ParsingBasedProposalComputer;
import org.eclipse.cdt.internal.ui.text.contentassist.RelevanceConstants;
import org.eclipse.cdt.internal.ui.viewsupport.CElementImageProvider;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.commons.ui.CommonImages;
import org.eclipse.mylyn.internal.cdt.ui.CDTUIBridgePlugin;
import org.eclipse.swt.graphics.Image;
/**
* Searches the DOM (both the AST and the index) for completion proposals.
*
* @author Bryan Wilkinson
*/
public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer {
/**
* Default constructor is required (executable extension).
*/
public DOMCompletionProposalComputer() {
}
@Override
protected List<ICompletionProposal> computeCompletionProposals(CContentAssistInvocationContext context,
IASTCompletionNode completionNode, String prefix) {
List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();
if (inPreprocessorDirective(context)) {
if (!inPreprocessorKeyword(context)) {
// add only macros
if (prefix.length() == 0) {
try {
prefix = context.computeIdentifierPrefix().toString();
} catch (BadLocationException exc) {
CUIPlugin.log(exc);
}
}
addMacroProposals(context, prefix, proposals);
}
} else {
boolean handleMacros = false;
IASTName[] names = completionNode.getNames();
for (int i = 0; i < names.length; ++i) {
if (names[i].getTranslationUnit() == null) {
// The node isn't properly hooked up, must have backtracked out of this node
continue;
}
IASTCompletionContext astContext = names[i].getCompletionContext();
if (astContext == null) {
continue;
} else if (astContext instanceof IASTIdExpression || astContext instanceof IASTNamedTypeSpecifier) {
// handle macros only if there is a prefix
handleMacros = prefix.length() > 0;
}
IBinding[] bindings = astContext.findBindings(names[i], !context.isContextInformationStyle());
if (bindings != null) {
for (int j = 0; j < bindings.length; ++j) {
handleBinding(bindings[j], context, prefix, astContext, proposals);
}
}
}
if (handleMacros) {
addMacroProposals(context, prefix, proposals);
}
}
return proposals;
}
/**
* Test whether the invocation offset is inside or before the preprocessor directive keyword.
*
* @param context
* the invocation context
* @return <code>true</code> if the invocation offset is inside or before the directive keyword
*/
private boolean inPreprocessorKeyword(CContentAssistInvocationContext context) {
IDocument doc = context.getDocument();
int offset = context.getInvocationOffset();
try {
final ITypedRegion partition = TextUtilities.getPartition(doc, ICPartitions.C_PARTITIONING, offset, true);
if (ICPartitions.C_PREPROCESSOR.equals(partition.getType())) {
String ppPrefix = doc.get(partition.getOffset(), offset - partition.getOffset());
if (ppPrefix.matches("\\s*#\\s*\\w*")) { //$NON-NLS-1$
// we are inside the directive keyword
return true;
}
}
} catch (BadLocationException exc) {
}
return false;
}
/**
* Check if the invocation offset is inside a preprocessor directive.
*
* @param context
* the content asist invocation context
* @return <code>true</code> if invocation offset is inside a preprocessor directive
*/
private boolean inPreprocessorDirective(CContentAssistInvocationContext context) {
IDocument doc = context.getDocument();
int offset = context.getInvocationOffset();
try {
final ITypedRegion partition = TextUtilities.getPartition(doc, ICPartitions.C_PARTITIONING, offset, true);
if (ICPartitions.C_PREPROCESSOR.equals(partition.getType())) {
return true;
}
} catch (BadLocationException exc) {
}
return false;
}
private void addMacroProposals(CContentAssistInvocationContext context, String prefix,
List<ICompletionProposal> proposals) {
char[] prefixChars = prefix.toCharArray();
final boolean matchPrefix = !context.isContextInformationStyle();
IASTCompletionNode completionNode = context.getCompletionNode();
IASTPreprocessorMacroDefinition[] macros = completionNode.getTranslationUnit().getMacroDefinitions();
if (macros != null) {
for (int i = 0; i < macros.length; ++i) {
final char[] macroName = macros[i].getName().toCharArray();
if (CharArrayUtils.equals(macroName, 0, matchPrefix ? prefixChars.length : macroName.length,
prefixChars, true)) {
handleMacro(macros[i], context, prefix, proposals);
}
}
}
macros = completionNode.getTranslationUnit().getBuiltinMacroDefinitions();
if (macros != null) {
for (int i = 0; i < macros.length; ++i) {
final char[] macroName = macros[i].getName().toCharArray();
if (CharArrayUtils.equals(macroName, 0, matchPrefix ? prefixChars.length : macroName.length,
prefixChars, true)) {
handleMacro(macros[i], context, prefix, proposals);
}
}
}
}
private void handleMacro(IASTPreprocessorMacroDefinition macro, CContentAssistInvocationContext context,
String prefix, List<ICompletionProposal> proposals) {
//CElementHandleFactory.create;
final String macroName = macro.getName().toString();
final int baseRelevance = computeBaseRelevance(prefix, macroName);
Image image = getImage(CElementImageProvider.getMacroImageDescriptor());
if (macro instanceof IASTPreprocessorFunctionStyleMacroDefinition) {
IASTPreprocessorFunctionStyleMacroDefinition functionMacro = (IASTPreprocessorFunctionStyleMacroDefinition) macro;
StringBuilder repStringBuff = new StringBuilder();
repStringBuff.append(macroName);
repStringBuff.append('(');
StringBuilder args = new StringBuilder();
IASTFunctionStyleMacroParameter[] params = functionMacro.getParameters();
if (params != null) {
for (int i = 0; i < params.length; ++i) {
if (i > 0) {
args.append(", "); //$NON-NLS-1$
}
args.append(params[i].getParameter());
}
}
String argString = args.toString();
StringBuilder descStringBuff = new StringBuilder(repStringBuff.toString());
descStringBuff.append(argString);
descStringBuff.append(')');
repStringBuff.append(')');
String repString = repStringBuff.toString();
String descString = descStringBuff.toString();
CCompletionProposal proposal = createProposal(repString, descString, prefix.length(), image, baseRelevance
+ RelevanceConstants.MACRO_TYPE_RELEVANCE, context, getCElement(macro), macro.getName().toString());
if (!context.isContextInformationStyle()) {
proposal.setCursorPosition(repString.length() - 1);
}
if (argString.length() > 0) {
CProposalContextInformation info = new CProposalContextInformation(image, descString, argString);
info.setContextInformationPosition(context.getContextInformationOffset());
proposal.setContextInformation(info);
}
proposals.add(proposal);
} else {
proposals.add(createProposal(macroName, macroName, prefix.length(), image, baseRelevance
+ RelevanceConstants.MACRO_TYPE_RELEVANCE, context, getCElement(macro), macro.getName().toString()));
}
}
@SuppressWarnings("restriction")
protected void handleBinding(IBinding binding, CContentAssistInvocationContext cContext, String prefix,
IASTCompletionContext astContext, List<ICompletionProposal> proposals) {
if ((binding instanceof CPPImplicitFunction || binding instanceof CPPImplicitTypedef)
&& !(binding instanceof CPPImplicitMethod)) {
return;
}
if (!isAnonymousBinding(binding)) {
final String name = binding.getName();
final int baseRelevance = computeBaseRelevance(prefix, name);
if (binding instanceof ICPPClassType) {
handleClass((ICPPClassType) binding, astContext, cContext, baseRelevance, proposals);
} else if (binding instanceof IFunction) {
handleFunction((IFunction) binding, cContext, baseRelevance, proposals);
} else if (!cContext.isContextInformationStyle()) {
if (binding instanceof IVariable) {
handleVariable((IVariable) binding, cContext, baseRelevance, proposals);
} else if (binding instanceof ITypedef) {
proposals.add(createProposal(name, name, getImage(binding), baseRelevance
+ RelevanceConstants.TYPEDEF_TYPE_RELEVANCE, cContext, getCElement(binding),
binding.getName()));
} else if (binding instanceof ICPPNamespace) {
handleNamespace((ICPPNamespace) binding, astContext, cContext, baseRelevance, proposals);
} else if (binding instanceof IEnumeration) {
proposals.add(createProposal(name, name, getImage(binding), baseRelevance
+ RelevanceConstants.ENUMERATION_TYPE_RELEVANCE, cContext, getCElement(binding),
binding.getName()));
} else if (binding instanceof IEnumerator) {
proposals.add(createProposal(name, name, getImage(binding), baseRelevance
+ RelevanceConstants.ENUMERATOR_TYPE_RELEVANCE, cContext, getCElement(binding),
binding.getName()));
} else {
proposals.add(createProposal(name, name, getImage(binding), baseRelevance
+ RelevanceConstants.DEFAULT_TYPE_RELEVANCE, cContext, getCElement(binding),
binding.getName()));
}
}
}
}
private boolean isAnonymousBinding(IBinding binding) {
char[] name = binding.getNameCharArray();
return name.length == 0 || name[0] == '{';
}
private void handleClass(ICPPClassType classType, IASTCompletionContext astContext,
CContentAssistInvocationContext context, int baseRelevance, List<ICompletionProposal> proposals) {
if (context.isContextInformationStyle()) {
try {
ICPPConstructor[] constructors = classType.getConstructors();
for (ICPPConstructor constructor : constructors) {
handleFunction(constructor, context, baseRelevance, proposals);
}
} catch (Exception e) {
handle(e);
}
} else {
int relevance = 0;
try {
switch (classType.getKey()) {
case ICPPClassType.k_class:
relevance = RelevanceConstants.CLASS_TYPE_RELEVANCE;
break;
case ICompositeType.k_struct:
relevance = RelevanceConstants.STRUCT_TYPE_RELEVANCE;
break;
case ICompositeType.k_union:
relevance = RelevanceConstants.UNION_TYPE_RELEVANCE;
break;
}
} catch (Exception e) {
handle(e);
}
if (astContext instanceof IASTName && !(astContext instanceof ICPPASTQualifiedName)) {
IASTName name = (IASTName) astContext;
if (name.getParent() instanceof IASTDeclarator) {
proposals.add(createProposal(
classType.getName() + "::", classType.getName(), getImage(classType), baseRelevance + relevance, context, getCElement(classType), classType.getName())); //$NON-NLS-1$
}
}
proposals.add(createProposal(classType.getName(), classType.getName(), getImage(classType), baseRelevance
+ RelevanceConstants.CLASS_TYPE_RELEVANCE, context, getCElement(classType), classType.getName()));
}
}
private void handle(Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
}
private void handleFunction(IFunction function, CContentAssistInvocationContext context, int baseRelevance,
List<ICompletionProposal> proposals) {
Image image = getImage(function);
StringBuilder repStringBuff = new StringBuilder();
repStringBuff.append(function.getName());
repStringBuff.append('(');
StringBuilder dispargs = new StringBuilder(); // for the displayString
StringBuilder idargs = new StringBuilder(); // for the idString
String returnTypeStr = null;
try {
IParameter[] params = function.getParameters();
if (params != null) {
for (int i = 0; i < params.length; ++i) {
IType paramType = params[i].getType();
if (i > 0) {
dispargs.append(',');
idargs.append(',');
}
dispargs.append(ASTTypeUtil.getType(paramType, false));
idargs.append(ASTTypeUtil.getType(paramType, false));
String paramName = params[i].getName();
if (paramName != null && paramName.length() > 0) {
dispargs.append(' ');
dispargs.append(paramName);
}
}
if (function.takesVarArgs()) {
if (params.length > 0) {
dispargs.append(',');
idargs.append(',');
}
dispargs.append("..."); //$NON-NLS-1$
idargs.append("..."); //$NON-NLS-1$
} else if (params.length == 0) { // force the void in
dispargs.append("void"); //$NON-NLS-1$
idargs.append("void"); //$NON-NLS-1$
}
}
IFunctionType functionType = function.getType();
if (functionType != null) {
IType returnType = functionType.getReturnType();
if (returnType != null) {
returnTypeStr = ASTTypeUtil.getType(returnType, false);
}
}
} catch (Exception e) {
}
String dispargString = dispargs.toString();
String idargString = idargs.toString();
StringBuilder dispStringBuff = new StringBuilder(repStringBuff.toString());
dispStringBuff.append(dispargString);
dispStringBuff.append(')');
if (returnTypeStr != null && returnTypeStr.length() > 0) {
dispStringBuff.append(" : "); //$NON-NLS-1$
dispStringBuff.append(returnTypeStr);
}
String dispString = dispStringBuff.toString();
StringBuilder idStringBuff = new StringBuilder(repStringBuff.toString());
idStringBuff.append(idargString);
idStringBuff.append(')');
String idString = idStringBuff.toString();
repStringBuff.append(')');
String repString = repStringBuff.toString();
final int relevance = function instanceof ICPPMethod
? RelevanceConstants.METHOD_TYPE_RELEVANCE
: RelevanceConstants.FUNCTION_TYPE_RELEVANCE;
CCompletionProposal proposal = createProposal(repString, dispString, idString, context.getCompletionNode()
.getLength(), image, baseRelevance + relevance, context, getCElement(function), function.getName());
if (!context.isContextInformationStyle()) {
proposal.setCursorPosition(repString.length() - 1);
}
if (dispargString.length() > 0) {
CProposalContextInformation info = new CProposalContextInformation(image, dispString, dispargString);
info.setContextInformationPosition(context.getContextInformationOffset());
proposal.setContextInformation(info);
}
proposals.add(proposal);
}
private void handleVariable(IVariable variable, CContentAssistInvocationContext context, int baseRelevance,
List<ICompletionProposal> proposals) {
StringBuilder repStringBuff = new StringBuilder();
repStringBuff.append(variable.getName());
String returnTypeStr = "<unknown>"; //$NON-NLS-1$
try {
IType varType = variable.getType();
if (varType != null) {
returnTypeStr = ASTTypeUtil.getType(varType, false);
}
} catch (Exception e) {
}
StringBuilder dispStringBuff = new StringBuilder(repStringBuff.toString());
if (returnTypeStr != null) {
dispStringBuff.append(" : "); //$NON-NLS-1$
dispStringBuff.append(returnTypeStr);
}
String dispString = dispStringBuff.toString();
StringBuilder idStringBuff = new StringBuilder(repStringBuff.toString());
String idString = idStringBuff.toString();
String repString = repStringBuff.toString();
Image image = getImage(variable);
final int relevance = isLocalVariable(variable)
? RelevanceConstants.LOCAL_VARIABLE_TYPE_RELEVANCE
: isField(variable)
? RelevanceConstants.FIELD_TYPE_RELEVANCE
: RelevanceConstants.VARIABLE_TYPE_RELEVANCE;
CCompletionProposal proposal = createProposal(repString, dispString, idString, context.getCompletionNode()
.getLength(), image, baseRelevance + relevance, context, getCElement(variable), variable.getName());
proposals.add(proposal);
}
private static boolean isField(IVariable variable) {
return variable instanceof IField;
}
private static boolean isLocalVariable(IVariable variable) {
try {
return isLocalScope(variable.getScope());
} catch (DOMException exc) {
return false;
}
}
private static boolean isLocalScope(IScope scope) {
while (scope != null) {
if (scope instanceof ICPPFunctionScope || scope instanceof ICPPBlockScope
|| scope instanceof ICFunctionScope) {
return true;
}
try {
scope = scope.getParent();
} catch (DOMException e) {
scope = null;
}
}
return false;
}
private void handleNamespace(ICPPNamespace namespace, IASTCompletionContext astContext,
CContentAssistInvocationContext cContext, int baseRelevance, List<ICompletionProposal> proposals) {
if (astContext instanceof ICPPASTQualifiedName) {
IASTCompletionContext parent = ((ICPPASTQualifiedName) astContext).getCompletionContext();
handleNamespace(namespace, parent, cContext, baseRelevance, proposals);
return;
}
StringBuilder repStringBuff = new StringBuilder();
repStringBuff.append(namespace.getName());
if (!(astContext instanceof ICPPASTUsingDeclaration) && !(astContext instanceof ICPPASTUsingDirective)) {
repStringBuff.append("::"); //$NON-NLS-1$
}
String repString = repStringBuff.toString();
proposals.add(createProposal(repString, namespace.getName(), getImage(namespace), baseRelevance
+ RelevanceConstants.NAMESPACE_TYPE_RELEVANCE, cContext, getCElement(namespace), namespace.getName()));
}
private ICElement getCElement(ICPPNamespace namespace) {
// ignore
return null;
}
private ICElement getCElement(IVariable variable) {
return null;
}
private ICElement getCElement(IFunction function) {
return null;
}
private ICElement getCElement(ICPPClassType classType) {
return null;
}
private ICElement getCElement(IASTPreprocessorMacroDefinition macro) {
if (macro != null && macro.getFileLocation() != null) {
try {
return getCElement(macro.getFileLocation().getFileName(), macro.getFileLocation().getNodeOffset());
} catch (Exception e) {
StatusHandler.log(new Status(IStatus.ERROR, CDTUIBridgePlugin.ID_PLUGIN,
"Unable to get CElement for Macro", e)); //$NON-NLS-1$
}
}
return null;
}
@SuppressWarnings("restriction")
private ICElement getCElement(IBinding binding) {
IASTNode definition = null;
if (binding instanceof ICInternalBinding) {
IASTNode[] declarations = ((ICInternalBinding) binding).getDeclarations();
if (declarations != null && declarations.length > 0) {
definition = declarations[0];
}
} else if (binding instanceof ICPPInternalBinding) {
IASTNode[] declarations = ((ICPPInternalBinding) binding).getDeclarations();
if (declarations != null && declarations.length > 0) {
definition = declarations[0];
}
}
if (definition != null && definition.getFileLocation() != null) {
try {
return getCElement(definition.getFileLocation().getFileName(), definition.getFileLocation()
.getNodeOffset());
} catch (CModelException e) {
StatusHandler.log(new Status(IStatus.ERROR, CDTUIBridgePlugin.ID_PLUGIN,
"Unable to get CElement for Binding", e)); //$NON-NLS-1$
}
}
return null;
}
private ICElement getCElement(String filename, int offset) throws CModelException {
IFile res = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(filename));
ITranslationUnit cu = null;
if (res instanceof IFile) {
IFile file = res;
if (CoreModel.isValidTranslationUnitName(null, file.getName())) {
cu = CoreModelUtil.findTranslationUnit(file);
} else {
return null;
}
}
if (cu != null) {
ICElement ce = cu.getElementAtOffset(offset);
return ce;
} else {
return null;
}
}
private CCompletionProposal createProposal(String repString, String dispString, Image image, int relevance,
CContentAssistInvocationContext context, ICElement element, String bindingName) {
return createProposal(repString, dispString, null, context.getCompletionNode().getLength(), image, relevance,
context, element, bindingName);
}
private CCompletionProposal createProposal(String repString, String dispString, int prefixLength, Image image,
int relevance, CContentAssistInvocationContext context, ICElement element, String bindingName) {
return createProposal(repString, dispString, null, prefixLength, image, relevance, context, element,
bindingName);
}
private CCompletionProposal createProposal(String repString, String dispString, String idString, int prefixLength,
Image image, int relevance, CContentAssistInvocationContext context, ICElement element, String bindingName) {
int parseOffset = context.getParseOffset();
int invocationOffset = context.getInvocationOffset();
boolean doReplacement = !context.isContextInformationStyle();
int repLength = doReplacement ? prefixLength : 0;
int repOffset = doReplacement ? parseOffset - repLength : invocationOffset;
repString = doReplacement ? repString : ""; //$NON-NLS-1$
return new CCompletionProposal(repString, repOffset, repLength, image, dispString, idString, relevance,
context.getViewer(), element, bindingName);
}
private Image getImage(ImageDescriptor desc) {
return desc != null ? CommonImages.getImage(desc) : null;
}
private Image getImage(IBinding binding) {
ImageDescriptor imageDescriptor = null;
try {
if (binding instanceof ITypedef) {
imageDescriptor = CElementImageProvider.getTypedefImageDescriptor();
} else if (binding instanceof ICompositeType) {
if (((ICompositeType) binding).getKey() == ICPPClassType.k_class
|| binding instanceof ICPPClassTemplate) {
imageDescriptor = CElementImageProvider.getClassImageDescriptor();
} else if (((ICompositeType) binding).getKey() == ICompositeType.k_struct) {
imageDescriptor = CElementImageProvider.getStructImageDescriptor();
} else if (((ICompositeType) binding).getKey() == ICompositeType.k_union) {
imageDescriptor = CElementImageProvider.getUnionImageDescriptor();
}
} else if (binding instanceof ICPPMethod) {
switch (((ICPPMethod) binding).getVisibility()) {
case ICPPMember.v_private:
imageDescriptor = CElementImageProvider.getMethodImageDescriptor(ASTAccessVisibility.PRIVATE);
break;
case ICPPMember.v_protected:
imageDescriptor = CElementImageProvider.getMethodImageDescriptor(ASTAccessVisibility.PROTECTED);
break;
default:
imageDescriptor = CElementImageProvider.getMethodImageDescriptor(ASTAccessVisibility.PUBLIC);
break;
}
} else if (binding instanceof IFunction) {
imageDescriptor = CElementImageProvider.getFunctionImageDescriptor();
} else if (binding instanceof ICPPField) {
switch (((ICPPField) binding).getVisibility()) {
case ICPPMember.v_private:
imageDescriptor = CElementImageProvider.getFieldImageDescriptor(ASTAccessVisibility.PRIVATE);
break;
case ICPPMember.v_protected:
imageDescriptor = CElementImageProvider.getFieldImageDescriptor(ASTAccessVisibility.PROTECTED);
break;
default:
imageDescriptor = CElementImageProvider.getFieldImageDescriptor(ASTAccessVisibility.PUBLIC);
break;
}
} else if (binding instanceof IField) {
imageDescriptor = CElementImageProvider.getFieldImageDescriptor(ASTAccessVisibility.PUBLIC);
} else if (binding instanceof IVariable) {
imageDescriptor = CElementImageProvider.getVariableImageDescriptor();
} else if (binding instanceof IEnumeration) {
imageDescriptor = CElementImageProvider.getEnumerationImageDescriptor();
} else if (binding instanceof IEnumerator) {
imageDescriptor = CElementImageProvider.getEnumeratorImageDescriptor();
} else if (binding instanceof ICPPNamespace) {
imageDescriptor = CElementImageProvider.getNamespaceImageDescriptor();
} else if (binding instanceof ICPPFunctionTemplate) {
imageDescriptor = CElementImageProvider.getFunctionImageDescriptor();
} else if (binding instanceof ICPPUsingDeclaration) {
IBinding[] delegates = ((ICPPUsingDeclaration) binding).getDelegates();
if (delegates.length > 0) {
return getImage(delegates[0]);
}
}
} catch (Exception e) {
handle(e);
}
return imageDescriptor != null ? CommonImages.getImage(imageDescriptor) : null;
}
}