mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-05 23:35:48 +02:00
Bug 278337.
This commit is contained in:
parent
aecdc9e38c
commit
75560d52b8
9 changed files with 240 additions and 141 deletions
|
@ -48,6 +48,17 @@ public interface IProblemBinding extends IBinding, IScope, IType {
|
|||
*/
|
||||
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() {
|
||||
|
@ -60,6 +70,10 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I
|
|||
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
|
||||
|
|
|
@ -839,7 +839,8 @@ public class CVisitor extends ASTQueries {
|
|||
try {
|
||||
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) {
|
||||
|
@ -854,7 +855,8 @@ public class CVisitor extends ASTQueries {
|
|||
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;
|
||||
}
|
||||
|
@ -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,7 +1885,10 @@ 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 (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);
|
||||
|
@ -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);
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
// boolean fromIndex= isFromIndex(fn);
|
||||
// if (isFromIndex(result) == fromIndex)
|
||||
// return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
// if (!fromIndex)
|
||||
// result= fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -281,6 +283,10 @@ 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$
|
||||
|
@ -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,15 +188,22 @@ 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) {
|
||||
IBinding b = sourceName.resolveBinding();
|
||||
IBinding[] bindings = new IBinding[] { b };
|
||||
if (b instanceof IProblemBinding) {
|
||||
IBinding[] candidateBindings = ((IProblemBinding) b).getCandidateBindings();
|
||||
if (candidateBindings.length != 0) {
|
||||
bindings = candidateBindings;
|
||||
}
|
||||
} 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++) {
|
||||
|
@ -219,6 +229,7 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR
|
|||
found = navigateOneLocation(declNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found && !navigationFallBack(ast, sourceName, kind)) {
|
||||
reportSymbolLookupFailure(new String(sourceName.toCharArray()));
|
||||
}
|
||||
|
@ -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