From 58562529e5149f91551ff41e04af64d5b146cba4 Mon Sep 17 00:00:00 2001 From: Andrew Niefer Date: Tue, 20 Jul 2004 20:22:07 +0000 Subject: [PATCH] Further transition away from java.util collections in the symbol table --- .../core/parser/tests/ParserTestSuite.java | 2 + .../parser/tests/scanner2/ObjectMapTest.java | 150 ++++++++++++++++++ .../core/parser/pst/ContainerSymbol.java | 43 +++-- .../parser/pst/DerivableContainerSymbol.java | 3 +- .../core/parser/pst/IParameterizedSymbol.java | 4 +- .../core/parser/pst/ParameterizedSymbol.java | 13 +- .../core/parser/pst/ParserSymbolTable.java | 108 ++++++------- .../internal/core/parser/pst/TypeFilter.java | 76 ++++----- .../core/parser/scanner2/HashTable.java | 26 ++- .../core/parser/scanner2/ObjectMap.java | 68 +++++++- .../core/parser/scanner2/ObjectSet.java | 7 + 11 files changed, 363 insertions(+), 137 deletions(-) create mode 100644 core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner2/ObjectMapTest.java diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java index 7191d74c22d..42d444c3c73 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java @@ -17,6 +17,7 @@ import junit.framework.TestSuite; import org.eclipse.cdt.core.model.tests.CModelElementsTests; import org.eclipse.cdt.core.model.tests.StructuralCModelElementsTests; import org.eclipse.cdt.core.parser.ParserFactory; +import org.eclipse.cdt.core.parser.tests.scanner2.ObjectMapTest; import org.eclipse.cdt.core.parser.tests.scanner2.Scanner2Test; /** @@ -53,6 +54,7 @@ public class ParserTestSuite extends TestCase { suite.addTestSuite( CompleteParseASTSymbolIteratorTest.class ); suite.addTestSuite( CompleteParseASTTemplateTest.class ); suite.addTestSuite( StructuralParseTest.class ); + suite.addTestSuite( ObjectMapTest.class ); return suite; } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner2/ObjectMapTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner2/ObjectMapTest.java new file mode 100644 index 00000000000..4147d34aebd --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner2/ObjectMapTest.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/* + * Created on Jul 19, 2004 + */ +package org.eclipse.cdt.core.parser.tests.scanner2; + +import junit.framework.TestCase; + +import org.eclipse.cdt.internal.core.parser.scanner2.ObjectMap; + +/** + * @author aniefer + */ +public class ObjectMapTest extends TestCase { + + static public class HashObject{ + HashObject( int h ){ + hash = h; + } + public int hashCode(){ + return hash; + } + final public int hash; + } + + public void insertContents( ObjectMap map, Object[][] contents ) throws Exception { + for( int i = 0; i < contents.length; i++ ) + map.put( contents[i][0], contents[i][1] ); + } + + public void assertContents( ObjectMap map, Object[][] contents ) throws Exception { + for( int i = 0; i < contents.length; i++ ){ + assertEquals( map.keyAt(i), contents[i][0] ); + assertEquals( map.getAt(i), contents[i][1] ); + assertEquals( map.get(contents[i][0]), contents[i][1] ); + } + assertEquals( map.size(), contents.length ); + } + + public void testSimpleAdd() throws Exception{ + ObjectMap map = new ObjectMap( 2 ); + + Object [][] contents = new Object[][] { {"1", "ob" } }; //$NON-NLS-1$//$NON-NLS-2$ + + insertContents( map, contents ); + assertContents( map, contents ); + + assertEquals( map.size(), 1 ); + assertEquals( map.capacity(), 2 ); + } + + public void testSimpleCollision() throws Exception{ + ObjectMap map = new ObjectMap( 2 ); + + HashObject key1 = new HashObject( 1 ); + HashObject key2 = new HashObject( 1 ); + + Object [][] contents = new Object[][] { {key1, "1" }, //$NON-NLS-1$ + {key2, "2" } }; //$NON-NLS-1$ + + insertContents( map, contents ); + + assertEquals( map.size(), 2 ); + assertEquals( map.capacity(), 2 ); + + assertContents( map, contents ); + } + + public void testResize() throws Exception{ + ObjectMap map = new ObjectMap( 1 ); + + assertEquals( map.size(), 0 ); + assertEquals( map.capacity(), 1 ); + + Object [][] res = new Object [][] { { "0", "o0" }, //$NON-NLS-1$//$NON-NLS-2$ + { "1", "o1" }, //$NON-NLS-1$//$NON-NLS-2$ + { "2", "o2" }, //$NON-NLS-1$//$NON-NLS-2$ + { "3", "o3" }, //$NON-NLS-1$//$NON-NLS-2$ + { "4", "o4" } }; //$NON-NLS-1$//$NON-NLS-2$ + + insertContents( map, res ); + assertEquals( map.capacity(), 8 ); + assertContents( map, res ); + } + + public void testCollisionResize() throws Exception{ + ObjectMap map = new ObjectMap( 1 ); + + assertEquals( map.size(), 0 ); + assertEquals( map.capacity(), 1 ); + + Object [][] res = new Object [][] { { new HashObject(0), "o0" }, //$NON-NLS-1$ + { new HashObject(1), "o1" }, //$NON-NLS-1$ + { new HashObject(0), "o2" }, //$NON-NLS-1$ + { new HashObject(1), "o3" }, //$NON-NLS-1$ + { new HashObject(0), "o4" } }; //$NON-NLS-1$ + + insertContents( map, res ); + assertEquals( map.capacity(), 8 ); + assertContents( map, res ); + } + + public void testReAdd() throws Exception{ + ObjectMap map = new ObjectMap( 1 ); + + assertEquals( map.size(), 0 ); + assertEquals( map.capacity(), 1 ); + + Object [][] res = new Object [][] { { "0", "o0" }, //$NON-NLS-1$ //$NON-NLS-2$ + { "1", "o1" } }; //$NON-NLS-1$ //$NON-NLS-2$ + + insertContents( map, res ); + assertEquals( map.capacity(), 2 ); + assertContents( map, res ); + + res = new Object [][]{ { "0", "o00" }, //$NON-NLS-1$ //$NON-NLS-2$ + { "1", "o01" }, //$NON-NLS-1$ //$NON-NLS-2$ + { "10", "o10" }, //$NON-NLS-1$ //$NON-NLS-2$ + { "11", "o11" } }; //$NON-NLS-1$ //$NON-NLS-2$ + + insertContents( map, res ); + assertContents( map, res ); + } + + public void testResizeResolvesCollision() throws Exception{ + ObjectMap map = new ObjectMap( 2 ); + + Object k1 = new HashObject( 0 ); + Object k2 = new HashObject( 1 ); + Object k3 = new HashObject( 4 ); //collision with 0 in a table capacity 2, but ok in table capacity 4 + + Object [][] con = new Object[][] { { k1, "1" }, //$NON-NLS-1$ + { k2, "2" }, //$NON-NLS-1$ + { k3, "3" } } ; //$NON-NLS-1$ + + insertContents( map, con ); + assertContents( map, con ); + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java index 3ffe56b26c1..5b095570828 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java @@ -19,12 +19,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; -import java.util.Set; import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; @@ -838,18 +836,18 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { LookupData data = new LookupData( prefix ){ public List getParameters() { return params; } public boolean isPrefixLookup(){ return true; } - public Set getAmbiguities(){ return ambiguities; } + public ObjectSet getAmbiguities(){ return ambiguities; } public TypeFilter getFilter() { return typeFilter; } public void addAmbiguity( String n ){ - if( ambiguities == Collections.EMPTY_SET ){ - ambiguities = new HashSet(); + if( ambiguities == ObjectSet.EMPTY_SET ){ + ambiguities = new ObjectSet(2); } - ambiguities.add( n ); + ambiguities.put( n ); } final private List params = paramList; - private Set ambiguities = Collections.EMPTY_SET; + private ObjectSet ambiguities = ObjectSet.EMPTY_SET; final private TypeFilter typeFilter = filter; }; @@ -878,21 +876,21 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { } return null; } - //remove any ambiguous symbols - if( data.getAmbiguities() != null && !data.getAmbiguities().isEmpty() ){ - Iterator iter = data.getAmbiguities().iterator(); - while( iter.hasNext() ){ - data.foundItems.remove( iter.next() ); - } - } List list = new ArrayList(); - Iterator iter = data.foundItems.keySet().iterator(); Object obj = null; + Object key = null; List tempList = null; - while( iter.hasNext() ){ - obj = data.foundItems.get( iter.next() ); + int size = data.foundItems.size(); + for( int i = 0; i < size; i++ ){ + key = data.foundItems.keyAt( i ); + + //skip ambiguous symbols + if( data.getAmbiguities() != null && data.getAmbiguities().containsKey( key ) ) + continue; + + obj = data.foundItems.get( key ); if( obj instanceof List ){ //a list must be all functions? @@ -1031,7 +1029,7 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { protected class ContentsIterator implements Iterator { final Iterator internalIterator; - Set alreadyReturned = new HashSet(); + ObjectSet alreadyReturned = new ObjectSet( 2 ); public ContentsIterator( Iterator iter ){ internalIterator = iter; @@ -1046,14 +1044,14 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { return false; while( internalIterator.hasNext() ){ IExtensibleSymbol extensible = (IExtensibleSymbol) internalIterator.next(); - if( !alreadyReturned.contains( extensible ) ){ + if( !alreadyReturned.containsKey( extensible ) ){ if( extensible instanceof ISymbol ){ ISymbol symbol = (ISymbol) extensible; ISymbol forward = symbol.getForwardSymbol(); if( symbol.isForwardDeclaration() && forward != null && forward.getContainingSymbol() == ContainerSymbol.this ) { - alreadyReturned.add( forward ); + alreadyReturned.put( forward ); next = forward; return true; } @@ -1077,13 +1075,13 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { while( internalIterator.hasNext() ){ extensible = (IExtensibleSymbol) internalIterator.next(); - if( !alreadyReturned.contains( extensible ) ){ + if( !alreadyReturned.containsKey( extensible ) ){ if( extensible instanceof ISymbol ){ ISymbol symbol = (ISymbol) extensible; if( symbol.isForwardDeclaration() && symbol.getForwardSymbol() != null && symbol.getForwardSymbol().getContainingSymbol() == ContainerSymbol.this ) { - alreadyReturned.add( symbol.getForwardSymbol() ); + alreadyReturned.put( symbol.getForwardSymbol() ); return symbol.getForwardSymbol(); } } else if( extensible instanceof IUsingDeclarationSymbol ){ @@ -1172,6 +1170,7 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { // private final IUsingDirectiveSymbol _directive; // } + static public final SymbolTableComparator comparator = new SymbolTableComparator(); static protected class SymbolTableComparator implements Comparator{ static final private Collator collator = Collator.getInstance(); static { collator.setStrength( Collator.PRIMARY ); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java index 5eb5045c8b5..c3424162e00 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java @@ -22,6 +22,7 @@ import java.util.Map; import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTable.LookupData; +import org.eclipse.cdt.internal.core.parser.scanner2.ObjectMap; /** * @author aniefer @@ -284,7 +285,7 @@ public class DerivableContainerSymbol extends ContainerSymbol implements IDeriva LookupData data = new LookupData( ParserSymbolTable.THIS ); try { - Map map = ParserSymbolTable.lookupInContained( data, obj ); + ObjectMap map = ParserSymbolTable.lookupInContained( data, obj ); foundThis = ( map != null ) ? map.containsKey( data.name ) : false; } catch (ParserSymbolTableException e) { return false; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IParameterizedSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IParameterizedSymbol.java index 64b1181a3d6..444f534d797 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IParameterizedSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IParameterizedSymbol.java @@ -17,8 +17,8 @@ package org.eclipse.cdt.internal.core.parser.pst; import java.util.List; -import java.util.Map; +import org.eclipse.cdt.internal.core.parser.scanner2.ObjectMap; /** * @author aniefer @@ -32,7 +32,7 @@ public interface IParameterizedSymbol extends IContainerSymbol { public void addParameter( ITypeInfo.eType type, int info, ITypeInfo.PtrOp ptrOp, boolean hasDefault ); public void addParameter( ISymbol typeSymbol, int info, ITypeInfo.PtrOp ptrOp, boolean hasDefault ); - public Map getParameterMap(); + public ObjectMap getParameterMap(); public List getParameterList(); //public void setParameterList( List list ); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java index ff79cbd5805..44835c1171f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java @@ -15,11 +15,12 @@ package org.eclipse.cdt.internal.core.parser.pst; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; +import org.eclipse.cdt.internal.core.parser.scanner2.ObjectMap; + /** * @author aniefer * @@ -40,7 +41,7 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz ParameterizedSymbol copy = (ParameterizedSymbol)super.clone(); copy._parameterList = ( _parameterList != Collections.EMPTY_LIST ) ? (List) ((ArrayList)_parameterList).clone() : _parameterList; - copy._parameterMap = ( _parameterMap != Collections.EMPTY_MAP ) ? (Map) ((HashMap) _parameterMap).clone() : _parameterMap; + copy._parameterMap = ( _parameterMap != ObjectMap.EMPTY_MAP ) ? (ObjectMap) _parameterMap.clone() : _parameterMap; return copy; } @@ -123,8 +124,8 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz String name = param.getName(); if( name != null && !name.equals(ParserSymbolTable.EMPTY_NAME) ) { - if( _parameterMap == Collections.EMPTY_MAP ){ - _parameterMap = new HashMap( ); + if( _parameterMap == ObjectMap.EMPTY_MAP ){ + _parameterMap = new ObjectMap( 2 ); } if( !_parameterMap.containsKey( name ) ) @@ -165,7 +166,7 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#getParameterMap() */ - public Map getParameterMap(){ + public ObjectMap getParameterMap(){ return _parameterMap; } @@ -312,7 +313,7 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz private List _parameterList = Collections.EMPTY_LIST; //have my cake - private Map _parameterMap = Collections.EMPTY_MAP; //and eat it too + private ObjectMap _parameterMap = ObjectMap.EMPTY_MAP; //and eat it too private ISymbol _returnType; private boolean _hasVarArgs = false; //whether or not this function has variable arguments } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java index 134f9159e32..4e9df0bcd72 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java @@ -15,14 +15,10 @@ package org.eclipse.cdt.internal.core.parser.pst; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; -import java.util.Set; -import java.util.TreeMap; import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ParserMode; @@ -30,8 +26,8 @@ import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; import org.eclipse.cdt.core.parser.ast.IASTMember; import org.eclipse.cdt.core.parser.ast.IASTNode; import org.eclipse.cdt.internal.core.parser.pst.IDerivableContainerSymbol.IParentSymbol; -import org.eclipse.cdt.internal.core.parser.scanner2.ObjectSet; import org.eclipse.cdt.internal.core.parser.scanner2.ObjectMap; +import org.eclipse.cdt.internal.core.parser.scanner2.ObjectSet; /** * @author aniefer @@ -127,7 +123,7 @@ public class ParserSymbolTable { ArrayList transitives = null; //list of transitive using directives //if this name define in this scope? - Map map = null; + ObjectMap map = null; if( !data.usingDirectivesOnly ){ map = lookupInContained( data, inSymbol ); if( data.foundItems == null || data.foundItems.isEmpty() ){ @@ -251,7 +247,7 @@ public class ParserSymbolTable { if( !data.visited.containsKey( temp ) ){ data.visited.put( temp ); - Map map = lookupInContained( data, temp ); + ObjectMap map = lookupInContained( data, temp ); foundSomething = ( map != null && !map.isEmpty() ); if( foundSomething ){ if( data.foundItems == null ) @@ -278,15 +274,15 @@ public class ParserSymbolTable { * @param map * @param map2 */ - private static void mergeResults( LookupData data, Map resultMap, Map map ) throws ParserSymbolTableException { + private static void mergeResults( LookupData data, ObjectMap resultMap, ObjectMap 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(); + int size = map.size(); + for( int i = 0; i < size; i++ ){ + key = map.keyAt( i ); if( resultMap.containsKey( key ) ){ List list = new ArrayList(); Object obj = resultMap.get( key ); @@ -313,8 +309,8 @@ public class ParserSymbolTable { * * Look for data.name in our collection _containedDeclarations */ - protected static Map lookupInContained( LookupData data, IContainerSymbol lookIn ) throws ParserSymbolTableException{ - Map found = null; + protected static ObjectMap lookupInContained( LookupData data, IContainerSymbol lookIn ) throws ParserSymbolTableException{ + ObjectMap found = null; Object obj = null; @@ -327,8 +323,8 @@ public class ParserSymbolTable { int numKeys = -1; int idx = 0; - if( data.isPrefixLookup() && declarations != Collections.EMPTY_MAP ){ - numKeys = declarations.size();//iterator = declarations.keySet().iterator(); + if( data.isPrefixLookup() && declarations != ObjectMap.EMPTY_MAP ){ + numKeys = declarations.size(); } String name = ( numKeys > 0 ) ? (String) declarations.keyAt( idx++ ) : data.name; @@ -341,10 +337,7 @@ public class ParserSymbolTable { if( obj != null ){ if( found == null ){ - if( data.isPrefixLookup() ) - found = new TreeMap( new ContainerSymbol.SymbolTableComparator() ); - else - found = new LinkedHashMap(); + found = new ObjectMap( 2 ); } found.put( name, obj ); } @@ -356,7 +349,7 @@ public class ParserSymbolTable { name = null; } if( found != null && data.isPrefixLookup() ) - found = new LinkedHashMap( found ); + found.sort( ContainerSymbol.comparator ); if( found != null && !data.isPrefixLookup() ){ return found; @@ -386,7 +379,7 @@ public class ParserSymbolTable { * @param found * @throws ParserSymbolTableException */ - private static Map lookupInParameters(LookupData data, IContainerSymbol lookIn, Map found) throws ParserSymbolTableException { + private static ObjectMap lookupInParameters(LookupData data, IContainerSymbol lookIn, ObjectMap found) throws ParserSymbolTableException { Object obj; Iterator iterator; String name; @@ -402,50 +395,50 @@ public class ParserSymbolTable { obj = collectSymbol( data, symbol ); if( obj != null ){ if( found == null ){ - if( data.isPrefixLookup() ) - found = new TreeMap( new ContainerSymbol.SymbolTableComparator() ); - else - found = new LinkedHashMap(); + found = new ObjectMap(2); } found.put( symbol.getName(), obj ); } } } - return ( found instanceof TreeMap ) ? new LinkedHashMap( found ) : found; + if( found != null && data.isPrefixLookup() ) + found.sort( ContainerSymbol.comparator ); + + return found; } } - Map parameters = ((IParameterizedSymbol)lookIn).getParameterMap(); - if( parameters != Collections.EMPTY_MAP ){ - iterator = null; - if( data.isPrefixLookup() ){ - iterator = parameters.keySet().iterator(); - } + ObjectMap parameters = ((IParameterizedSymbol)lookIn).getParameterMap(); + if( parameters != ObjectMap.EMPTY_MAP ){ + int numKeys = -1; + int idx = 0; - name = ( iterator != null && iterator.hasNext() ) ? (String) iterator.next() : data.name; + if( data.isPrefixLookup() && parameters != ObjectMap.EMPTY_MAP ){ + numKeys = parameters.size(); + } + name = ( numKeys > 0 ) ? (String) parameters.keyAt( idx++ ) : data.name; while( name != null ){ if( nameMatches( data, name ) ){ obj = parameters.get( name ); obj = collectSymbol( data, obj ); if( obj != null ){ if( found == null ){ - if( data.isPrefixLookup() ) - found = new TreeMap( new ContainerSymbol.SymbolTableComparator() ); - else - found = new LinkedHashMap(); + found = new ObjectMap( 2 ); } found.put( name, obj ); } } - if( iterator != null && iterator.hasNext() ){ - name = (String) iterator.next(); - } else { + if( idx < numKeys ) + name = (String) parameters.keyAt( idx++ ); + else name = null; - } } } - return ( found instanceof TreeMap ) ? new LinkedHashMap( found ) : found; + if( found != null && data.isPrefixLookup() ) + found.sort( ContainerSymbol.comparator ); + + return found; } private static boolean nameMatches( LookupData data, String name ){ @@ -630,7 +623,7 @@ public class ParserSymbolTable { * @return Declaration * @throws ParserSymbolTableException */ - private static Map lookupInParents( LookupData data, ISymbol lookIn ) throws ParserSymbolTableException{ + private static ObjectMap lookupInParents( LookupData data, ISymbol lookIn ) throws ParserSymbolTableException{ IDerivableContainerSymbol container = null; if( lookIn instanceof IDerivableContainerSymbol ){ @@ -641,9 +634,9 @@ public class ParserSymbolTable { List scopes = container.getParents(); - Map temp = null; - Map symbol = null; - Map inherited = null; + ObjectMap temp = null; + ObjectMap symbol = null; + ObjectMap inherited = null; IDerivableContainerSymbol.IParentSymbol wrapper = null; @@ -701,10 +694,11 @@ public class ParserSymbolTable { if( symbol == null || symbol.isEmpty() ){ symbol = temp; } else if ( temp != null && !temp.isEmpty() ) { - Iterator iter = temp.keySet().iterator(); Object key = null; - while( iter.hasNext() ){ - key = iter.next(); + int tempSize = temp.size(); + for( int ii = 0; ii < tempSize; ii++ ){ + key = temp.keyAt( ii ); + if( symbol.containsKey( key ) ){ Object obj = symbol.get( key ); List objList = ( obj instanceof List ) ? (List)obj : null; @@ -770,15 +764,15 @@ public class ParserSymbolTable { * @param map * @throws ParserSymbolTableException */ - private static void mergeInheritedResults( Map resultMap, Map map ){ + private static void mergeInheritedResults( ObjectMap resultMap, ObjectMap map ){ if( resultMap == null || map == null || map.isEmpty() ){ return; } - Iterator keyIterator = map.keySet().iterator(); Object key = null; - while( keyIterator.hasNext() ){ - key = keyIterator.next(); + int size = map.size(); + for( int i = 0; i < size; i++ ){ + key = map.keyAt( i ); if( !resultMap.containsKey( key ) ){ resultMap.put( key, map.get( key ) ); } @@ -1400,7 +1394,7 @@ public class ParserSymbolTable { list = new ArrayList(4); list.add( temp ); if( data.usingDirectives == null ){ - data.usingDirectives = new HashMap(); + data.usingDirectives = new ObjectMap(2); } data.usingDirectives.put( enclosing, list ); } else { @@ -2224,7 +2218,7 @@ public class ParserSymbolTable { protected static final TypeFilter FUNCTION_FILTER = new TypeFilter( ITypeInfo.t_function ); public String name; - public Map usingDirectives; + public ObjectMap usingDirectives; public ObjectSet visited = new ObjectSet(0); //used to ensure we don't visit things more than once public ObjectSet inheritanceChain; //used to detect circular inheritance public ISymbol templateMember; //to assit with template member defs @@ -2236,7 +2230,7 @@ public class ParserSymbolTable { public boolean exactFunctionsOnly = false; public boolean returnInvisibleSymbols = false; - public Map foundItems = null; + public ObjectMap foundItems = null; public LookupData( String n ){ name = n; @@ -2245,7 +2239,7 @@ public class ParserSymbolTable { //the following function are optionally overloaded by anonymous classes deriving from //this LookupData public boolean isPrefixLookup(){ return false;} //prefix lookup - public Set getAmbiguities() { return null; } + public ObjectSet getAmbiguities() { return null; } public void addAmbiguity(String n ) { /*nothing*/ } public List getParameters() { return null; } //parameter info for resolving functions public ObjectSet getAssociated() { return null; } //associated namespaces for argument dependant lookup diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TypeFilter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TypeFilter.java index de74acfe4a0..1a634c85e6f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TypeFilter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TypeFilter.java @@ -11,10 +11,8 @@ package org.eclipse.cdt.internal.core.parser.pst; -import java.util.HashSet; -import java.util.Set; - import org.eclipse.cdt.core.parser.ast.IASTNode.LookupKind; +import org.eclipse.cdt.internal.core.parser.scanner2.ObjectSet; /** * @author aniefer @@ -24,43 +22,39 @@ public class TypeFilter { public TypeFilter(){ } - public TypeFilter( Set types ){ - acceptedTypes.addAll( types ); - } - public TypeFilter( ITypeInfo.eType type ){ - acceptedTypes.add( type ); + acceptedTypes.put( type ); } public TypeFilter( LookupKind kind ){ - acceptedKinds.add( kind ); + acceptedKinds.put( kind ); populatedAcceptedTypes( kind ); } public void addAcceptedType( ITypeInfo.eType type ){ - acceptedTypes.add( type ); + acceptedTypes.put( type ); } public void addAcceptedType( LookupKind kind ) { populatedAcceptedTypes( kind ); - acceptedKinds.add( kind ); + acceptedKinds.put( kind ); } public boolean willAccept( ITypeInfo.eType type ){ - return( acceptedTypes.contains( ITypeInfo.t_any ) || - acceptedTypes.contains( type ) ); + return( acceptedTypes.containsKey( ITypeInfo.t_any ) || + acceptedTypes.containsKey( type ) ); } public boolean shouldAccept( ISymbol symbol ){ return shouldAccept( symbol, symbol.getTypeInfo() ); } public boolean shouldAccept( ISymbol symbol, ITypeInfo typeInfo ){ - if( acceptedTypes.contains( ITypeInfo.t_any ) ){ + if( acceptedTypes.containsKey( ITypeInfo.t_any ) ){ return true; } if( acceptedKinds.isEmpty() ){ - return acceptedTypes.contains( typeInfo.getType() ); + return acceptedTypes.containsKey( typeInfo.getType() ); } IContainerSymbol container = symbol.getContainingSymbol(); @@ -71,16 +65,16 @@ public class TypeFilter { if( typeInfo.isType( ITypeInfo.t_function ) ) { - if( ( acceptedKinds.contains( LookupKind.FUNCTIONS ) && !symbolIsMember ) || - ( acceptedKinds.contains( LookupKind.METHODS ) && symbolIsMember ) ) + if( ( acceptedKinds.containsKey( LookupKind.FUNCTIONS ) && !symbolIsMember ) || + ( acceptedKinds.containsKey( LookupKind.METHODS ) && symbolIsMember ) ) { return true; } return false; } else if ( typeInfo.isType( ITypeInfo.t_type ) && typeInfo.checkBit( ITypeInfo.isTypedef ) ){ - if( acceptedKinds.contains( LookupKind.TYPEDEFS ) || - acceptedKinds.contains( LookupKind.TYPES ) ) + if( acceptedKinds.containsKey( LookupKind.TYPEDEFS ) || + acceptedKinds.containsKey( LookupKind.TYPES ) ) { return true; } @@ -88,9 +82,9 @@ public class TypeFilter { } else if ( typeInfo.isType( ITypeInfo.t_type ) || typeInfo.isType( ITypeInfo.t__Bool, ITypeInfo.t_void ) ) { - if( ( acceptedKinds.contains( LookupKind.VARIABLES ) && !symbolIsMember && !symbolIsLocal ) || - ( acceptedKinds.contains( LookupKind.LOCAL_VARIABLES ) && !symbolIsMember && symbolIsLocal ) || - ( acceptedKinds.contains( LookupKind.FIELDS ) && symbolIsMember ) ) + if( ( acceptedKinds.containsKey( LookupKind.VARIABLES ) && !symbolIsMember && !symbolIsLocal ) || + ( acceptedKinds.containsKey( LookupKind.LOCAL_VARIABLES ) && !symbolIsMember && symbolIsLocal ) || + ( acceptedKinds.containsKey( LookupKind.FIELDS ) && symbolIsMember ) ) { return true; } @@ -98,7 +92,7 @@ public class TypeFilter { } else { - return acceptedTypes.contains( typeInfo.getType() ); + return acceptedTypes.containsKey( typeInfo.getType() ); } } @@ -106,22 +100,22 @@ public class TypeFilter { * @param lookupKind */ private void populatedAcceptedTypes(LookupKind kind) { - if ( kind == LookupKind.ALL ) { acceptedTypes.add( ITypeInfo.t_any ); } - else if ( kind == LookupKind.STRUCTURES ) { acceptedTypes.add( ITypeInfo.t_class ); - acceptedTypes.add( ITypeInfo.t_struct ); - acceptedTypes.add( ITypeInfo.t_union ); } - else if ( kind == LookupKind.STRUCTS ) { acceptedTypes.add( ITypeInfo.t_struct ); } - else if ( kind == LookupKind.UNIONS ) { acceptedTypes.add( ITypeInfo.t_union ); } - else if ( kind == LookupKind.CLASSES ) { acceptedTypes.add( ITypeInfo.t_class ); } - else if ( kind == LookupKind.CONSTRUCTORS ){ acceptedTypes.add( ITypeInfo.t_constructor ); } - else if ( kind == LookupKind.NAMESPACES ) { acceptedTypes.add( ITypeInfo.t_namespace ); } - else if ( kind == LookupKind.ENUMERATIONS ){ acceptedTypes.add( ITypeInfo.t_enumeration ); } - else if ( kind == LookupKind.ENUMERATORS ) { acceptedTypes.add( ITypeInfo.t_enumerator ); } -// else if ( kind == LookupKind.TYPEDEFS ) { acceptedTypes.add( TypeInfo.t_type ); } - else if ( kind == LookupKind.TYPES ) { acceptedTypes.add( ITypeInfo.t_class ); - acceptedTypes.add( ITypeInfo.t_struct ); - acceptedTypes.add( ITypeInfo.t_union ); - acceptedTypes.add( ITypeInfo.t_enumeration ); } + if ( kind == LookupKind.ALL ) { acceptedTypes.put( ITypeInfo.t_any ); } + else if ( kind == LookupKind.STRUCTURES ) { acceptedTypes.put( ITypeInfo.t_class ); + acceptedTypes.put( ITypeInfo.t_struct ); + acceptedTypes.put( ITypeInfo.t_union ); } + else if ( kind == LookupKind.STRUCTS ) { acceptedTypes.put( ITypeInfo.t_struct ); } + else if ( kind == LookupKind.UNIONS ) { acceptedTypes.put( ITypeInfo.t_union ); } + else if ( kind == LookupKind.CLASSES ) { acceptedTypes.put( ITypeInfo.t_class ); } + else if ( kind == LookupKind.CONSTRUCTORS ){ acceptedTypes.put( ITypeInfo.t_constructor ); } + else if ( kind == LookupKind.NAMESPACES ) { acceptedTypes.put( ITypeInfo.t_namespace ); } + else if ( kind == LookupKind.ENUMERATIONS ){ acceptedTypes.put( ITypeInfo.t_enumeration ); } + else if ( kind == LookupKind.ENUMERATORS ) { acceptedTypes.put( ITypeInfo.t_enumerator ); } +// else if ( kind == LookupKind.TYPEDEFS ) { acceptedTypes.put( TypeInfo.t_type ); } + else if ( kind == LookupKind.TYPES ) { acceptedTypes.put( ITypeInfo.t_class ); + acceptedTypes.put( ITypeInfo.t_struct ); + acceptedTypes.put( ITypeInfo.t_union ); + acceptedTypes.put( ITypeInfo.t_enumeration ); } } @@ -132,8 +126,8 @@ public class TypeFilter { return lookingInThis; } - private Set acceptedTypes = new HashSet(); - private Set acceptedKinds = new HashSet(); + private ObjectSet acceptedTypes = new ObjectSet(2); + private ObjectSet acceptedKinds = new ObjectSet(2); private boolean lookingInThis = false; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/HashTable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/HashTable.java index c81c9520a28..7cc6d50c31d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/HashTable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/HashTable.java @@ -21,7 +21,7 @@ package org.eclipse.cdt.internal.core.parser.scanner2; */ public abstract class HashTable implements Cloneable{ - private Object[] keyTable; + protected Object[] keyTable; private int[] hashTable; private int[] nextTable; @@ -81,7 +81,7 @@ public abstract class HashTable implements Cloneable{ currEntry = -1; } - protected int capacity() { + public int capacity() { return keyTable.length; } @@ -112,9 +112,21 @@ public abstract class HashTable implements Cloneable{ System.arraycopy(oldKeyTable, 0, keyTable, 0, oldKeyTable.length); // Need to rehash everything - hashTable = new int[size * 2]; - nextTable = new int[size]; - for (int i = 0; i < oldKeyTable.length; ++i) { + rehash( oldKeyTable.length, true ); + } + + protected void rehash( int n, boolean reallocate ){ + if( reallocate ){ + hashTable = new int[ keyTable.length * 2 ]; + nextTable = new int[ keyTable.length ]; + } else { + for( int i = 0; i < keyTable.length; i++ ){ + hashTable[2*i] = 0; + hashTable[2*i+1] = 0; + nextTable[i] = 0; + } + } + for (int i = 0; i < n; ++i) { insert(i); } } @@ -184,11 +196,11 @@ public abstract class HashTable implements Cloneable{ // adjust hash and next entries for things that moved for (int j = 0; j < hashTable.length; ++j) - if (hashTable[j] > i) + if (hashTable[j] > i + 1) --hashTable[j]; for (int j = 0; j < nextTable.length; ++j) - if (nextTable[j] > i) + if (nextTable[j] > i + 1) --nextTable[j]; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectMap.java index 8d568b5478b..d5938935e3a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectMap.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectMap.java @@ -15,6 +15,7 @@ */ package org.eclipse.cdt.internal.core.parser.scanner2; +import java.util.Comparator; /** * @author aniefer @@ -76,5 +77,70 @@ public class ObjectMap extends HashTable{ return null; return get( keyAt( i ) ); - } + } + + public boolean isEmpty(){ + return currEntry == -1; + } + + public Object remove( Object key ) { + int i = lookup(key); + if (i < 0) + return null; + + Object value = valueTable[i]; + removeEntry(i); + + return value; + } + + protected void removeEntry(int i) { + // Remove the entry from the valueTable, shifting everything over if necessary + if (i < currEntry) + System.arraycopy(valueTable, i + 1, valueTable, i, currEntry - i); + valueTable[currEntry] = null; + + // Make sure you remove the value before calling super where currEntry will change + super.removeEntry(i); + } + + public void sort( Comparator c ) { + if( size() > 1 ){ + quickSort( c, 0, size() - 1 ); + + rehash( size(), false ); + } + } + + private void quickSort( Comparator c, int p, int r ){ + if( p < r ){ + int q = partition( c, p, r ); + if( p < q ) quickSort( c, p, q ); + if( ++q < r ) quickSort( c, q, r ); + } + } + private int partition( Comparator c, int p, int r ){ + Object x = keyTable[ p ]; + Object temp = null; + int i = p; + int j = r; + + while( true ){ + while( c.compare( keyTable[ j ], x ) > 0 ){ j--; } + if( i < j ) + while( c.compare( keyTable[ i ], x ) < 0 ){ i++; } + + if( i < j ){ + temp = keyTable[j]; + keyTable[j] = keyTable[i]; + keyTable[i] = temp; + + temp = valueTable[j]; + valueTable[j] = valueTable[i]; + valueTable[i] = temp; + } else { + return j; + } + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectSet.java index e7eb2c3b50e..f4f9582cc6d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectSet.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner2/ObjectSet.java @@ -74,4 +74,11 @@ public class ObjectSet extends HashTable{ removeEntry(i); return true; } + + /** + * @return + */ + public boolean isEmpty() { + return currEntry == -1; + } }