[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[cdt-patch] Parser Symbol Table: prefix lookup
|
First pass at prefix lookup.
Core:
In prefix lookup, the lookup does not stop when a symbol is found, also
abiguity resolution is modified.
Add IContainerSymbol.prefixLookup (signature subject to change)
Add ParserSymbolTable.LookupMode, an enum with 2 values: NORMAL,
PREFIX
In prefix mode, the lookup does not stop when a symbol is found.
Tests:
ParserSymbolTableTest.testBug46882
ParserSymbolTableTest.testPrefixLookup_Unqualified
ParserSymbolTableTest.testPrefixLookup_Qualified
ParserSymbolTableTest.testPrefixLookup_Inheritance
Tested on windows.
-Andrew
Index: parser/ChangeLog
===================================================================
retrieving revision 1.163
diff -u -r1.163 ChangeLog
--- parser/ChangeLog 20 Nov 2003 15:22:56 -0000 1.163
+++ parser/ChangeLog 27 Nov 2003 16:58:47 -0000
@@ -1,3 +1,9 @@
+2003-11-27 Andrew Niefer
+ Initial changes to support prefix lookup
+ Add IContainerSymbol.prefixLookup (signature subject to change)
+ Add ParserSymbolTable.LookupMode, an enum with 2 values: NORMAL, PREFIX
+ In prefix mode, the lookup does not stop when a symbol is found.
+
2003-11-18 Andrew Niefer
Refactor PST: Split Declaration into 4 classes : ContainerSymbol, DerivableContainerSymbol, ParameterizedContainerSymbol,
SpecializedSymbol. Move these along with BasicSymbol & TemplateInstance to no longer be nested in ParserSymbolTable.
Index: parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java
===================================================================
retrieving revision 1.1
diff -u -r1.1 ContainerSymbol.java
--- parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java 20 Nov 2003 15:22:56 -0000 1.1
+++ parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java 27 Nov 2003 16:58:51 -0000
@@ -212,37 +212,44 @@
//figure out which declaration we are talking about, if it is a set of functions,
//then they will be in data.foundItems (since we provided no parameter info);
- ISymbol obj = null;
+ ISymbol symbol = null;
+ ISymbol clone = null;
+ Iterator iter = null;
+
try{
- obj = ParserSymbolTable.resolveAmbiguities( data );
+ symbol = ParserSymbolTable.resolveAmbiguities( data );
} catch ( ParserSymbolTableException e ) {
if( e.reason != ParserSymbolTableException.r_UnableToResolveFunction ){
throw e;
}
}
- if( data.foundItems == null ){
+ if( symbol == null && (data.foundItems == null || data.foundItems.isEmpty()) ){
throw new ParserSymbolTableException( ParserSymbolTableException.r_InvalidUsing );
}
- ISymbol clone = null;
+ if( symbol == null ){
+ Object object = data.foundItems.get( data.name );
+ iter = ( object instanceof List ) ? ((List) object).iterator() : null;
+ symbol = ( iter != null && iter.hasNext() ) ? (ISymbol)iter.next() : null;
+ }
- //if obj != null, then that is the only object to consider, so size is 1,
- //otherwise we consider the foundItems set
- int size = ( obj == null ) ? data.foundItems.size() : 1;
- Iterator iter = data.foundItems.iterator();
- for( int i = size; i > 0; i-- ){
- obj = ( obj != null && size == 1 ) ? obj : (ISymbol) iter.next();
-
- if( ParserSymbolTable.okToAddUsingDeclaration( obj, this ) ){
- clone = (BasicSymbol) obj.clone(); //7.3.3-9
+ while( symbol != null ){
+ if( ParserSymbolTable.okToAddUsingDeclaration( symbol, this ) ){
+ clone = (ISymbol) symbol.clone(); //7.3.3-9
addSymbol( clone );
} else {
throw new ParserSymbolTableException( ParserSymbolTableException.r_InvalidUsing );
}
+
+ if( iter != null && iter.hasNext() ){
+ symbol = (ISymbol) iter.next();
+ } else {
+ symbol = null;
+ }
}
-
- return ( size == 1 ) ? clone : null;
+
+ return clone;
}
/* (non-Javadoc)
@@ -322,7 +329,7 @@
}
}
- ParserSymbolTable.lookupInContained( data, container );
+ data.foundItems = ParserSymbolTable.lookupInContained( data, container );
return ParserSymbolTable.resolveAmbiguities( data );
}
@@ -349,7 +356,7 @@
LookupData data = new LookupData( name, TypeInfo.t_namespace, getTemplateInstance() );
data.upperType = TypeInfo.t_union;
- ParserSymbolTable.lookupInContained( data, inSymbol );
+ data.foundItems = ParserSymbolTable.lookupInContained( data, inSymbol );
if( data.foundItems != null ){
foundSymbol = (ISymbol) ParserSymbolTable.resolveAmbiguities( data );//, data.foundItems );
@@ -455,9 +462,9 @@
//if we haven't found anything, or what we found is not a class member, consider the
//associated scopes
if( found == null || found.getContainingSymbol().getType() != TypeInfo.t_class ){
- if( found != null ){
- data.foundItems.add( found );
- }
+// if( found != null ){
+// data.foundItems.add( found );
+// }
IContainerSymbol associatedScope;
//dump the hash to an array and iterate over the array because we
@@ -539,6 +546,34 @@
return null;
}
+ public List prefixLookup( TypeInfo.eType type, String prefix, boolean qualified ) throws ParserSymbolTableException{
+ LookupData data = new LookupData( prefix, type, getTemplateInstance() );
+ data.qualified = qualified;
+ data.mode = ParserSymbolTable.LookupMode.PREFIX;
+
+ ParserSymbolTable.lookup( data, this );
+
+ if( data.foundItems == null || data.foundItems.isEmpty() ){
+ return null;
+ } else {
+ List list = new LinkedList();
+
+ Iterator iter = data.foundItems.keySet().iterator();
+ Object obj = null;
+ while( iter.hasNext() ){
+ obj = data.foundItems.get( iter.next() );
+
+ if( obj instanceof List ){
+ list.addAll( (List) obj );
+ } else{
+ list.add( obj );
+ }
+ }
+
+ return list;
+ }
+ }
+
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol#instantiate(java.util.List)
*/
Index: parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java
===================================================================
retrieving revision 1.1
diff -u -r1.1 DerivableContainerSymbol.java
--- parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java 20 Nov 2003 15:22:56 -0000 1.1
+++ parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java 27 Nov 2003 16:58:52 -0000
@@ -17,6 +17,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
+import java.util.Map;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
@@ -189,11 +190,19 @@
if( obj.getContainingSymbol().isType( TypeInfo.t_class, TypeInfo.t_union ) ){
//check to see if there is already a this object, since using declarations
//of function will have them from the original declaration
+ boolean foundThis = false;
+
LookupData data = new LookupData( ParserSymbolTable.THIS, TypeInfo.t_any, null );
- ParserSymbolTable.lookupInContained( data, obj );
+ try {
+ Map map = ParserSymbolTable.lookupInContained( data, obj );
+ foundThis = map.containsKey( data.name );
+ } catch (ParserSymbolTableException e) {
+ return false;
+ }
+
//if we didn't find "this" then foundItems will still be null, no need to actually
//check its contents
- if( data.foundItems == null ){
+ if( !foundThis ){
ISymbol thisObj = getSymbolTable().newSymbol( ParserSymbolTable.THIS, TypeInfo.t_type );
thisObj.setTypeSymbol( obj.getContainingSymbol() );
//thisObj.setCVQualifier( obj.getCVQualifier() );
Index: parser/org/eclipse/cdt/internal/core/parser/pst/IContainerSymbol.java
===================================================================
retrieving revision 1.7
diff -u -r1.7 IContainerSymbol.java
--- parser/org/eclipse/cdt/internal/core/parser/pst/IContainerSymbol.java 20 Nov 2003 15:22:56 -0000 1.7
+++ parser/org/eclipse/cdt/internal/core/parser/pst/IContainerSymbol.java 27 Nov 2003 16:58:52 -0000
@@ -39,6 +39,8 @@
public Map getContainedSymbols();
+ public List prefixLookup( TypeInfo.eType type, String prefix, boolean qualified ) throws ParserSymbolTableException;
+
public ISymbol elaboratedLookup( TypeInfo.eType type, String name ) throws ParserSymbolTableException;
public ISymbol lookup( String name ) throws ParserSymbolTableException;
public ISymbol lookupMemberForDefinition( String name ) throws ParserSymbolTableException;
Index: parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java
===================================================================
retrieving revision 1.26
diff -u -r1.26 ParserSymbolTable.java
--- parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java 20 Nov 2003 15:22:56 -0000 1.26
+++ parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java 27 Nov 2003 16:58:53 -0000
@@ -22,6 +22,7 @@
import java.util.Map;
import java.util.Set;
+import org.eclipse.cdt.core.parser.Enum;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
import org.eclipse.cdt.internal.core.parser.pst.TypeInfo.PtrOp;
@@ -105,7 +106,12 @@
LinkedList transitives = new LinkedList(); //list of transitive using directives
//if this name define in this scope?
- lookupInContained( data, inSymbol );
+ Map map = lookupInContained( data, inSymbol );
+ if( data.foundItems == null || data.foundItems.isEmpty() ){
+ data.foundItems = map;
+ } else {
+ mergeResults( data, data.foundItems, map );
+ }
if( inSymbol.getSymbolTable().getLanguage() == ParserLanguage.CPP &&
!data.ignoreUsingDirectives )
@@ -120,7 +126,7 @@
//if we are doing a qualified lookup, only process using directives if
//we haven't found the name yet (and if we aren't ignoring them).
- if( !data.qualified || data.foundItems == null ){
+ if( !data.qualified || data.foundItems == null || data.foundItems.isEmpty() ){
processDirectives( inSymbol, data, transitives );
if( inSymbol.hasUsingDirectives() ){
@@ -139,25 +145,26 @@
}
}
- if( data.foundItems != null || data.stopAt == inSymbol ){
+ if( data.mode == LookupMode.NORMAL && ( !data.foundItems.isEmpty() || data.stopAt == inSymbol ) ){
return;
}
if( inSymbol instanceof IDerivableContainerSymbol ){
//if we still havn't found it, check any parents we have
- data.visited.clear(); //each virtual base class is searched at most once
- symbol = lookupInParents( data, (IDerivableContainerSymbol)inSymbol );
-
- //there is a resolveAmbiguities inside LookupInParents, which means if we found
- //something the foundItems set will be non-null, but empty. So, add the decl into
- //the foundItems set
- if( symbol != null ){
- data.foundItems.add( symbol );
+ data.visited.clear(); //each virtual base class is searched at most once
+ map = lookupInParents( data, (IDerivableContainerSymbol)inSymbol );
+
+ if( data.foundItems == null || data.foundItems.isEmpty() ){
+ data.foundItems = map;
+ } else {
+ mergeInheritedResults( data.foundItems, map );
}
}
//if still not found, check our containing scope.
- if( data.foundItems == null && inSymbol.getContainingSymbol() != null ){
+ if( ( data.foundItems == null || data.foundItems.isEmpty() || ( data.mode == LookupMode.PREFIX && !data.qualified ) )
+ && inSymbol.getContainingSymbol() != null )
+ {
lookup( data, inSymbol.getContainingSymbol() );
}
@@ -183,7 +190,7 @@
* directives, the effect is as if the using-directives from the second
* namespace also appeared in the first.
*/
- static private void lookupInNominated( LookupData data, IContainerSymbol symbol, LinkedList transitiveDirectives ){
+ static private void lookupInNominated( LookupData data, IContainerSymbol symbol, LinkedList transitiveDirectives ) throws ParserSymbolTableException{
//if the data.usingDirectives is empty, there is nothing to do.
if( data.usingDirectives == null ){
return;
@@ -212,11 +219,13 @@
if( !data.visited.contains( temp ) ){
data.visited.add( temp );
- foundSomething = lookupInContained( data, temp );
-
+ Map map = lookupInContained( data, temp );
+ foundSomething = !map.isEmpty();
+ mergeResults( data, data.foundItems, map );
+
//only consider the transitive using directives if we are an unqualified
//lookup, or we didn't find the name in decl
- if( (!data.qualified || !foundSomething ) && temp.getUsingDirectives() != null ){
+ if( (!data.qualified || !foundSomething || data.mode == LookupMode.PREFIX ) && temp.getUsingDirectives() != null ){
//name wasn't found, add transitive using directives for later consideration
transitiveDirectives.addAll( temp.getUsingDirectives() );
}
@@ -227,14 +236,47 @@
}
/**
+ * @param map
+ * @param map2
+ */
+ private static void mergeResults( LookupData data, Map resultMap, Map map ) throws ParserSymbolTableException {
+ if( resultMap == null || map == null || map.isEmpty() ){
+ return;
+ }
+
+ Iterator keyIterator = map.keySet().iterator();
+ Object key = null;
+ while( keyIterator.hasNext() ){
+ key = keyIterator.next();
+ if( resultMap.containsKey( key ) ){
+ List list = new LinkedList();
+ Object obj = resultMap.get( key );
+
+ if ( obj instanceof List ) list.addAll( (List) obj );
+ else list.add( obj );
+
+ obj = map.get( key );
+
+ if( obj instanceof List ) list.addAll( (List) obj );
+ else list.add( obj );
+
+ resultMap.put( key, collectSymbol( data, list ) );
+ } else {
+ resultMap.put( key, map.get( key ) );
+ }
+ }
+ }
+
+ /**
* function LookupInContained
* @param data
* @return List
*
* Look for data.name in our collection _containedDeclarations
*/
- protected static boolean lookupInContained( LookupData data, IContainerSymbol lookIn ){
-
+ protected static Map lookupInContained( LookupData data, IContainerSymbol lookIn ) throws ParserSymbolTableException{
+ Map found = new HashMap();
+
boolean foundSomething = false;
ISymbol temp = null;
Object obj = null;
@@ -246,78 +288,63 @@
Map declarations = lookIn.getContainedSymbols();
- obj = ( declarations != null ) ? declarations.get( data.name ) : null;
-
- if( obj != null ){
- //the contained declarations map either to a Declaration object, or to a list
- //of declaration objects.
- if( obj instanceof ISymbol ){
- temp = (ISymbol) obj;
- //if( ((ISymbol)obj).isType( data.type, data.upperType ) ){
- if( checkType( data, temp, data.type, data.upperType ) ){
- if( data.foundItems == null ){
- data.foundItems = new HashSet();
- }
- if( temp.isTemplateMember() )
- data.foundItems.add( new TemplateInstance( temp.getSymbolTable(), temp, data.templateInstance.getArgumentMap() ) );
- else
- data.foundItems.add( temp );
+ Iterator iterator = ( data.mode == LookupMode.PREFIX ) ? declarations.keySet().iterator() : null;
+ String name = ( iterator != null && iterator.hasNext() ) ? (String) iterator.next() : data.name;
+
+ while( name != null ) {
+ if( nameMatches( data, name ) ){
+ obj = ( declarations != null ) ? declarations.get( name ) : null;
+
+ obj = collectSymbol( data, obj );
+
+ if( obj != null )
+ found.put( name, obj );
+ }
- foundSomething = true;
- }
+ if( iterator != null && iterator.hasNext() ){
+ name = (String) iterator.next();
} else {
- //we have to filter on type so can't just add the list whole to the fount set
- LinkedList objList = (LinkedList)obj;
- Iterator iter = objList.iterator();
- int size = objList.size();
-
- for( int i = 0; i < size; i++ ){
- temp = (ISymbol) iter.next();
-
- //if( temp.isType( data.type, data.upperType ) ){
- if( checkType( data, temp, data.type, data.upperType ) ){
- if( data.foundItems == null ){
- data.foundItems = new HashSet();
- }
- if( temp.isTemplateMember() )
- data.foundItems.add( new TemplateInstance( temp.getSymbolTable(), temp, data.templateInstance.getArgumentMap() ) );
- else
- data.foundItems.add(temp);
- foundSomething = true;
- }
- }
+ name = null;
}
- }
-
- if( foundSomething ){
- return foundSomething;
+ }
+
+ if( !found.isEmpty() && data.mode == LookupMode.NORMAL ){
+ return found;
}
if( lookIn instanceof IParameterizedSymbol ){
Map parameters = ((IParameterizedSymbol)lookIn).getParameterMap();
if( parameters != null ){
- obj = parameters.get( data.name );
- //if( obj != null && ((ISymbol)obj).isType( data.type, data.upperType ) ){
- if( obj != null && checkType( data, (ISymbol)obj, data.type, data.upperType ) ){
- if( data.foundItems == null ){
- data.foundItems = new HashSet();
+ iterator = ( data.mode == LookupMode.PREFIX ) ? parameters.keySet().iterator() : null;
+ name = ( iterator != null && iterator.hasNext() ) ? (String) iterator.next() : data.name;
+ while( name != null ){
+ if( nameMatches( data, name ) ){
+ obj = parameters.get( data.name );
+ obj = collectSymbol( data, obj );
+ if( obj != null ){
+ found.put( name, obj );
+ }
}
- ISymbol symbol = (ISymbol) obj;
-
- if( symbol.isTemplateMember() && data.templateInstance != null ){
- data.foundItems.add( new TemplateInstance( symbol.getSymbolTable(), symbol, data.templateInstance.getArgumentMap() ) );
+ if( iterator != null && iterator.hasNext() ){
+ name = (String) iterator.next();
} else {
- data.foundItems.add( symbol );
+ name = null;
}
-
- foundSomething = true;
}
+
}
}
- return foundSomething;
+ return found;
}
+ private static boolean nameMatches( LookupData data, String name ){
+ if( data.mode == LookupMode.PREFIX ){
+ return name.startsWith( data.name );
+ } else {
+ return name.equals( data.name );
+ }
+ }
private static boolean checkType( LookupData data, ISymbol symbol, TypeInfo.eType type, TypeInfo.eType upperType ){
if( data.templateInstance != null && symbol.isTemplateMember() ){
if( symbol.isType( TypeInfo.t_type ) ){
@@ -331,6 +358,100 @@
return symbol.isType( type, upperType );
}
+ private static Object collectSymbol(LookupData data, Object object ) throws ParserSymbolTableException {
+ if( object == null ){
+ return null;
+ }
+
+ ISymbol foundSymbol = null;
+
+ Iterator iter = ( object instanceof List ) ? ((List)object).iterator() : null;
+ ISymbol symbol = ( iter != null ) ? (ISymbol) iter.next() : (ISymbol) object;
+
+ List functionList = new LinkedList();
+ ISymbol obj = null;
+ IContainerSymbol cls = null;
+
+ while( symbol != null ){
+ if( checkType( data, symbol, data.type, data.upperType ) ){
+ if( symbol.isTemplateMember() && data.templateInstance != null )
+ foundSymbol = new TemplateInstance( symbol.getSymbolTable(), symbol, data.templateInstance.getArgumentMap() );
+ else
+ foundSymbol = symbol;
+
+ if( foundSymbol.isType( TypeInfo.t_function ) ){
+ functionList.add( foundSymbol );
+ } else {
+ //if this is a class-name, other stuff hides it
+ if( foundSymbol.isType( TypeInfo.t_class, TypeInfo.t_enumeration ) ){
+ if( cls == null ){
+ cls = (IContainerSymbol) foundSymbol;
+ } else {
+ if( cls.getTypeInfo().isForwardDeclaration() && cls.getTypeSymbol() == foundSymbol ){
+ //cls is a forward declaration of decl, we want decl.
+ cls = (IContainerSymbol) foundSymbol;
+ } else if( foundSymbol.getTypeInfo().isForwardDeclaration() && foundSymbol.getTypeSymbol() == cls ){
+ //decl is a forward declaration of cls, we already have what we want (cls)
+ } else {
+ throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
+ }
+ }
+ } else {
+ //an object, can only have one of these
+ if( obj == null ){
+ obj = foundSymbol;
+ } else {
+ throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
+ }
+ }
+ }
+ }
+
+ if( iter != null ){
+ symbol = iter.hasNext() ? (ISymbol) iter.next() : null;
+ } else {
+ symbol = null;
+ }
+ }
+
+ int numFunctions = functionList.size();
+
+ boolean ambiguous = false;
+
+ if( cls != null ){
+ //the class is only hidden by other stuff if they are from the same scope
+ if( obj != null && cls.getContainingSymbol() != obj.getContainingSymbol()){
+ ambiguous = true;
+ }
+ if( functionList != null ){
+ Iterator fnIter = functionList.iterator();
+ IParameterizedSymbol fn = null;
+ for( int i = numFunctions; i > 0; i-- ){
+ fn = (IParameterizedSymbol) fnIter.next();
+ if( cls.getContainingSymbol()!= fn.getContainingSymbol()){
+ ambiguous = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if( obj != null && !ambiguous ){
+ if( numFunctions > 0 ){
+ ambiguous = true;
+ } else {
+ return obj;
+ }
+ } else if( numFunctions > 0 ) {
+ return functionList;
+ }
+
+ if( ambiguous ){
+ throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
+ } else {
+ return cls;
+ }
+ }
/**
*
* @param data
@@ -338,7 +459,7 @@
* @return Declaration
* @throws ParserSymbolTableException
*/
- private static ISymbol lookupInParents( LookupData data, ISymbol lookIn ) throws ParserSymbolTableException{
+ private static Map lookupInParents( LookupData data, ISymbol lookIn ) throws ParserSymbolTableException{
IDerivableContainerSymbol container = null;
/*if( lookIn instanceof TemplateInstance ){
@@ -351,8 +472,9 @@
List scopes = container.getParents();
- ISymbol temp = null;
- ISymbol symbol = null;
+ Map temp = null;
+ Map symbol = null;
+ Map inherited = null;
Iterator iterator = null;
IDerivableContainerSymbol.IParentSymbol wrapper = null;
@@ -396,39 +518,39 @@
data.templateInstance = (TemplateInstance) parent;
ISymbol instance = ((TemplateInstance)parent).getInstantiatedSymbol();
if( instance instanceof IContainerSymbol )
- lookupInContained( data, (IContainerSymbol)instance );
+ temp = lookupInContained( data, (IContainerSymbol)instance );
else
throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplate );
data.templateInstance = tempInstance;
} else if( parent instanceof IDerivableContainerSymbol ){
- lookupInContained( data, (IDerivableContainerSymbol) parent );
+ temp = lookupInContained( data, (IDerivableContainerSymbol) parent );
} else {
throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
}
- temp = resolveAmbiguities( data );
- if( temp == null ){
- temp = lookupInParents( data, parent );
+
+ if( temp.isEmpty() || data.mode == LookupMode.PREFIX ){
+ inherited = lookupInParents( data, parent );
+ mergeInheritedResults( temp, inherited );
}
} else {
throw new ParserSymbolTableException( ParserSymbolTableException.r_CircularInheritance );
}
}
- if( temp != null && temp.isType( data.type ) ){
-
- if( symbol == null ){
+ if( temp != null && !temp.isEmpty() ){
+ if( symbol == null || symbol.isEmpty() ){
symbol = temp;
- } else if ( temp != null ) {
- //it is not ambiguous if temp & decl are the same thing and it is static
- //or an enumerator
- TypeInfo type = temp.getTypeInfo();
-
- if( symbol == temp && ( type.checkBit( TypeInfo.isStatic ) || type.isType( TypeInfo.t_enumerator ) ) ){
- temp = null;
- } else {
- throw( new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ) );
+ } else if ( temp != null && !temp.isEmpty() ) {
+ Iterator iter = temp.keySet().iterator();
+ Object key = null;
+ while( iter.hasNext() ){
+ key = iter.next();
+ if( symbol.containsKey( key ) ){
+ checkAmbiguity( symbol.get( key ), temp.get( key ) );
+ } else {
+ symbol.put( key, temp.get( key ) );
+ }
}
-
}
} else {
temp = null; //reset temp for next iteration
@@ -440,6 +562,50 @@
return symbol;
}
+ private static void checkAmbiguity( Object obj1, Object obj2 ) throws ParserSymbolTableException{
+ //it is not ambiguous if they are the same thing and it is static or an enumerator
+ if( obj1 == obj2 ){
+
+ Iterator iter = ( obj1 instanceof List ) ? ((List) obj1).iterator() : null;
+ ISymbol symbol = ( iter != null ) ? (ISymbol) iter.next() : ( ISymbol )obj1;
+ while( symbol != null ) {
+ TypeInfo type = ((ISymbol)obj1).getTypeInfo();
+ if( !type.checkBit( TypeInfo.isStatic ) && !type.isType( TypeInfo.t_enumerator ) ){
+ throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
+ }
+
+ if( iter != null && iter.hasNext() ){
+ symbol = (ISymbol) iter.next();
+ } else {
+ symbol = null;
+ }
+ }
+ return;
+ }
+ throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
+ }
+
+ /**
+ * Symbols in map are added to the resultMap if a symbol with that name does not already exist there
+ * @param resultMap
+ * @param map
+ * @throws ParserSymbolTableException
+ */
+ private static void mergeInheritedResults( Map resultMap, Map map ) throws ParserSymbolTableException{
+ if( resultMap == null || map == null || map.isEmpty() ){
+ return;
+ }
+
+ Iterator keyIterator = map.keySet().iterator();
+ Object key = null;
+ while( keyIterator.hasNext() ){
+ key = keyIterator.next();
+ if( !resultMap.containsKey( key ) ){
+ resultMap.put( key, map.get( key ) );
+ }
+ }
+ }
+
/**
* function isValidOverload
* @param origDecl
@@ -561,119 +727,38 @@
ISymbol obj = null;
IContainerSymbol cls = null;
- if( data.foundItems == null ){
+ if( data.foundItems == null || data.foundItems.isEmpty() || data.mode == LookupMode.PREFIX ){
return null;
}
int size = data.foundItems.size();
- Iterator iter = data.foundItems.iterator();
-
- boolean needDecl = true;
-
- if( size == 0){
- return null;
- } else if (size == 1) {
- decl = (ISymbol) iter.next();
- //if it is a function we need to check its parameters
- if( !decl.isType( TypeInfo.t_function ) ){
- data.foundItems.clear();
- return decl;
- }
- needDecl = false;
- }
+ //Iterator iter = data.foundItems.iterator();
- LinkedList functionList = null;
+ Object object = data.foundItems.get( data.name );
- for( int i = size; i > 0; i-- ){
- //if we
- if( needDecl ){
- decl = (ISymbol) iter.next();
- } else {
- needDecl = true;
- }
-
- if( decl.isType( TypeInfo.t_function ) ){
- if( functionList == null){
- functionList = new LinkedList();
- }
- functionList.add( decl );
- } else {
- //if this is a class-name, other stuff hides it
- if( decl.isType( TypeInfo.t_class, TypeInfo.t_enumeration ) ){
- if( cls == null ){
- cls = (IContainerSymbol) decl;
- } else {
- if( cls.getTypeInfo().isForwardDeclaration() && cls.getTypeSymbol() == decl ){
- //cls is a forward declaration of decl, we want decl.
- cls = (IContainerSymbol) decl;
- } else if( decl.getTypeInfo().isForwardDeclaration() && decl.getTypeSymbol() == cls ){
- //decl is a forward declaration of cls, we already have what we want (cls)
- } else {
- throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
- }
- }
- } else {
- //an object, can only have one of these
- if( obj == null ){
- obj = decl;
- } else {
- throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
- }
- }
- }
-
- decl = null;
- }
-
- data.foundItems.clear();
-
- int numFunctions = ( functionList == null ) ? 0 : functionList.size();
+ LinkedList functionList = new LinkedList();
- boolean ambiguous = false;
-
- if( cls != null ){
- //the class is only hidden by other stuff if they are from the same scope
- if( obj != null && cls.getContainingSymbol() != obj.getContainingSymbol()){
- ambiguous = true;
- }
- if( functionList != null ){
- Iterator fnIter = functionList.iterator();
- IParameterizedSymbol fn = null;
- for( int i = numFunctions; i > 0; i-- ){
- fn = (IParameterizedSymbol) fnIter.next();
- if( cls.getContainingSymbol()!= fn.getContainingSymbol()){
- ambiguous = true;
- break;
- }
- }
+ if( object instanceof List ){
+ functionList.addAll( (List) object );
+ } else {
+ ISymbol symbol = (ISymbol) object;
+ if( symbol.isType( TypeInfo.t_function ) ){
+ functionList.add( symbol );
+ } else {
+ return symbol;
}
}
- if( obj != null && !ambiguous ){
- if( numFunctions > 0 ){
- ambiguous = true;
+ if( data.parameters == null ){
+ //we have no parameter information, if we only have one function, return
+ //that, otherwise we can't decide between them
+ if( functionList.size() == 1){
+ return (ISymbol) functionList.getFirst();
} else {
- return obj;
+ throw new ParserSymbolTableException( ParserSymbolTableException.r_UnableToResolveFunction );
}
- } else if( numFunctions > 0 ) {
- if( data.parameters == null ){
- //we have no parameter information, if we only have one function, return
- //that, otherwise we can't decide between them
- if( numFunctions == 1){
- return (ISymbol) functionList.getFirst();
- } else {
- data.foundItems.addAll( functionList );
- throw new ParserSymbolTableException( ParserSymbolTableException.r_UnableToResolveFunction );
- }
- } else {
- return resolveFunction( data, functionList );
- }
- }
-
- if( ambiguous ){
- throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
} else {
- return cls;
+ return resolveFunction( data, functionList );
}
}
@@ -1549,7 +1634,7 @@
data.parameters = params;
data.forUserDefinedConversion = true;
- lookupInContained( data, (IContainerSymbol) sourceDecl );
+ data.foundItems = lookupInContained( data, (IContainerSymbol) sourceDecl );
conversion = (IParameterizedSymbol)resolveAmbiguities( data );
}
}
@@ -2089,7 +2174,15 @@
}
-
+ static public class LookupMode extends Enum{
+ public static final LookupMode PREFIX = new LookupMode( 1 );
+ public static final LookupMode NORMAL = new LookupMode( 2 );
+
+ private LookupMode( int constant)
+ {
+ super( constant );
+ }
+ }
static protected class LookupData
@@ -2111,9 +2204,10 @@
public boolean ignoreUsingDirectives = false;
public boolean forUserDefinedConversion = false;
- public HashSet foundItems = null;
+ public Map foundItems = null;
public ISymbol templateInstance = null;
+ public LookupMode mode = LookupMode.NORMAL;
public LookupData( String n, TypeInfo.eType t, ISymbol i ){
name = n;
Index: ChangeLog
===================================================================
retrieving revision 1.144
diff -u -r1.144 ChangeLog
--- ChangeLog 20 Nov 2003 15:23:01 -0000 1.144
+++ ChangeLog 27 Nov 2003 16:58:25 -0000
@@ -1,3 +1,10 @@
+2003-11-27 Andrew Niefer
+ tests for Symbol table prefix lookup
+ ParserSymbolTableTest.testBug46882
+ ParserSymbolTableTest.testPrefixLookup_Unqualified
+ ParserSymbolTableTest.testPrefixLookup_Qualified
+ ParserSymbolTableTest.testPrefixLookup_Inheritance
+
2003-11-18 Andrew Niefer
update ParserSymbolTableTest to reflect refactoring of Declaration into 4 separate classes.
Index: parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java
===================================================================
retrieving revision 1.24
diff -u -r1.24 ParserSymbolTableTest.java
--- parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java 20 Nov 2003 15:23:01 -0000 1.24
+++ parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java 27 Nov 2003 16:58:28 -0000
@@ -13,6 +13,7 @@
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import junit.framework.TestCase;
@@ -688,6 +689,8 @@
}
look = f.lookupNestedNameSpecifier("N");
+ assertEquals( look, nsN );
+
look = ((IContainerSymbol) look).qualifiedLookup("i"); //ok
assertEquals( look, nsN_i );
}
@@ -804,6 +807,8 @@
compUnit.addSymbol(f);
IContainerSymbol lookA = f.lookupNestedNameSpecifier("A");
+ assertEquals( lookA, nsA );
+
ISymbol look = lookA.qualifiedLookup("a");
assertEquals( look, a );
@@ -2938,5 +2943,169 @@
assertEquals( look, init2 );
}
+
+ /**
+ * class A {
+ * void f( int ) {}
+ * void f( ) {}
+ * };
+ * class B : public A {
+ * void f( char ) { }
+ * } b;
+ *
+ * b.f( 1 ); //calls B::f
+ * b.f(); //error
+ * @throws Exception
+ */
+ public void testBug46882() throws Exception{
+ newTable();
+
+ IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_class );
+
+ table.getCompilationUnit().addSymbol( A );
+
+ IParameterizedSymbol f1 = table.newParameterizedSymbol( "f", TypeInfo.t_function );
+ f1.addParameter( TypeInfo.t_int, 0, null, false );
+ A.addSymbol( f1 );
+
+ IParameterizedSymbol f2 = table.newParameterizedSymbol( "f", TypeInfo.t_function );
+ A.addSymbol( f2 );
+
+ IDerivableContainerSymbol B = table.newDerivableContainerSymbol( "B", TypeInfo.t_class );
+ B.addParent( A );
+
+ table.getCompilationUnit().addSymbol( B );
+
+ IParameterizedSymbol f3 = table.newParameterizedSymbol( "f", TypeInfo.t_function );
+ f3.addParameter( TypeInfo.t_char, 0, null, false );
+ B.addSymbol( f3 );
+
+ List params = new LinkedList();
+ params.add( new TypeInfo( TypeInfo.t_int, 0, null ) );
+
+ ISymbol look = B.qualifiedFunctionLookup( "f", params );
+ assertEquals( look, f3 );
+
+ params.clear();
+ look = B.qualifiedFunctionLookup( "f", params );
+ assertEquals( look, null );
+ }
+
+ /**
+ * int aVar;
+ * void foo( ) {
+ * int anotherVar;
+ * a(CTRL+SPACE)
+ * }
+ */
+ public void testPrefixLookup_Unqualified() throws Exception {
+ newTable();
+
+ ISymbol aVar = table.newSymbol( "aVar", TypeInfo.t_int );
+ table.getCompilationUnit().addSymbol( aVar );
+
+ IParameterizedSymbol foo = table.newParameterizedSymbol( "foo", TypeInfo.t_function );
+ table.getCompilationUnit().addSymbol( foo );
+
+ ISymbol anotherVar = table.newSymbol( "anotherVar", TypeInfo.t_int );
+ foo.addSymbol( anotherVar );
+
+ List results = foo.prefixLookup( TypeInfo.t_any, "a", false );
+ assertTrue( results != null );
+ assertEquals( results.size(), 2 );
+
+ assertTrue( results.contains( aVar ) );
+ assertTrue( results.contains( anotherVar ) );
+ }
+
+ /**
+ * int aVar; //not a member of D, not reported
+ *
+ * class D{
+ * int aField;
+ * void aMethod();
+ * };
+ *
+ * D d;
+ * d.a(CTRL+SPACE)
+ */
+ public void testPrefixLookup_Qualified() throws Exception {
+ newTable();
+
+ ISymbol aVar = table.newSymbol( "aVar", TypeInfo.t_int );
+ table.getCompilationUnit().addSymbol( aVar );
+
+ IDerivableContainerSymbol D = table.newDerivableContainerSymbol( "D", TypeInfo.t_class );
+ table.getCompilationUnit().addSymbol( D );
+
+ ISymbol aField = table.newSymbol( "aField", TypeInfo.t_int );
+ IParameterizedSymbol aMethod = table.newParameterizedSymbol( "aMethod", TypeInfo.t_function );
+
+ D.addSymbol( aField );
+ D.addSymbol( aMethod );
+
+ List results = D.prefixLookup( TypeInfo.t_any, "a", true );
+
+ assertTrue( results != null );
+ assertEquals( results.size(), 2 );
+
+ assertTrue( !results.contains( aVar ) );
+ assertTrue( results.contains( aField ) );
+ assertTrue( results.contains( aMethod ) );
+ }
+
+ /**
+ * class A {
+ * int aVar
+ * int anotherVar; //hidden, not reported
+ * void af (); //hidden, not reported
+ * };
+ *
+ * class B : public A {
+ * int anotherVar;
+ * void af( char );
+ * } b;
+ *
+ * b.a(CTRL+SPACE)
+ * @throws Exception
+ */
+ public void testPrefixLookup_Inheritance() throws Exception {
+ newTable();
+
+ IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_class );
+ table.getCompilationUnit().addSymbol( A );
+
+ ISymbol aVar = table.newSymbol( "aVar", TypeInfo.t_int );
+ ISymbol anotherVar1 = table.newSymbol( "anotherVar", TypeInfo.t_int );
+ A.addSymbol( aVar );
+ A.addSymbol( anotherVar1 );
+
+ IParameterizedSymbol af1 = table.newParameterizedSymbol( "af", TypeInfo.t_function );
+ A.addSymbol( af1 );
+
+ IDerivableContainerSymbol B = table.newDerivableContainerSymbol( "B", TypeInfo.t_class );
+ B.addParent( A );
+
+ table.getCompilationUnit().addSymbol( B );
+
+ ISymbol anotherVar2 = table.newSymbol( "anotherVar", TypeInfo.t_int );
+ B.addSymbol( anotherVar2 );
+
+ IParameterizedSymbol af2 = table.newParameterizedSymbol( "af", TypeInfo.t_function );
+ af2.addParameter( TypeInfo.t_char, 0, null, false );
+ B.addSymbol( af2 );
+
+
+ List results = B.prefixLookup( TypeInfo.t_any, "a", true );
+
+ assertTrue( results != null );
+ assertEquals( results.size(), 3 );
+ assertTrue( ! results.contains( anotherVar1 ) );
+ assertTrue( ! results.contains( af1 ) );
+ assertTrue( results.contains( aVar ) );
+ assertTrue( results.contains( anotherVar2 ) );
+ assertTrue( results.contains( af2 ) );
+ }
+
}