mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 17:05:26 +02:00
Bug 278337.
This commit is contained in:
parent
aecdc9e38c
commit
75560d52b8
9 changed files with 240 additions and 141 deletions
|
@ -47,8 +47,19 @@ public interface IProblemBinding extends IBinding, IScope, IType {
|
|||
* returns the line number for this problem if known
|
||||
*/
|
||||
public int getLineNumber();
|
||||
|
||||
/*
|
||||
|
||||
/**
|
||||
* Returns bindings that were considered when resolving the node corresponding
|
||||
* to this problem binding, but rejected for some reason.
|
||||
* @return an array of candidate bindings.
|
||||
*
|
||||
* This method is experimental. Clients calling this method should expect
|
||||
* possible changes.
|
||||
* @since 5.1 experimental
|
||||
*/
|
||||
public IBinding[] getCandidateBindings();
|
||||
|
||||
/*
|
||||
* Parser Semantic Problems
|
||||
* All Semantic problems take a char[] as an argument
|
||||
*/
|
||||
|
|
|
@ -40,16 +40,26 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I
|
|||
protected final int id;
|
||||
protected char[] arg;
|
||||
protected IASTNode node;
|
||||
private String message = null;
|
||||
private final String message = null;
|
||||
private final IBinding[] candidateBindings;
|
||||
|
||||
public ProblemBinding(IASTName name, int id) {
|
||||
this(name, id, null);
|
||||
this(name, id, null, null);
|
||||
}
|
||||
|
||||
|
||||
public ProblemBinding(IASTName name, int id, IBinding[] candidateBindings) {
|
||||
this(name, id, null, candidateBindings);
|
||||
}
|
||||
|
||||
public ProblemBinding(IASTNode node, int id, char[] arg) {
|
||||
this(node, id, arg, null);
|
||||
}
|
||||
|
||||
public ProblemBinding(IASTNode node, int id, char[] arg, IBinding[] candidateBindings) {
|
||||
this.id = id;
|
||||
this.arg = arg;
|
||||
this.node = node;
|
||||
this.candidateBindings = candidateBindings;
|
||||
}
|
||||
|
||||
public EScopeKind getKind() {
|
||||
|
@ -59,7 +69,11 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I
|
|||
public IASTNode getASTNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
public IBinding[] getCandidateBindings() {
|
||||
return candidateBindings != null ? candidateBindings : IBinding.EMPTY_BINDING_ARRAY;
|
||||
}
|
||||
|
||||
protected static final String[] errorMessages;
|
||||
static {
|
||||
errorMessages = new String[IProblemBinding.SEMANTIC_INVALID_TEMPLATE_ARGUMENTS];
|
||||
|
@ -134,6 +148,7 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I
|
|||
return getASTNode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
// Don't clone problems
|
||||
|
|
|
@ -837,9 +837,10 @@ public class CVisitor extends ASTQueries {
|
|||
} else if (node instanceof IASTIdExpression) {
|
||||
IScope scope = getContainingScope(node);
|
||||
try {
|
||||
IBinding binding = lookup(scope, ((IASTIdExpression)node).getName());
|
||||
IBinding binding = lookup(scope, ((IASTIdExpression) node).getName());
|
||||
if (binding instanceof IType && !(binding instanceof IProblemBinding) ) {
|
||||
return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, binding.getNameCharArray());
|
||||
return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE,
|
||||
binding.getNameCharArray(), new IBinding[] { binding });
|
||||
}
|
||||
return binding;
|
||||
} catch (DOMException e) {
|
||||
|
@ -848,20 +849,21 @@ public class CVisitor extends ASTQueries {
|
|||
} else if (node instanceof ICASTTypedefNameSpecifier) {
|
||||
IScope scope = getContainingScope(node);
|
||||
try {
|
||||
IASTName name= ((ICASTTypedefNameSpecifier)node).getName();
|
||||
IASTName name= ((ICASTTypedefNameSpecifier) node).getName();
|
||||
IBinding binding = lookup(scope, name);
|
||||
if (binding == null)
|
||||
return new ProblemBinding(node, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, name.toCharArray());
|
||||
if (binding instanceof IType)
|
||||
return binding;
|
||||
return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, binding.getNameCharArray());
|
||||
return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, binding.getNameCharArray(),
|
||||
new IBinding[] { binding });
|
||||
} catch (DOMException e) {
|
||||
return null;
|
||||
}
|
||||
} else if (node instanceof ICASTElaboratedTypeSpecifier) {
|
||||
IScope scope = getContainingScope(node);
|
||||
try {
|
||||
return lookup(scope, ((ICASTElaboratedTypeSpecifier)node).getName());
|
||||
return lookup(scope, ((ICASTElaboratedTypeSpecifier) node).getName());
|
||||
} catch (DOMException e) {
|
||||
return null;
|
||||
}
|
||||
|
@ -885,10 +887,12 @@ public class CVisitor extends ASTQueries {
|
|||
}
|
||||
if (name != null) {
|
||||
IBinding binding = name.resolveBinding();
|
||||
if (binding instanceof IType)
|
||||
if (binding instanceof IType) {
|
||||
return binding;
|
||||
else if (binding != null)
|
||||
return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, binding.getNameCharArray());
|
||||
} else if (binding != null) {
|
||||
return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE,
|
||||
binding.getNameCharArray(), new IBinding[] { binding });
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} else if (node instanceof ICASTFieldDesignator) {
|
||||
|
|
|
@ -201,7 +201,8 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
|
|||
if (owner instanceof ICPPClassType) {
|
||||
return (ICPPClassType) owner;
|
||||
}
|
||||
return new ProblemBinding(this, IProblemBinding.SEMANTIC_BAD_SCOPE, binding.getName().toCharArray());
|
||||
return new ProblemBinding(this, IProblemBinding.SEMANTIC_BAD_SCOPE,
|
||||
binding.getName().toCharArray());
|
||||
} else if (binding instanceof IFunction) {
|
||||
t = ((IFunction) binding).getType();
|
||||
} else if (binding instanceof IVariable) {
|
||||
|
|
|
@ -329,7 +329,8 @@ public class CPPSemantics {
|
|||
node= node.getParent();
|
||||
}
|
||||
if (!ok) {
|
||||
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE);
|
||||
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -414,11 +415,13 @@ public class CPPSemantics {
|
|||
if (parent instanceof IASTTypeId && parent.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT) {
|
||||
if (!(binding instanceof IType)) {
|
||||
// a type id needs to hold a type
|
||||
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE);
|
||||
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
// don't create a problem here
|
||||
} else {
|
||||
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE);
|
||||
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
}
|
||||
} else if (namePropertyInParent == IASTIdExpression.ID_NAME) {
|
||||
|
@ -430,7 +433,8 @@ public class CPPSemantics {
|
|||
(binding instanceof ICPPUnknownType || binding instanceof ITypedef || binding instanceof IEnumeration)) {
|
||||
// constructor or simple-type constructor
|
||||
} else {
|
||||
binding= new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE);
|
||||
binding= new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -449,10 +453,13 @@ public class CPPSemantics {
|
|||
}
|
||||
// If we're still null...
|
||||
if (binding == null) {
|
||||
if (name instanceof ICPPASTQualifiedName && data.forFunctionDeclaration())
|
||||
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND);
|
||||
else
|
||||
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND);
|
||||
if (name instanceof ICPPASTQualifiedName && data.forFunctionDeclaration()) {
|
||||
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND,
|
||||
data.getFoundBindings());
|
||||
} else {
|
||||
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
}
|
||||
return binding;
|
||||
}
|
||||
|
@ -1060,7 +1067,8 @@ public class CPPSemantics {
|
|||
Object temp = lookupInParents(data, classScope, overallScope, fileSet);
|
||||
if (!isEmpty) {
|
||||
inherited = mergePrefixResults(null, inCurrentScope, true);
|
||||
inherited = mergePrefixResults((CharArrayObjectMap)inherited, (CharArrayObjectMap)temp, true);
|
||||
inherited = mergePrefixResults((CharArrayObjectMap) inherited,
|
||||
(CharArrayObjectMap) temp, true);
|
||||
} else {
|
||||
inherited= temp;
|
||||
}
|
||||
|
@ -1071,7 +1079,8 @@ public class CPPSemantics {
|
|||
visitVirtualBaseClasses(data, cls);
|
||||
}
|
||||
} else {
|
||||
data.problem = new ProblemBinding(null, IProblemBinding.SEMANTIC_CIRCULAR_INHERITANCE, cls.getNameCharArray());
|
||||
data.problem = new ProblemBinding(null, IProblemBinding.SEMANTIC_CIRCULAR_INHERITANCE,
|
||||
cls.getNameCharArray(), data.getFoundBindings());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1085,14 +1094,14 @@ public class CPPSemantics {
|
|||
for (int j = 0; j < r.length && r[j] != null; j++) {
|
||||
if (checkForAmbiguity(data, r[j], inherited)) {
|
||||
data.problem = new ProblemBinding(data.astName,
|
||||
IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (checkForAmbiguity(data, result, inherited)) {
|
||||
data.problem = new ProblemBinding(data.astName,
|
||||
IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1852,7 +1861,8 @@ public class CPPSemantics {
|
|||
type= temp;
|
||||
}
|
||||
} else {
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1866,7 +1876,8 @@ public class CPPSemantics {
|
|||
if (c < 0) {
|
||||
obj= temp;
|
||||
} else if (c == 0) {
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1874,8 +1885,11 @@ public class CPPSemantics {
|
|||
if (data.forUsingDeclaration()) {
|
||||
IBinding[] bindings = null;
|
||||
if (obj != null) {
|
||||
if (fns.size() > 0) return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
// if (type == null) return obj;
|
||||
if (fns.size() > 0) {
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
// if (type == null) return obj;
|
||||
bindings = (IBinding[]) ArrayUtil.append(IBinding.class, bindings, obj);
|
||||
bindings = (IBinding[]) ArrayUtil.append(IBinding.class, bindings, type);
|
||||
} else {
|
||||
|
@ -1898,8 +1912,10 @@ public class CPPSemantics {
|
|||
|
||||
int numFns = fns.size();
|
||||
if (numFns > 0) {
|
||||
if (obj != null)
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
if (obj != null) {
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
return resolveFunction(data, fns.keyArray(IFunction.class), true);
|
||||
}
|
||||
|
||||
|
@ -2169,13 +2185,15 @@ public class CPPSemantics {
|
|||
return null;
|
||||
|
||||
if (ambiguous || bestFnCost.hasAmbiguousUserDefinedConversion()) {
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
|
||||
return bestFnCost.getFunction();
|
||||
}
|
||||
|
||||
private static FunctionCost costForFunctionCall(IFunction fn, IType[] argTypes, IASTExpression[] args, boolean allowUDC, LookupData data) throws DOMException {
|
||||
private static FunctionCost costForFunctionCall(IFunction fn, IType[] argTypes, IASTExpression[] args,
|
||||
boolean allowUDC, LookupData data) throws DOMException {
|
||||
final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType();
|
||||
if (ftype == null)
|
||||
return null;
|
||||
|
@ -2270,7 +2288,7 @@ public class CPPSemantics {
|
|||
ICPPASTConversionName astName= (ICPPASTConversionName) data.astName;
|
||||
IType t= CPPVisitor.createType(astName.getTypeId());
|
||||
if (t == null) {
|
||||
return new ProblemBinding(astName, IProblemBinding.SEMANTIC_INVALID_TYPE);
|
||||
return new ProblemBinding(astName, IProblemBinding.SEMANTIC_INVALID_TYPE, data.getFoundBindings());
|
||||
}
|
||||
if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) {
|
||||
CPPTemplates.instantiateConversionTemplates(fns, t);
|
||||
|
@ -2293,7 +2311,7 @@ public class CPPSemantics {
|
|||
}
|
||||
if (unknown != null)
|
||||
return unknown;
|
||||
return new ProblemBinding(astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND);
|
||||
return new ProblemBinding(astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, data.getFoundBindings());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2337,8 +2355,10 @@ public class CPPSemantics {
|
|||
|
||||
while (type != null) {
|
||||
type = getUltimateType(type, false);
|
||||
if (type == null || !(type instanceof IFunctionType))
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
if (type == null || !(type instanceof IFunctionType)) {
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
|
||||
for (IBinding fn2 : fns) {
|
||||
IFunction fn = (IFunction) fn2;
|
||||
|
@ -2356,13 +2376,9 @@ public class CPPSemantics {
|
|||
if (c < 0) {
|
||||
result= fn;
|
||||
} else if (c == 0) {
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
}
|
||||
// boolean fromIndex= isFromIndex(fn);
|
||||
// if (isFromIndex(result) == fromIndex)
|
||||
// return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
// if (!fromIndex)
|
||||
// result= fn;
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2374,7 +2390,8 @@ public class CPPSemantics {
|
|||
}
|
||||
}
|
||||
|
||||
return result != null ? result : new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
return result != null ? result :
|
||||
new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings());
|
||||
}
|
||||
|
||||
private static Object getTargetType(LookupData data) {
|
||||
|
|
|
@ -631,8 +631,8 @@ public class CPPVisitor extends ASTQueries {
|
|||
ASTInternal.addDeclaration(binding, name);
|
||||
return binding;
|
||||
}
|
||||
} catch (DOMException e1) {
|
||||
return e1.getProblem();
|
||||
} catch (DOMException e) {
|
||||
return e.getProblem();
|
||||
}
|
||||
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION);
|
||||
}
|
||||
|
@ -654,7 +654,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
} else {
|
||||
IASTNode def = internal.getDefinition();
|
||||
if (def instanceof IASTDeclarator)
|
||||
def = ((IASTDeclarator)def).getName();
|
||||
def = ((IASTDeclarator) def).getName();
|
||||
if (def != name) {
|
||||
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDEFINITION);
|
||||
}
|
||||
|
|
|
@ -18,30 +18,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
|
||||
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.IASTParameterDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.*;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
|
||||
|
@ -66,6 +43,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.core.parser.util.ObjectSet;
|
||||
|
@ -641,4 +619,23 @@ public class LookupData {
|
|||
public boolean hasArgumentTypes() {
|
||||
return functionArgTypes != null || functionArgs != null;
|
||||
}
|
||||
|
||||
public IBinding[] getFoundBindings() {
|
||||
if (foundItems instanceof Object[]) {
|
||||
Object[] items = (Object[]) foundItems;
|
||||
if (items.length != 0) {
|
||||
IBinding[] bindings = new IBinding[items.length];
|
||||
int k = 0;
|
||||
for (Object item : items) {
|
||||
if (item instanceof IBinding) {
|
||||
bindings[k++] = (IBinding) item;
|
||||
}
|
||||
}
|
||||
if (k != 0) {
|
||||
return ArrayUtil.trimAt(IBinding.class, bindings, k - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return IBinding.EMPTY_BINDING_ARRAY;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,9 +66,11 @@ import org.eclipse.cdt.internal.ui.editor.ASTProvider;
|
|||
import org.eclipse.cdt.internal.ui.search.actions.OpenDeclarationsAction;
|
||||
|
||||
/**
|
||||
* It is required to test the selection performance independent of the indexer to make sure that the DOM is functioning properly.
|
||||
* It is required to test the selection performance independent of the indexer to make sure that the DOM
|
||||
* is functioning properly.
|
||||
*
|
||||
* Indexer bugs can drastically influence the correctness of these tests so the indexer has to be off when performing them.
|
||||
* Indexer bugs can drastically influence the correctness of these tests so the indexer has to be off when
|
||||
* performing them.
|
||||
*
|
||||
* @author dsteffle
|
||||
*/
|
||||
|
@ -101,7 +103,7 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase {
|
|||
File indexFile = new File(pathLoc.append(INDEX_FILE_ID + ".index").toOSString()); //$NON-NLS-1$
|
||||
if (indexFile.exists())
|
||||
indexFile.delete();
|
||||
} catch ( CoreException e ) {
|
||||
} catch (CoreException e) {
|
||||
/*boo*/
|
||||
}
|
||||
if (project == null)
|
||||
|
@ -124,17 +126,17 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase {
|
|||
|
||||
public static Test suite() {
|
||||
TestSuite suite= suite(CPPSelectionTestsNoIndexer.class, "_");
|
||||
suite.addTest( new CPPSelectionTestsNoIndexer("cleanupProject") ); //$NON-NLS-1$
|
||||
suite.addTest(new CPPSelectionTestsNoIndexer("cleanupProject")); //$NON-NLS-1$
|
||||
return suite;
|
||||
}
|
||||
|
||||
public void cleanupProject() throws Exception {
|
||||
closeAllEditors();
|
||||
try{
|
||||
project.delete( true, false, monitor );
|
||||
} catch( CoreException e ){
|
||||
try {
|
||||
project.delete(true, false, monitor);
|
||||
} catch (CoreException e) {
|
||||
try {
|
||||
project.delete( true, false, monitor );
|
||||
project.delete(true, false, monitor);
|
||||
}
|
||||
catch (CoreException e1) {}
|
||||
} finally {
|
||||
|
@ -151,35 +153,35 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase {
|
|||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if( project == null || !project.exists() )
|
||||
if (project == null || !project.exists())
|
||||
return;
|
||||
|
||||
closeAllEditors();
|
||||
|
||||
IResource [] members = project.members();
|
||||
IResource[] members = project.members();
|
||||
for (IResource member : members) {
|
||||
if( member.getName().equals( ".project" ) || member.getName().equals( ".cproject" ) ) //$NON-NLS-1$ //$NON-NLS-2$
|
||||
if (member.getName().equals(".project") || member.getName().equals(".cproject")) //$NON-NLS-1$ //$NON-NLS-2$
|
||||
continue;
|
||||
if (member.getName().equals(".settings"))
|
||||
continue;
|
||||
try{
|
||||
member.delete( false, monitor );
|
||||
} catch( Throwable e ){
|
||||
try {
|
||||
member.delete(false, monitor);
|
||||
} catch (Throwable e) {
|
||||
/*boo*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected IFile importFile(String fileName, String contents ) throws Exception{
|
||||
protected IFile importFile(String fileName, String contents) throws Exception{
|
||||
//Obtain file handle
|
||||
IFile file = project.getProject().getFile(fileName);
|
||||
|
||||
InputStream stream = new ByteArrayInputStream( contents.getBytes() );
|
||||
InputStream stream = new ByteArrayInputStream(contents.getBytes());
|
||||
//Create file input stream
|
||||
if( file.exists() )
|
||||
file.setContents( stream, false, false, monitor );
|
||||
if (file.exists())
|
||||
file.setContents(stream, false, false, monitor);
|
||||
else
|
||||
file.create( stream, false, monitor );
|
||||
file.create(stream, false, monitor);
|
||||
|
||||
fileManager.addFile(file);
|
||||
|
||||
|
@ -199,19 +201,19 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase {
|
|||
|
||||
file.createLink(location, IResource.ALLOW_MISSING_LOCAL, null);
|
||||
|
||||
InputStream stream = new ByteArrayInputStream( contents.getBytes() );
|
||||
InputStream stream = new ByteArrayInputStream(contents.getBytes());
|
||||
//Create file input stream
|
||||
if( file.exists() )
|
||||
file.setContents( stream, false, false, monitor );
|
||||
if (file.exists())
|
||||
file.setContents(stream, false, false, monitor);
|
||||
else
|
||||
file.create( stream, false, monitor );
|
||||
file.create(stream, false, monitor);
|
||||
|
||||
fileManager.addFile(file);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
protected IFile importFileInsideLinkedFolder(String fileName, String contents, String folderName ) throws Exception{
|
||||
protected IFile importFileInsideLinkedFolder(String fileName, String contents, String folderName) throws Exception{
|
||||
IFolder linkedFolder = project.getFolder(folderName);
|
||||
IPath folderLocation = new Path(project.getLocation().toOSString() + File.separator + folderName + "_this_is_linked"); //$NON-NLS-1$
|
||||
IFolder actualFolder = project.getFolder(folderName + "_this_is_linked"); //$NON-NLS-1$
|
||||
|
@ -224,12 +226,12 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase {
|
|||
|
||||
IFile file = linkedFolder.getFile(fileName);
|
||||
|
||||
InputStream stream = new ByteArrayInputStream( contents.getBytes() );
|
||||
InputStream stream = new ByteArrayInputStream(contents.getBytes());
|
||||
//Create file input stream
|
||||
if( file.exists() )
|
||||
file.setContents( stream, false, false, monitor );
|
||||
if (file.exists())
|
||||
file.setContents(stream, false, false, monitor);
|
||||
else
|
||||
file.create( stream, false, monitor );
|
||||
file.create(stream, false, monitor);
|
||||
|
||||
fileManager.addFile(file);
|
||||
|
||||
|
@ -263,7 +265,7 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase {
|
|||
// the action above should highlight the declaration, so now retrieve it and use that selection to get the IASTName selected on the TU
|
||||
ISelection sel = ((AbstractTextEditor)part).getSelectionProvider().getSelection();
|
||||
|
||||
final IASTName[] result= {null};
|
||||
final IASTName[] result= { null };
|
||||
if (sel instanceof ITextSelection) {
|
||||
final ITextSelection textSel = (ITextSelection)sel;
|
||||
ITranslationUnit tu= CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput());
|
||||
|
@ -280,7 +282,11 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase {
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private void assertContents(String code, int offset, String expected) {
|
||||
assertEquals(expected, code.substring(offset, offset + expected.length()));
|
||||
}
|
||||
|
||||
public void testBug93281() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("class Point{ \n"); //$NON-NLS-1$
|
||||
|
@ -412,11 +418,11 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase {
|
|||
|
||||
public void testBug95224() throws Exception{
|
||||
Writer writer = new StringWriter();
|
||||
writer.write( "class A{\n"); //$NON-NLS-1$
|
||||
writer.write( "A();\n"); //$NON-NLS-1$
|
||||
writer.write( "A(const A&); // open definition on A finds class A\n"); //$NON-NLS-1$
|
||||
writer.write( "~A(); // open definition on A finds nothing\n"); //$NON-NLS-1$
|
||||
writer.write( "};\n"); //$NON-NLS-1$
|
||||
writer.write("class A{\n"); //$NON-NLS-1$
|
||||
writer.write("A();\n"); //$NON-NLS-1$
|
||||
writer.write("A(const A&); // open definition on A finds class A\n"); //$NON-NLS-1$
|
||||
writer.write("~A(); // open definition on A finds nothing\n"); //$NON-NLS-1$
|
||||
writer.write("};\n"); //$NON-NLS-1$
|
||||
|
||||
String code = writer.toString();
|
||||
IFile file = importFile("testBug95224.cpp", code); //$NON-NLS-1$
|
||||
|
@ -431,10 +437,10 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase {
|
|||
|
||||
public void testBasicTemplateInstance() throws Exception{
|
||||
Writer writer = new StringWriter();
|
||||
writer.write( "namespace N{ \n"); //$NON-NLS-1$
|
||||
writer.write( " template < class T > class AAA { T _t; };\n"); //$NON-NLS-1$
|
||||
writer.write( "}; \n"); //$NON-NLS-1$
|
||||
writer.write( "N::AAA<int> a; \n"); //$NON-NLS-1$
|
||||
writer.write("namespace N{ \n"); //$NON-NLS-1$
|
||||
writer.write(" template < class T > class AAA { T _t; };\n"); //$NON-NLS-1$
|
||||
writer.write("}; \n"); //$NON-NLS-1$
|
||||
writer.write("N::AAA<int> a; \n"); //$NON-NLS-1$
|
||||
|
||||
String code = writer.toString();
|
||||
IFile file = importFile("testBasicTemplateInstance.cpp", code); //$NON-NLS-1$
|
||||
|
@ -1048,4 +1054,41 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase {
|
|||
assertEquals("myFunc", name.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// struct A {
|
||||
// void method(int p) {}
|
||||
// };
|
||||
//
|
||||
// void test(A* a) {
|
||||
// a->method();
|
||||
// a.method(0);
|
||||
// }
|
||||
// void A::method(int a, int b) {}
|
||||
// void B::method(int b) {}
|
||||
public void testUnresolvedMethod_278337() throws Exception {
|
||||
String code= getContentsForTest(1)[0].toString();
|
||||
IFile file = importFile("testBug278337.cpp", code);
|
||||
IASTNode node= testF3(file, code.indexOf("method();"));
|
||||
assertContents(code, node.getFileLocation().getNodeOffset(), "method(int p)");
|
||||
node= testF3(file, code.indexOf("method(0);"));
|
||||
assertNull(node);
|
||||
node= testF3(file, code.indexOf("method(int a, int b)"));
|
||||
assertContents(code, node.getFileLocation().getNodeOffset(), "method(int p)");
|
||||
node= testF3(file, code.indexOf("method(int b)"));
|
||||
// Should not navigate away since there is no good candidate.
|
||||
assertContents(code, node.getFileLocation().getNodeOffset(), "method(int b)");
|
||||
}
|
||||
|
||||
// class A {
|
||||
// class B {};
|
||||
// };
|
||||
//
|
||||
// B b;
|
||||
public void testUnresolvedType() throws Exception {
|
||||
String code= getContentsForTest(1)[0].toString();
|
||||
IFile file = importFile("testUndefinedType.cpp", code);
|
||||
int offset= code.indexOf("B b;");
|
||||
IASTNode node= testF3(file, offset);
|
||||
assertNull(node);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,6 +88,9 @@ import org.eclipse.cdt.internal.ui.editor.CEditorMessages;
|
|||
import org.eclipse.cdt.internal.ui.text.CWordFinder;
|
||||
import org.eclipse.cdt.internal.ui.viewsupport.IndexUI;
|
||||
|
||||
/**
|
||||
* Navigates to the definition of a name, or to the declaration if invoked on the definition.
|
||||
*/
|
||||
public class OpenDeclarationsAction extends SelectionParseAction implements ASTRunnable {
|
||||
public static boolean sIsJUnitTest = false;
|
||||
|
||||
|
@ -185,38 +188,46 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR
|
|||
openInclude(((IASTPreprocessorIncludeStatement) parent));
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
IBinding binding = sourceName.resolveBinding();
|
||||
NameKind kind = getNameKind(sourceName);
|
||||
if (binding != null && !(binding instanceof IProblemBinding)) {
|
||||
if (kind == NameKind.DEFINITION && binding instanceof IType) {
|
||||
// Don't navigate away from a type definition.
|
||||
// Select the name at the current location instead.
|
||||
navigateToName(sourceName);
|
||||
return Status.OK_STATUS;
|
||||
IBinding b = sourceName.resolveBinding();
|
||||
IBinding[] bindings = new IBinding[] { b };
|
||||
if (b instanceof IProblemBinding) {
|
||||
IBinding[] candidateBindings = ((IProblemBinding) b).getCandidateBindings();
|
||||
if (candidateBindings.length != 0) {
|
||||
bindings = candidateBindings;
|
||||
}
|
||||
IName[] declNames = findDeclNames(ast, kind, binding);
|
||||
// Exclude the current location.
|
||||
for (int i = 0; i < declNames.length; i++) {
|
||||
if (isSameName(declNames[i], sourceName)) {
|
||||
declNames[i] = null;
|
||||
} else if (binding instanceof IParameter) {
|
||||
if (!isInSameFunction(sourceName, declNames[i])) {
|
||||
declNames[i] = null;
|
||||
}
|
||||
} else if (binding instanceof ICPPTemplateParameter) {
|
||||
if (!isInSameTemplate(sourceName, declNames[i])) {
|
||||
} else if (kind == NameKind.DEFINITION && b instanceof IType) {
|
||||
// Don't navigate away from a type definition.
|
||||
// Select the name at the current location instead.
|
||||
navigateToName(sourceName);
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
for (IBinding binding : bindings) {
|
||||
if (binding != null && !(binding instanceof IProblemBinding)) {
|
||||
IName[] declNames = findDeclNames(ast, kind, binding);
|
||||
// Exclude the current location.
|
||||
for (int i = 0; i < declNames.length; i++) {
|
||||
if (isSameName(declNames[i], sourceName)) {
|
||||
declNames[i] = null;
|
||||
} else if (binding instanceof IParameter) {
|
||||
if (!isInSameFunction(sourceName, declNames[i])) {
|
||||
declNames[i] = null;
|
||||
}
|
||||
} else if (binding instanceof ICPPTemplateParameter) {
|
||||
if (!isInSameTemplate(sourceName, declNames[i])) {
|
||||
declNames[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
declNames = (IName[]) ArrayUtil.removeNulls(IName.class, declNames);
|
||||
declNames = (IName[]) ArrayUtil.removeNulls(IName.class, declNames);
|
||||
|
||||
if (navigateViaCElements(fWorkingCopy.getCProject(), fIndex, declNames)) {
|
||||
found= true;
|
||||
} else {
|
||||
// Leave old method as fallback for local variables, parameters and
|
||||
// everything else not covered by ICElementHandle.
|
||||
found = navigateOneLocation(declNames);
|
||||
if (navigateViaCElements(fWorkingCopy.getCProject(), fIndex, declNames)) {
|
||||
found= true;
|
||||
} else {
|
||||
// Leave old method as fallback for local variables, parameters and
|
||||
// everything else not covered by ICElementHandle.
|
||||
found = navigateOneLocation(declNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found && !navigationFallBack(ast, sourceName, kind)) {
|
||||
|
@ -372,10 +383,10 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR
|
|||
continue;
|
||||
}
|
||||
IName[] names = findNames(fIndex, ast, kind, binding);
|
||||
// Exclude the current location.
|
||||
// Exclude names of the same kind.
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (getNameKind(names[i]) == kind) {
|
||||
names[i] = null; // Don' navigate to a name of the same kind.
|
||||
names[i] = null;
|
||||
}
|
||||
}
|
||||
names = (IName[]) ArrayUtil.removeNulls(IName.class, names);
|
||||
|
|
Loading…
Add table
Reference in a new issue