From 037ae1d1b3722156c7c20f2401916fdf51ad2a21 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Fri, 23 Oct 2009 07:27:33 +0000 Subject: [PATCH] Navigation of fields, bug 292635. --- .../core/parser/tests/ast2/AST2CPPTests.java | 26 +++++- .../core/dom/parser/cpp/CPPASTDeclarator.java | 93 ++++++++++--------- .../dom/parser/cpp/CPPBuiltinVariable.java | 6 -- .../core/dom/parser/cpp/CPPVariable.java | 31 +------ .../internal/ui/search/CSearchMessages.java | 2 + .../ui/search/CSearchMessages.properties | 9 +- .../internal/ui/search/PDOMSearchQuery.java | 18 +++- 7 files changed, 99 insertions(+), 86 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 47f70f3edcb..b63d06ec1f1 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -7383,15 +7383,35 @@ public class AST2CPPTests extends AST2BaseTest { IASTTranslationUnit tu= parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP); checkDeclDef(declNames, defNames, tu.getDeclarations()); - declNames= new String[] {"v7"}; - defNames= new String[] {"v6", "v8"}; + declNames= new String[] {"v7", "v8"}; + defNames= new String[] {"v6"}; IASTCompositeTypeSpecifier cls= getCompositeType(tu, 5); checkDeclDef(declNames, defNames, cls.getMembers()); } + // extern "C" int v1; + // class X { + // static const int v2= 1; + // }; + // const int X::v2; + public void testVariableDefVsDecl_292635() throws Exception { + String[] declNames= {"v1"}; + String[] defNames= {"X::v2"}; + IASTTranslationUnit tu= parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP); + checkDeclDef(declNames, defNames, tu.getDeclarations()); + + declNames= new String[] {"v2"}; + defNames= new String[] {}; + IASTCompositeTypeSpecifier cls= getCompositeType(tu, 1); + checkDeclDef(declNames, defNames, cls.getMembers()); + } + private void checkDeclDef(String[] declNames, String[] defNames, IASTDeclaration[] decls) { int i= 0, j= 0; for (IASTDeclaration decl : decls) { + if (decl instanceof ICPPASTLinkageSpecification) { + decl= ((ICPPASTLinkageSpecification) decl).getDeclarations()[0]; + } final IASTDeclarator[] dtors = ((IASTSimpleDeclaration) decl).getDeclarators(); for (IASTDeclarator dtor : dtors) { final String name = dtor.getName().toString(); @@ -7401,7 +7421,7 @@ public class AST2CPPTests extends AST2BaseTest { assertEquals(declNames[i++], name); break; case IASTNameOwner.r_definition: - assertTrue("Unexpected decl " + name, i < defNames.length); + assertTrue("Unexpected decl " + name, j < defNames.length); assertEquals(defNames[j++], name); break; default: diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java index 7b80479a2f2..b2a77f10b0f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java @@ -24,6 +24,7 @@ import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTTypeId; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; @@ -166,56 +167,60 @@ public class CPPASTDeclarator extends ASTNode implements IASTDeclarator { public int getRoleForName(IASTName n) { - IASTNode getParent = getParent(); - boolean fnDtor = (this instanceof IASTFunctionDeclarator); - if (getParent instanceof IASTDeclaration) { - if (getParent instanceof IASTFunctionDefinition) + // 3.1.2 + IASTNode parent = ASTQueries.findOutermostDeclarator(this).getParent(); + if (parent instanceof IASTDeclaration) { + // a declaration is a definition unless ... + if (parent instanceof IASTFunctionDefinition) return r_definition; - if (getParent instanceof IASTSimpleDeclaration) { - final int storage = ((IASTSimpleDeclaration) getParent).getDeclSpecifier().getStorageClass(); - - if (getInitializer() != null || storage == IASTDeclSpecifier.sc_typedef) - return r_definition; - if (storage == IASTDeclSpecifier.sc_extern) { - return r_declaration; - } + + if (parent instanceof IASTSimpleDeclaration) { + final IASTSimpleDeclaration sdecl = (IASTSimpleDeclaration) parent; - // static member variables without initializer are declarations - if (!fnDtor && storage == IASTDeclSpecifier.sc_static) { - if (CPPVisitor.getContainingScope(getParent) instanceof ICPPClassScope) { - return r_declaration; - } - } - } - return fnDtor ? r_declaration : r_definition; - } - if (getParent instanceof IASTTypeId) - return r_reference; - if (getParent instanceof IASTDeclarator) { - IASTNode t = getParent; - while (t instanceof IASTDeclarator) - t = t.getParent(); - if (t instanceof IASTDeclaration) { - if (getParent instanceof IASTFunctionDefinition) - return r_definition; - if (getParent instanceof IASTSimpleDeclaration) { - if (getInitializer() != null) - return r_definition; - IASTSimpleDeclaration sd = (IASTSimpleDeclaration) getParent; - int storage = sd.getDeclSpecifier().getStorageClass(); - if (storage == IASTDeclSpecifier.sc_extern || storage == IASTDeclSpecifier.sc_typedef || - storage == IASTDeclSpecifier.sc_static) { - return r_declaration; - } - } - return fnDtor ? r_declaration : r_definition; + // unless it declares a function without body + if (this instanceof IASTFunctionDeclarator) { + return r_declaration; + } + + final int storage = sdecl.getDeclSpecifier().getStorageClass(); + // unless it contains the extern specifier or a linkage-specification and neither initializer nor function-body + if (getInitializer() == null && (storage == IASTDeclSpecifier.sc_extern || isSimpleLinkageSpec(sdecl))) { + return r_declaration; + } + // unless it declares a static data member in a class declaration + if (storage == IASTDeclSpecifier.sc_static && CPPVisitor.getContainingScope(parent) instanceof ICPPClassScope) { + return r_declaration; + } + // unless it is a class name declaration: no declarator in this case + // unless it is a typedef declaration + if (storage == IASTDeclSpecifier.sc_typedef) + return r_definition; // should actually be a declaration + + // unless it is a using-declaration or using-directive: no declarator in this case } - if (t instanceof IASTTypeId) - return r_reference; + + // all other cases + return r_definition; } - if (getParent instanceof IASTParameterDeclaration) + + if (parent instanceof IASTTypeId) + return r_reference; + + if (parent instanceof IASTParameterDeclaration) return (n.getLookupKey().length > 0) ? r_definition : r_declaration; return r_unclear; } + + private boolean isSimpleLinkageSpec(IASTSimpleDeclaration sdecl) { + IASTNode parent= sdecl.getParent(); + if (parent instanceof ICPPASTLinkageSpecification) { + ICPPASTLinkageSpecification spec= (ICPPASTLinkageSpecification) parent; + // todo distinction between braced enclose and simple linkage specification + if (spec.getDeclarations().length == 1) { + return true; + } + } + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBuiltinVariable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBuiltinVariable.java index c48ba72fb40..6de75c90300 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBuiltinVariable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBuiltinVariable.java @@ -11,7 +11,6 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.DOMException; -import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IScope; @@ -116,9 +115,4 @@ public class CPPBuiltinVariable extends CPPVariable { public IBinding getOwner() throws DOMException { return null; } - - @Override - protected boolean isDefinition(IASTName name) { - return false; - } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java index 715f95f3270..d60155ca9ba 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java @@ -29,7 +29,6 @@ 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.IValue; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; @@ -94,7 +93,7 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt private IType type = null; public CPPVariable(IASTName name) { - boolean isDef = isDefinition(name); + boolean isDef = name == null ? false : name.isDefinition(); if (name instanceof ICPPASTQualifiedName) { IASTName[] ns = ((ICPPASTQualifiedName)name).getNames(); name = ns[ns.length - 1]; @@ -113,28 +112,6 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt } } - protected boolean isDefinition(IASTName name) { - IASTDeclarator dtor= findDeclarator(name); - if (dtor == null) { - return false; - } - - IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) dtor.getParent(); - IASTDeclSpecifier declSpec = simpleDecl.getDeclSpecifier(); - - // (3.1-1) A declaration is a definition unless ... - // it contains the extern specifier or a linkage-spec and does not contain an initializer - if (dtor.getInitializer() == null && declSpec.getStorageClass() == IASTDeclSpecifier.sc_extern) - return false; - // or it declares a static data member in a class declaration - if (simpleDecl.getParent() instanceof ICPPASTCompositeTypeSpecifier && - declSpec.getStorageClass() == IASTDeclSpecifier.sc_static) { - return false; - } - - return true; - } - private IASTDeclarator findDeclarator(IASTName name) { IASTNode node = name.getParent(); if (node instanceof ICPPASTQualifiedName) @@ -154,7 +131,7 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt if (!(node instanceof IASTName)) return; IASTName name = (IASTName) node; - if (isDefinition(name)) { + if (name.isDefinition()) { definition = name; } else if (declarations == null) { declarations = new IASTName[] { name }; @@ -316,8 +293,8 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt } IASTNode[] ds= getDeclarations(); if (ds != null) { - for (int i = 0; i < ds.length; i++) { - if (CPPVisitor.isExternC(ds[i])) { + for (IASTNode element : ds) { + if (CPPVisitor.isExternC(element)) { return true; } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.java index c281fbcfbec..79ab7dc0fa9 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.java @@ -68,6 +68,8 @@ public final class CSearchMessages extends NLS { public static String PDOMSearchQuery_refs_result_label; public static String PDOMSearchQuery_defs_result_label; public static String PDOMSearchQuery_decls_result_label; + public static String PDOMSearchQuery_decldefs_result_label; + public static String PDOMSearchQuery_occurrences_result_label; public static String PDOMSearchElementQuery_something; public static String PDOMSearchPatternQuery_PatternQuery_labelPatternInScope; public static String PDOMSearch_query_pattern_error; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.properties index 418f5662d77..e412ac92259 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/CSearchMessages.properties @@ -70,9 +70,12 @@ ProjectScope = Project PDOMSearchQuery_refs_label = Search references PDOMSearchQuery_defs_label = Search definitions PDOMSearchQuery_decls_label = Search declarations -PDOMSearchQuery_refs_result_label = References to {0} -PDOMSearchQuery_defs_result_label = Definitions of {0} -PDOMSearchQuery_decls_result_label = Declarations of {0} +PDOMSearchQuery_refs_result_label = References to ''{0}'' +PDOMSearchQuery_defs_result_label = Definitions of ''{0}'' +PDOMSearchQuery_decls_result_label = Declarations of ''{0}'' +PDOMSearchQuery_decldefs_result_label = Declarations and definitions of ''{0}'' +PDOMSearchQuery_occurrences_result_label = Occurrences of ''{0}'' + PDOMSearchElementQuery_something = something PDOMSearchPatternQuery_PatternQuery_labelPatternInScope={0} in {1} PDOMSearchTreeContentProvider_IndexerNotEnabledWarning=(unknown results: indexer is not enabled) diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchQuery.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchQuery.java index 03b03c50969..cd873a7cdc7 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchQuery.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/PDOMSearchQuery.java @@ -151,12 +151,24 @@ public abstract class PDOMSearchQuery implements ISearchQuery { public String getResultLabel(String pattern, int matchCount) { // Report pattern and number of matches String label; - if ((flags & FIND_REFERENCES) != 0) + final int kindFlags= flags & FIND_ALL_OCCURANCES; + switch(kindFlags) { + case FIND_REFERENCES: label = NLS.bind(CSearchMessages.PDOMSearchQuery_refs_result_label, pattern); - else if ((flags & FIND_DECLARATIONS) != 0) + break; + case FIND_DECLARATIONS: label = NLS.bind(CSearchMessages.PDOMSearchQuery_decls_result_label, pattern); - else + break; + case FIND_DEFINITIONS: label = NLS.bind(CSearchMessages.PDOMSearchQuery_defs_result_label, pattern); + break; + case FIND_DECLARATIONS_DEFINITIONS: + label = NLS.bind(CSearchMessages.PDOMSearchQuery_decldefs_result_label, pattern); + break; + default: + label = NLS.bind(CSearchMessages.PDOMSearchQuery_occurrences_result_label, pattern); + break; + } String countLabel = Messages.format(CSearchMessages.CSearchResultCollector_matches, new Integer( matchCount)); return label + " " + countLabel; //$NON-NLS-1$