From 57d668240ad64ebccdcae6a8af0025301b0110be Mon Sep 17 00:00:00 2001 From: John Camelon Date: Thu, 15 Jan 2004 23:06:58 +0000 Subject: [PATCH] Patch for Andrew Niefer. For normal lookups in the symbol table, a HashMap is faster than the tree map, but for prefix lookups the TreeMap is faster. So we are now using the HashMap for normal parses, and we use the TreeMap in the parse mode used by content assist. Note that with these changes the results returned by the IASTNode.lookup function used by content assist are now in predictable order: they are first sorted in the order of the scopes visited during the lookup and then they are sorted alphabetically Core: Modified symbol table constructor to take a ParseMode as a parameter. Modified symbol table to use a TreeMap instead of HashMap when ParseMode is COMPLETION_PARSE. Modified ASTNode.lookup to throw ASTNotImplementedException if called when ParseMode is not CONTEXTUAL_PARSE. Core.tests: Moved testBug48307_FriendFunction_1 & testBug48307_FriendFunction_2 to ContextualParseTest. Updated ContextualParseTest now that the order of prefix lookup results is predictable. UI: Updated CompletionEngine to catch ASTNotImplementedException from IASTNode.lookup. --- core/org.eclipse.cdt.core.tests/ChangeLog | 4 ++ .../parser/tests/CompleteParseASTTest.java | 46 ------------- .../parser/tests/ContextualParseTest.java | 68 +++++++++++++++---- .../parser/tests/ParserSymbolTableTest.java | 17 ++--- .../parser/ChangeLog-parser | 5 ++ .../cdt/core/parser/ParserFactory.java | 2 +- .../eclipse/cdt/core/parser/ast/IASTNode.java | 2 +- .../core/parser/ContextualParser.java | 2 +- .../core/parser/ast/complete/ASTNode.java | 9 ++- .../ast/complete/CompleteParseASTFactory.java | 5 +- .../core/parser/pst/ContainerSymbol.java | 40 ++++++++--- .../core/parser/pst/ParameterizedSymbol.java | 15 +++- .../core/parser/pst/ParserSymbolTable.java | 36 ++++++++-- core/org.eclipse.cdt.ui/ChangeLog | 3 + .../text/contentassist/CompletionEngine.java | 5 ++ 15 files changed, 170 insertions(+), 89 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/ChangeLog b/core/org.eclipse.cdt.core.tests/ChangeLog index 0240bc89fa2..f0ac085fc73 100644 --- a/core/org.eclipse.cdt.core.tests/ChangeLog +++ b/core/org.eclipse.cdt.core.tests/ChangeLog @@ -1,3 +1,7 @@ +2004-01-15 Andrew Niefer + Moved testBug48307_FriendFunction_1 & testBug48307_FriendFunction_2 to ContextualParseTest + Updated ContextualParseTest now that the order of prefix lookup results is predictable. + 2004-01-15 Hoda Amer Moved Content Assist testing to the UI.tests plugin diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java index adb77bc34d6..3ec47457d11 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java @@ -32,7 +32,6 @@ import org.eclipse.cdt.core.parser.ast.IASTFunction; import org.eclipse.cdt.core.parser.ast.IASTLinkageSpecification; import org.eclipse.cdt.core.parser.ast.IASTMethod; import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition; -import org.eclipse.cdt.core.parser.ast.IASTNode; import org.eclipse.cdt.core.parser.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.parser.ast.IASTReference; import org.eclipse.cdt.core.parser.ast.IASTScope; @@ -42,7 +41,6 @@ import org.eclipse.cdt.core.parser.ast.IASTUsingDeclaration; import org.eclipse.cdt.core.parser.ast.IASTUsingDirective; import org.eclipse.cdt.core.parser.ast.IASTVariable; import org.eclipse.cdt.core.parser.ast.IASTVariableReference; -import org.eclipse.cdt.core.parser.ast.IASTNode.ILookupResult; import org.eclipse.cdt.internal.core.parser.ParserException; @@ -1160,48 +1158,4 @@ public class CompleteParseASTTest extends CompleteParseBaseTest assertTrue( foo.takesVarArgs() ); assertAllReferences( 1, createTaskList( new Task( foo ) ) ); } - - public void testBug48307_FriendFunction_1() throws Exception { - StringWriter writer = new StringWriter(); - writer.write( "class A{ public : void foo(); }; " ); - writer.write( "class B{ "); - writer.write( " private : int aPrivate;" ); - writer.write( " friend void A::foo(); "); - writer.write( "};" ); - writer.write( "void A::foo(){}" ); - - Iterator i = parse( writer.toString() ).getDeclarations(); - - IASTClassSpecifier classA = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier(); - IASTClassSpecifier classB = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier(); - IASTMethod method = (IASTMethod) i.next(); - - ILookupResult result = method.lookup( "a", new IASTNode.LookupKind[] { IASTNode.LookupKind.ALL }, classB ); - - assertEquals( result.getResultsSize(), 1 ); - IASTField field = (IASTField) result.getNodes().next(); - assertEquals( field.getName(), "aPrivate" ); - } - - public void testBug48307_FriendFunction_2() throws Exception { - StringWriter writer = new StringWriter(); - writer.write( "void global();" ); - writer.write( "class B{ "); - writer.write( " private : int aPrivate;" ); - writer.write( " friend void global(); "); - writer.write( "};" ); - writer.write( "void global(){}" ); - - Iterator i = parse( writer.toString() ).getDeclarations(); - - IASTFunction functionDecl = (IASTFunction) i.next(); - IASTClassSpecifier classB = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier(); - IASTFunction functionDef = (IASTFunction) i.next(); - - ILookupResult result = functionDef.lookup( "a", new IASTNode.LookupKind[] { IASTNode.LookupKind.ALL }, classB ); - - assertEquals( result.getResultsSize(), 1 ); - IASTField field = (IASTField) result.getNodes().next(); - assertEquals( field.getName(), "aPrivate" ); - } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ContextualParseTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ContextualParseTest.java index 1ffe905bb4c..c656261ad53 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ContextualParseTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ContextualParseTest.java @@ -26,8 +26,8 @@ import org.eclipse.cdt.core.parser.ast.IASTMethod; import org.eclipse.cdt.core.parser.ast.IASTNode; import org.eclipse.cdt.core.parser.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.parser.ast.IASTVariable; -import org.eclipse.cdt.core.parser.ast.IASTNode.LookupKind; import org.eclipse.cdt.core.parser.ast.IASTNode.ILookupResult; +import org.eclipse.cdt.core.parser.ast.IASTNode.LookupKind; import org.eclipse.cdt.internal.core.parser.ParserLogService; /** @@ -150,12 +150,14 @@ public class ContextualParseTest extends CompleteParseBaseTest { Iterator iter = result.getNodes(); IASTVariable anotherVar = (IASTVariable) iter.next(); + + IASTVariable aVar = (IASTVariable) iter.next(); + if( i != 0 ) { IASTFunction foo = (IASTFunction) iter.next(); assertEquals( foo.getName(), "foo"); } - IASTVariable aVar = (IASTVariable) iter.next(); assertFalse( iter.hasNext() ); assertEquals( anotherVar.getName(), "anotherVar" ); @@ -198,18 +200,8 @@ public class ContextualParseTest extends CompleteParseBaseTest { Iterator iter = result.getNodes(); - IASTMethod aMethod = null; - IASTField aField = null; - - //we can't currently predict the order in this case - for( int i = 1; i <= 2; i++ ){ - IASTNode astNode = (IASTNode) iter.next(); - if( astNode instanceof IASTMethod ){ - aMethod = (IASTMethod) astNode; - } else{ - aField = (IASTField) astNode; - } - } + IASTField aField = (IASTField) iter.next(); + IASTMethod aMethod = (IASTMethod) iter.next(); assertFalse( iter.hasNext() ); @@ -562,4 +554,52 @@ public class ContextualParseTest extends CompleteParseBaseTest { ILookupResult result = inquestion.lookup( "a", kinds, null ); assertEquals(result.getResultsSize(), 3 ); } + + public void testBug48307_FriendFunction_1() throws Exception { + StringWriter writer = new StringWriter(); + writer.write( "class A{ public : void foo(); }; " ); + writer.write( "class B{ "); + writer.write( " private : int aPrivate;" ); + writer.write( " friend void A::foo(); "); + writer.write( "};" ); + writer.write( "void A::foo(){" ); + writer.write( " B b;"); + writer.write( " b.aP" ); + + String code = writer.toString(); + int index = code.indexOf( "b.aP" ); + IASTCompletionNode node = parse( code, index + 4 ); + + ILookupResult result = node.getCompletionScope().lookup( node.getCompletionPrefix(), + new IASTNode.LookupKind[] { IASTNode.LookupKind.ALL }, + node.getCompletionContext() ); + + assertEquals( result.getResultsSize(), 1 ); + IASTField field = (IASTField) result.getNodes().next(); + assertEquals( field.getName(), "aPrivate" ); + } + + public void testBug48307_FriendFunction_2() throws Exception { + StringWriter writer = new StringWriter(); + writer.write( "void global();" ); + writer.write( "class B{ "); + writer.write( " private : int aPrivate;" ); + writer.write( " friend void global(); "); + writer.write( "};" ); + writer.write( "void global(){" ); + writer.write( " B b;"); + writer.write( " b.aP" ); + + String code = writer.toString(); + int index = code.indexOf( "b.aP" ); + IASTCompletionNode node = parse( code, index + 4 ); + + ILookupResult result = node.getCompletionScope().lookup( node.getCompletionPrefix(), + new IASTNode.LookupKind[] { IASTNode.LookupKind.ALL }, + node.getCompletionContext() ); + + assertEquals( result.getResultsSize(), 1 ); + IASTField field = (IASTField) result.getNodes().next(); + assertEquals( field.getName(), "aPrivate" ); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java index 130a3c71980..bacf4d6e29f 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java @@ -20,6 +20,7 @@ import java.util.Map; import junit.framework.TestCase; import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; import org.eclipse.cdt.core.parser.ast.ASTClassKind; import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier; @@ -66,11 +67,11 @@ public class ParserSymbolTableTest extends TestCase { } public ParserSymbolTable newTable(){ - return newTable( ParserLanguage.CPP ); + return newTable( ParserLanguage.CPP, ParserMode.COMPLETE_PARSE ); } - public ParserSymbolTable newTable( ParserLanguage language ){ - table = new ParserSymbolTable( language ); + public ParserSymbolTable newTable( ParserLanguage language, ParserMode mode ){ + table = new ParserSymbolTable( language, mode ); return table; } /** @@ -3011,7 +3012,7 @@ public class ParserSymbolTableTest extends TestCase { * } */ public void testPrefixLookup_Unqualified() throws Exception { - newTable(); + newTable( ParserLanguage.CPP, ParserMode.COMPLETION_PARSE ); ISymbol aVar = table.newSymbol( "aVar", TypeInfo.t_int ); table.getCompilationUnit().addSymbol( aVar ); @@ -3042,7 +3043,7 @@ public class ParserSymbolTableTest extends TestCase { * d.a(CTRL+SPACE) */ public void testPrefixLookup_Qualified() throws Exception { - newTable(); + newTable( ParserLanguage.CPP, ParserMode.COMPLETION_PARSE ); ISymbol aVar = table.newSymbol( "aVar", TypeInfo.t_int ); table.getCompilationUnit().addSymbol( aVar ); @@ -3082,7 +3083,7 @@ public class ParserSymbolTableTest extends TestCase { * @throws Exception */ public void testPrefixLookup_Inheritance() throws Exception { - newTable(); + newTable( ParserLanguage.CPP, ParserMode.COMPLETION_PARSE ); IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); table.getCompilationUnit().addSymbol( A ); @@ -3143,7 +3144,7 @@ public class ParserSymbolTableTest extends TestCase { * @throws Exception */ public void testPrefixLookup_Ambiguities() throws Exception{ - newTable(); + newTable( ParserLanguage.CPP, ParserMode.COMPLETION_PARSE ); ISymbol aa = table.newSymbol( "aa", TypeInfo.t_int ); table.getCompilationUnit().addSymbol( aa ); @@ -3288,7 +3289,7 @@ public class ParserSymbolTableTest extends TestCase { * @throws Exception */ public void testPrefixFiltering() throws Exception{ - newTable(); + newTable( ParserLanguage.CPP, ParserMode.COMPLETION_PARSE ); IDerivableContainerSymbol a1 = table.newDerivableContainerSymbol( "a1", TypeInfo.t_struct ); table.getCompilationUnit().addSymbol( a1 ); diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog-parser b/core/org.eclipse.cdt.core/parser/ChangeLog-parser index ebc0b755c83..b2d2f4248f4 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog-parser +++ b/core/org.eclipse.cdt.core/parser/ChangeLog-parser @@ -1,3 +1,8 @@ +2004-01-15 Andrew Niefer + Modified symbol table constructor to take a ParseMode as a parameter. + Modified symbol table to use a TreeMap instead of HashMap when ParseMode is CONTEXTUAL_PARSE + Modified ASTNode.lookup to throw ASTNotImplementedException if called when ParseMode is not CONTEXTUAL_PARSE + 2004-01-15 Hoda Amer 2004-01-15 John Camelon diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ParserFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ParserFactory.java index fb2a283506a..69f27b82b09 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ParserFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ParserFactory.java @@ -37,7 +37,7 @@ public class ParserFactory { if( mode == ParserMode.QUICK_PARSE ) return new QuickParseASTFactory(); else - return new CompleteParseASTFactory( language ); + return new CompleteParseASTFactory( language, mode ); } public static IParser createParser( IScanner scanner, ISourceElementRequestor callback, ParserMode mode, ParserLanguage language, IParserLogService log ) throws ParserFactoryError diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ast/IASTNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ast/IASTNode.java index 34aba1197e6..e7add950bfe 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ast/IASTNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ast/IASTNode.java @@ -66,6 +66,6 @@ public interface IASTNode { * @return * @throws LookupException */ - public ILookupResult lookup( String prefix, LookupKind[] kind, IASTNode context) throws LookupException; + public ILookupResult lookup( String prefix, LookupKind[] kind, IASTNode context) throws LookupException, ASTNotImplementedException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ContextualParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ContextualParser.java index 8531c2843f7..c1abcc8a9da 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ContextualParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ContextualParser.java @@ -51,7 +51,7 @@ public class ContextualParser extends Parser implements IParser { */ public ContextualParser(IScanner scanner, ISourceElementRequestor callback, ParserLanguage language, IParserLogService log) { super(scanner, callback, language, log); - astFactory = ParserFactory.createASTFactory( ParserMode.COMPLETE_PARSE, language); + astFactory = ParserFactory.createASTFactory( ParserMode.COMPLETION_PARSE, language); scanner.setASTFactory(astFactory); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/ASTNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/ASTNode.java index 0b5883cb78d..dfc49a641a8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/ASTNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/ASTNode.java @@ -14,6 +14,8 @@ import java.util.Iterator; import java.util.List; import java.util.ListIterator; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.core.parser.ast.ASTNotImplementedException; import org.eclipse.cdt.core.parser.ast.IASTNode; import org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol; import org.eclipse.cdt.internal.core.parser.pst.ISymbol; @@ -31,7 +33,8 @@ public class ASTNode implements IASTNode { /* (non-Javadoc) * @see org.eclipse.cdt.core.parser.ast.IASTNode#lookup(java.lang.String, org.eclipse.cdt.core.parser.ast.IASTNode.LookupKind, org.eclipse.cdt.core.parser.ast.IASTNode) */ - public ILookupResult lookup(String prefix, LookupKind[] kind, IASTNode context) throws LookupException { + public ILookupResult lookup(String prefix, LookupKind[] kind, IASTNode context) throws LookupException, ASTNotImplementedException { + if( ! ( this instanceof ISymbolOwner ) || ( context != null && !(context instanceof ISymbolOwner) ) ){ return null; } @@ -39,6 +42,10 @@ public class ASTNode implements IASTNode { IContainerSymbol thisContainer = (IContainerSymbol) ((ISymbolOwner)this).getSymbol(); IContainerSymbol qualification = null; + if( thisContainer.getSymbolTable().getParserMode() != ParserMode.COMPLETION_PARSE ){ + throw new ASTNotImplementedException(); + } + if( context != null ){ ISymbol sym = (IContainerSymbol) ((ISymbolOwner)context).getSymbol(); if( sym == null || !(sym instanceof IContainerSymbol) ){ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java index 46c31360677..02e13ca50cf 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java @@ -20,6 +20,7 @@ import org.eclipse.cdt.core.parser.Enum; import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.ITokenDuple; import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; import org.eclipse.cdt.core.parser.ast.ASTClassKind; import org.eclipse.cdt.core.parser.ast.ASTNotImplementedException; @@ -115,11 +116,11 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto } } - public CompleteParseASTFactory( ParserLanguage language ) + public CompleteParseASTFactory( ParserLanguage language, ParserMode mode ) { super(); - pst = new ParserSymbolTable( language ); + pst = new ParserSymbolTable( language, mode ); } /* 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 a0011d30c3c..5e3769c8e13 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 @@ -14,6 +14,7 @@ package org.eclipse.cdt.internal.core.parser.pst; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -21,7 +22,9 @@ import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.TreeMap; +import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; import org.eclipse.cdt.core.parser.ast.IASTMember; import org.eclipse.cdt.core.parser.ast.IASTNode; @@ -51,9 +54,13 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { public Object clone(){ ContainerSymbol copy = (ContainerSymbol)super.clone(); - copy._usingDirectives = ( _usingDirectives != null ) ? (LinkedList) _usingDirectives.clone() : null; - copy._containedSymbols = ( _containedSymbols != null )? (HashMap) _containedSymbols.clone() : null; - + copy._usingDirectives = ( _usingDirectives != null ) ? (LinkedList) _usingDirectives.clone() : null; + + if( getSymbolTable().getParserMode() == ParserMode.COMPLETION_PARSE ) + copy._containedSymbols = ( _containedSymbols != null )? (Map)((TreeMap) _containedSymbols).clone() : null; + else + copy._containedSymbols = ( _containedSymbols != null )? (Map)((HashMap) _containedSymbols).clone() : null; + return copy; } @@ -118,7 +125,6 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { origList.add( origDecl ); origList.add( obj ); - declarations.remove( origDecl ); declarations.put( obj.getName(), origList ); } else { origList.add( obj ); @@ -264,7 +270,12 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { */ public Map getContainedSymbols(){ if( _containedSymbols == null ){ - _containedSymbols = new HashMap(); + if( getSymbolTable().getParserMode() == ParserMode.COMPLETION_PARSE ){ + _containedSymbols = new TreeMap( new SymbolTableComparator() ); + } else { + _containedSymbols = new HashMap( ); + } + } return _containedSymbols; } @@ -760,7 +771,6 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { } } if( list.size() == 1 ){ - _context.getContainedSymbols().remove( _symbol.getName() ); _context.getContainedSymbols().put( _symbol.getName(), list.getFirst() ); } } else if( obj instanceof BasicSymbol ){ @@ -786,8 +796,22 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { private IContainerSymbol _decl; private IContainerSymbol _namespace; } - + + static protected class SymbolTableComparator implements Comparator{ + public int compare( Object o1, Object o2 ){ + int result = ((String) o1).compareToIgnoreCase( (String) o2 ); + if( result == 0 ){ + return ((String) o1).compareTo( (String) o2 ); + } + return result; + } + + public boolean equals( Object obj ){ + return ( obj instanceof SymbolTableComparator ); + } + } + private LinkedList _usingDirectives; //collection of nominated namespaces - private HashMap _containedSymbols; //declarations contained by us. + private Map _containedSymbols; //declarations contained by us. } 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 20702b70150..ebc04793cbf 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 @@ -18,7 +18,9 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.TreeMap; +import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTable.Command; /** @@ -45,8 +47,12 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz ParameterizedSymbol copy = (ParameterizedSymbol)super.clone(); copy._parameterList = ( _parameterList != null ) ? (LinkedList) _parameterList.clone() : null; - copy._parameterMap = ( _parameterMap != null ) ? (HashMap) _parameterMap.clone() : null; + if( getSymbolTable().getParserMode() == ParserMode.COMPLETION_PARSE ) + copy._parameterMap = ( _parameterMap != null ) ? (Map) ((TreeMap) _parameterMap).clone() : null; + else + copy._parameterMap = ( _parameterMap != null ) ? (Map) ((HashMap) _parameterMap).clone() : null; + copy._argumentList = ( _argumentList != null ) ? (LinkedList) _argumentList.clone() : null; copy._specializations = ( _specializations != null ) ? (LinkedList) _specializations.clone() : null; @@ -142,7 +148,10 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz */ public Map getParameterMap(){ if( _parameterMap == null ){ - _parameterMap = new HashMap(); + if( getSymbolTable().getParserMode() == ParserMode.COMPLETION_PARSE ) + _parameterMap = new TreeMap( new SymbolTableComparator() ); + else + _parameterMap = new HashMap( ); } return _parameterMap; } @@ -282,7 +291,7 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz } private LinkedList _parameterList; //have my cake - private HashMap _parameterMap; //and eat it too + private Map _parameterMap; //and eat it too private LinkedList _specializations; //template specializations private LinkedList _argumentList; //template specialization arguments private ISymbol _returnType; 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 6d40ea458b7..b714b8af61d 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 @@ -22,9 +22,11 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Set; +import java.util.SortedMap; import org.eclipse.cdt.core.parser.Enum; import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; import org.eclipse.cdt.core.parser.ast.IASTMember; import org.eclipse.cdt.core.parser.ast.IASTNode; @@ -43,10 +45,11 @@ public class ParserSymbolTable { /** * Constructor for ParserSymbolTable. */ - public ParserSymbolTable( ParserLanguage language ) { + public ParserSymbolTable( ParserLanguage language, ParserMode mode ) { super(); _compilationUnit = newContainerSymbol( EMPTY_NAME, TypeInfo.t_namespace ); _language = language; + _mode = mode; } public IContainerSymbol getCompilationUnit(){ @@ -301,7 +304,15 @@ public class ParserSymbolTable { Map declarations = lookIn.getContainedSymbols(); - Iterator iterator = ( data.mode == LookupMode.PREFIX ) ? declarations.keySet().iterator() : null; + Iterator iterator = null; + if( data.mode == LookupMode.PREFIX ){ + if( declarations instanceof SortedMap ){ + iterator = ((SortedMap)declarations).tailMap( data.name.toLowerCase() ).keySet().iterator(); + } else { + throw new ParserSymbolTableException( ParserSymbolTableException.r_InternalError ); + } + } + String name = ( iterator != null && iterator.hasNext() ) ? (String) iterator.next() : data.name; while( name != null ) { @@ -312,6 +323,8 @@ public class ParserSymbolTable { if( obj != null ) found.put( name, obj ); + } else { + break; } if( iterator != null && iterator.hasNext() ){ @@ -328,7 +341,14 @@ public class ParserSymbolTable { if( lookIn instanceof IParameterizedSymbol ){ Map parameters = ((IParameterizedSymbol)lookIn).getParameterMap(); if( parameters != null ){ - iterator = ( data.mode == LookupMode.PREFIX ) ? parameters.keySet().iterator() : null; + iterator = null; + if( data.mode == LookupMode.PREFIX ){ + if( parameters instanceof SortedMap ){ + iterator = ((SortedMap) parameters).tailMap( data.name.toLowerCase() ).keySet().iterator(); + } else { + throw new ParserSymbolTableException( ParserSymbolTableException.r_InternalError ); + } + } name = ( iterator != null && iterator.hasNext() ) ? (String) iterator.next() : data.name; while( name != null ){ if( nameMatches( data, name ) ){ @@ -337,7 +357,10 @@ public class ParserSymbolTable { if( obj != null ){ found.put( name, obj ); } + } else { + break; } + if( iterator != null && iterator.hasNext() ){ name = (String) iterator.next(); } else { @@ -2184,7 +2207,8 @@ public class ParserSymbolTable { //private Stack _contextStack = new Stack(); private IContainerSymbol _compilationUnit; - private ParserLanguage _language; + private ParserLanguage _language; + private ParserMode _mode; private LinkedList undoList = new LinkedList(); private HashSet markSet = new HashSet(); @@ -2196,6 +2220,10 @@ public class ParserSymbolTable { return _language; } + public ParserMode getParserMode(){ + return _mode; + } + protected void pushCommand( Command command ){ undoList.addFirst( command ); } diff --git a/core/org.eclipse.cdt.ui/ChangeLog b/core/org.eclipse.cdt.ui/ChangeLog index f5641e15db9..91ad3780189 100644 --- a/core/org.eclipse.cdt.ui/ChangeLog +++ b/core/org.eclipse.cdt.ui/ChangeLog @@ -1,3 +1,6 @@ +2004-01-13 Andrew Niefer + Updated CompletionEngine to catch ASTNotImplementedException from IASTNode.lookup + 2004-01-15 Hoda Amer Moved Content Assist log to the UI plugin diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CompletionEngine.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CompletionEngine.java index fb65fc9950a..8294ff92478 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CompletionEngine.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CompletionEngine.java @@ -32,6 +32,7 @@ import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.core.parser.ParserUtil; import org.eclipse.cdt.core.parser.ScannerInfo; import org.eclipse.cdt.core.parser.ast.ASTClassKind; +import org.eclipse.cdt.core.parser.ast.ASTNotImplementedException; import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier; import org.eclipse.cdt.core.parser.ast.IASTCodeScope; import org.eclipse.cdt.core.parser.ast.IASTCompilationUnit; @@ -401,6 +402,10 @@ public class CompletionEngine implements RelevanceConstants{ // do we want to do something here? ilk.printStackTrace(); return null; + } catch (ASTNotImplementedException e) { + // shouldn't happen + e.printStackTrace(); + return null; } } private void completionOnMemberReference(IASTCompletionNode completionNode){