1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 17:05:26 +02:00

Bug 278337.

This commit is contained in:
Sergey Prigogin 2009-05-31 01:07:55 +00:00
parent aecdc9e38c
commit 75560d52b8
9 changed files with 240 additions and 141 deletions

View file

@ -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
*/

View file

@ -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

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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);